栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 实现的 BP神经网络 验证MNIST数据集

C/C++/C# 更新时间:发布时间: 百科书网 趣学号

程序说明:

        1.该程序的正向传递函数为:forward_propagation();

        2.该程序的反向传递函数可以使用两种方法:

                2.1:方法一:使用 backward_propagation() ;

                2.2:方法二:先使用 calcu_delta() 函数计算出偏导 delta,紧接着使用 backward_propagation_use_delta();

                2.3:说明:方法一代码比较容易阅读,按照反向传递公式一次性更新,但运行速度慢,因为在更新过程中存在大量重复运算;

                                   方法二运行速度快,将需要重复运算的delta偏导值先运算出来保存在数组中,然后再利用数组中的值来更新各个参数,减少了运算次数,速率可以提高3-4倍;

        3.show_pic_info()方法用来显示一个图片的信息,并且进行了重载,如下图所示:

        

        4.程序运行截图:(该程序会输出测试用例最后五张图片的信息,在程序中可以修改)

         5.程序代码(MNIST数据集请自行下载并且放在源文件同目录下),编辑器为codeblocks,编译器为codeblocks自带的GUN GCC Complier,移步GitHub。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int input_node_num = 784 ;    //输入节点数量
const int hidden_node_num = 100 ;   //隐层节点数量
const int output_node_num = 10 ;    //输出节点数量
const double learning_rate = 0.35 ; //学习率

int input_layer[input_node_num] ;   //输入层
double hidden_layer_output[hidden_node_num] ;   //隐藏层
int output_layer_target[output_node_num] ;  //输出层正确参考数据
double output_layer_real[output_node_num] ; //输出层真实输出数据


double input_hidden_weight[input_node_num][hidden_node_num] ;   //输入层 -> 隐藏层 权重
double hidden_output_weight[hidden_node_num][output_node_num] ; //隐藏层 -> 输出层 权重

double hidden_bias[hidden_node_num] ;   //隐藏层 偏置
double output_bias[output_node_num] ;   //输出层 偏置

//计算delta改变量,可以减少运算次数,优化运行效率
double hidden_delta[hidden_node_num] ;  //隐藏层求变化量时须用到的delta偏导值
double output_delta[output_node_num] ;  //输出层求变化量时须用到的delta偏导值

void show_pic_info(int tag_value)   //显示图片信息,tag_value:正确数据
{
    cout<<"图像信息:"< 输出层 权重
    for(int i = 0; i < hidden_node_num; i++)
    {
        for(int j = 0; j < output_node_num; j++)
        {
           hidden_output_weight[i][j] =  hidden_output_weight[i][j] - (learning_rate * (output_layer_real[j] - output_layer_target[j]) * output_layer_real[j] * (1 - output_layer_real[j]) * hidden_layer_output[i]);
        }
    }
    //更新隐藏层bias值
    for(int i = 0; i < hidden_node_num; i++)
    {
        double delta_sum = 0.0 ;
        for(int j = 0 ;j < output_node_num; j++)
        {
            delta_sum = delta_sum + (output_layer_real[j] - output_layer_target[j]) * output_layer_real[j] * (1 - output_layer_real[j]) * hidden_output_weight[i][j];
        }
        hidden_bias[i] = hidden_bias[i] - learning_rate * delta_sum * hidden_layer_output[i] * (1 - hidden_layer_output[i]);
    }
    //更新 输入 -> 隐藏 权重值
    for(int i = 0; i < input_node_num; i++)
    {
        double delta_sum = 0.0 ;
        for(int j = 0; j < hidden_node_num; j++)
        {
            for(int k = 0; k < output_node_num; k++)
            {
                delta_sum = delta_sum + (output_layer_real[k] - output_layer_target[k]) * output_layer_real[k] * (1 - output_layer_real[k]) * hidden_output_weight[j][k];
            }
            delta_sum = delta_sum * hidden_layer_output[j] * (1 - hidden_layer_output[j]) * input_layer[i];
            input_hidden_weight[i][j] = input_hidden_weight[i][j] - learning_rate * delta_sum;
        }
    }
}
double get_randnum()    //获得随机0-1数
{
    return (rand() % 1000 * 0.001 - 0.5);
}
double get_random(int min,int max)      //获得指定随机数
{
     return ( rand() % (max - min + 1) ) + min ;
}
void initialize_bpnet()     //初始化网络
{
    srand((int)time(0) + rand());
    for(int i = 0; i < input_node_num; i++)
    {
        for(int j = 0; j < hidden_node_num; j++)
        {
            input_hidden_weight[i][j] = get_randnum() ;
        }
    }

    for(int i = 0; i < hidden_node_num; i++)
    {
        for(int j = 0; j < output_node_num ; j++)
        {
            hidden_output_weight[i][j] = get_randnum();
        }
    }

    for(int i = 0; i < hidden_node_num ; i++)
    {
        hidden_bias[i] = get_randnum();
    }

    for(int i = 0; i < hidden_node_num ; i++)
    {
        output_bias[i] = get_randnum();
    }
}
void training() //开始训练
{
    FILE* training_image;
    FILE* training_label;
    int training_count = 0;
    unsigned char image_buffer[784];    //保存图片信息
    unsigned char label_buffer[10];     //保存标签数据

    training_image = fopen("./train-images.idx3-ubyte", "rb");
    training_label = fopen("./train-labels.idx1-ubyte", "rb");
    if (training_image == NULL || training_label == NULL) {
		cout << "open training file error" << endl;
		exit(0);
	}

	int head_info[1000];    //读取出文件的头信息,该信息不参与计算
	fread(head_info,1,16,training_image);   //读取16字节头部信息
	fread(head_info,1,8,training_label);    //读取8字节头部信息

	cout<<"Training started..."< max_value)
			{
				max_value = output_layer_real[k];
				max_index = k;
			}
		}

		if (output_layer_target[max_index] == 1)    //判断正确输出的坐标位置是否一致
        {
			test_success_num ++;
		}

		test_num ++;

		if ((int)test_num % 1000 == 0)
        {
			cout << "测试数量: " << test_num << "  成功数量: " << test_success_num << endl;
		}
		if( test_num>=9995&&test_num<10000)
        {
             show_pic_info(target_value,max_index);
        }
	}
	cout << endl;
	cout << "成功率: " << test_success_num / test_num << endl;
}
int main()
{
    initialize_bpnet();
    training();
    testing();
    system("pause");
    return 0;
}

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/1034036.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号