神经网络:利用C++实现前馈神经网络

来源:互联网 发布:python str 编辑:程序博客网 时间:2024/05/16 08:03

以下代码实现了只包含一个隐层的BP前馈神经网络。使用方法如下:

1.编写配置文件

配置文件为TXT文档,内容如下:

Layers: 3
Layer1: 2
Layer2: 2
Layer3: 2
Group: 1000
Groupt: 1000
Learningrate: 0.9
Accuracy: 0.95
iterations_outer: 100000
iter_show: 50000
xdata.txt
ydata.txt
xdata_t.txt
ydata_t.txt

其中Layers为神经网络的层数,由于只包含一个隐层,所以目前只能为3;
其后的Layer1~Layer3为各层神经元的数目;
Group为训练数据的组数;
Groupt为测试数据的组数;
Learningrate为学习率
Accuracy为设置的精度,暂时未用到
iterations_outer为训练迭代次数
iter_show为显示间隔
xdata.txt为训练用输入数据
ydata.txt为训练用输出数据
xdata_t.txt为测试用输入数据
ydata_t.txt为测试用输出数据

2.生成训练数据

用程序生成1000例训练数据以及1000例测试数据。随机产生0~10的随机数,保留两位小数。这里利用y=x这条直线将点分成两类,用1,0表示。也就是说输入数据是x,y;对应的输出是1
,0或者0,1向量。即输入层和输出层都有两个神经元,隐层神经元数目需要调试。
代码如下:

/*************************************************COPYRIGHT NOTICECopyright (c) 2016.10.19, GPHAll rights reserved.Description: 生成训练数据*************************************************/#include <stdio.h>#include <time.h>#include <fstream>using namespace std;/******************************************此函数计算设计的函数的返回值*******************************************/double compute(double x){    return x;}/******************************************此函数产生0到10之间的随机数,保留两位小数*******************************************/double random(void){    return rand() % 1001 / 100.0;}int main(int argc, char** argv){    srand((int)time(0));    ofstream xfile("xdata.txt");    ofstream yfile("ydata.txt");    double x, y;    x = random();    y = random();    if (y > compute(x))    {        xfile             << x            << endl << y;        yfile             << 1            << endl << 0;    }    else    {        xfile             << x            << endl << y;        yfile             << 0            << endl << 1;    }    for (int i = 1; i < 1000; i++)    {        x = random();        y = random();        if (y > compute(x))        {            xfile                 << endl << x                << endl << y;            yfile                 << endl << 1                << endl << 0;        }        else        {            xfile                << endl << x                << endl << y;            yfile                 << endl << 0                << endl << 1;        }    }    return 0;}
3.运行程序

函数定义了一个NN类进行处理,定义如下:

//定义神经元结构体typedef struct Neuron {    double output; //神经元输出    double treshold; // 神经元阈值    double weight[MaxNeuronNumber]; // 与上一层个神经元的连接权重向量    double g; // 梯度向量} Neuron;//定义NN类class NN {public:    int Layers; // 模型层数    int Layer[MaxLayerNumber]; // 各层神经元数目    int group_num; //训练数据组数    int groupt_num; //测试数据组数    double learningrate; // 学习率    double accuracy; // 准确率    int inLayernum; // 输入层神经元数目    int outLayernum; // 输出层神经元数目    string xfilename; // 训练数据x数据文件名    string yfilename; // 训练数据y数据文件名    string xtfilename; // 测试数据x数据文件名    string ytfilename; // 测试数据y数据文件名public:    int iterations_outer; // 循环次数    int iter_show; // 显示间隔public:    Neuron neuron[MaxNeuronNumber][MaxLayerNumber]; // 神经元定义public:    bool readmodel(char* modlefile); // 从模型文件中读入模型    bool getTraindata(void); // 从文本文件中读入训练数据    void initmodel(void); // 始化各层权值    void compute_g(int i_); // 根据一组输入计算各层输出以及梯度项    void compute_t(int i_); // 根据一组测试输入计算各层输出    void updateweights(int i_); // 更新权值};

主函数如下:

int main(int argc, char** argv) {    NN nn; // 定义类    // 读取模型设置    if (!nn.readmodel("model.txt")) {        cout << "Wrong model!\n";        system("pause");        return 0;    }    // 输出模型配置,等待确认    cout         << "模型配置如下(按空格键继续):\n"        << "Layers: " << nn.Layers << endl        << "Layer1: " << nn.Layer[0] << endl        << "Layer2: " << nn.Layer[1] << endl        << "Layer3: " << nn.Layer[2] << endl        << "Group: " << nn.group_num << endl        << "Groupt: " << nn.groupt_num << endl        << "xfile: " << nn.xfilename << endl        << "yfile: " << nn.yfilename << endl        << "xtfile: " << nn.xtfilename << endl        << "ytfile: " << nn.ytfilename << endl;    // 监听键盘按键,退出等待    while (1)    {        if (GetAsyncKeyState(' ') && 0x8000)        {            break;        }    }    // 获取数据    if (!nn.getTraindata())    {        system("pause");        return 0;    }    nn.initmodel(); // 初始化模型    int flag_count = 1;    bool flag_return = false;    int all = nn.iterations_outer * nn.group_num / 100;    // 开始训练    for (int i = 0; i < nn.iterations_outer; i++)    {        for (int g = 0; g < nn.group_num; g++)        {            nn.compute_g(g);// 计算梯度项            nn.updateweights(g); // 更新权重            flag_count++;            // 显示训练进度            if (flag_count > nn.iter_show)            {                flag_count = 1;                double y = 0, y6 = 0;                for (int j = 0; j < nn.outLayernum; j++)                {                    y += ydataarry[j][g];                    y6 += nn.neuron[j][nn.Layers - 1].output;                }                cout << "Iterations %" << (double)((i * nn.group_num + g) / all) << endl;            }            // 键盘终止训练            if (GetAsyncKeyState(VK_ESCAPE) && 0x8000)            {                flag_return = true;                cout << "Keyboard interrupt!\n";                break;            }        }        if (flag_return == true)            break;    }    // 开始测试    double count_right = 0;    flag_count = 1;    int i;    for (i = 0; i < nn.groupt_num; i++)    {        flag_count++;        nn.compute_t(i); // 根据输入计算模型输出        if ( (nn.neuron[0][nn.Layers - 1].output - nn.neuron[1][nn.Layers - 1].output) * (ytdataarry[0][i] - ytdataarry[1][i]) > 0 )        {            count_right++; // 输出正确则记录        }        // 显示进度        if (flag_count > nn.iter_show)        {            flag_count = 1;            cout << "Accuracy is %" << count_right * 100.0 / i << " at iteration %" << i * 100.0 / nn.groupt_num << endl;        }        // 键盘控制退出        if (GetAsyncKeyState(' ') && 0x8000)        {            flag_return = true;            cout << "Keyboard interrupt!\n";            break;        }    }    cout << "Accuracy is %" << count_right * 100.0 / i << " at iteration %" << i * 100.0 / nn.groupt_num << endl;    system("pause");    return 0;}// end for main()
4.附录

相关VS工程在这里下载。欢迎交流^_^

1 0
原创粉丝点击