影醉阏轩窗

衣带渐宽终不悔,为伊消得人憔悴。
扩大
缩小

神经网络从基础到改进+源程序

神经网络初步学习总结:(对神经网络的模型有一定的了解,如果从未接触有点看不懂)

第一点:以下是最简单的神经网络模型了

x:  输入参数

a0: 输入偏置

a1: 输入权重

b0: 隐藏层偏置

b1: 隐藏层输入权重

y:  隐藏层输入参数(经过激励函数的输出,下面会讲解激励函数)

Z:  隐藏层输出(经过激励的输出)

 

各个参数的展开式如下:不用介绍了,都很简单的函数,不懂得话去百度一些模型看看

 

 

 

 

激励函数:经过sigmoid()函数之后的数值,这是常见的分类函数。

          如果是用于函数逼近,使用Y = X 作为激励函数即可。

第二点:公式的相关介绍

首先明确梯度下降法:字面的理解是沿着切线的方向,可以更快更准确的找出最小值

                    我们使用这个规则只需要知道,梯度下降=偏导数,其中

                    偏导数=k*变化量  抓住这两个点,这是BP神经网络的核心之一

                    例如:  :比例系数,W:权值,E:误差

明白Delta学习规则:有监督的学习,是利用误差作为判断的标准。

                   形式:  y:隐藏层的输出

                                Z:实际输出,t:期望输出(实际值)

                   基于这个学习规则进行BP的反向调整权重,核心之二

结合上面两个公式Delta规则的误差作为标准,误差利用整体的平方可以减少误差波动的

                  影响下面为了计算方便多乘以一个1/2,求导之后消去,    

                 没意义只是为了计算方便:BP神经网络的权值和偏置调整就可以利用这

                 个公式,例如:  等等

 

神经网络的权值和偏置计算

  因为误差E和隐藏层偏置没有直接关系,

所以需要链式求偏导,返回去看一下模型的参数定义就知道了。

‚  因为误差E和输入层的输入数据没有直接联系,所以需要链式求偏导

很简单的链式求导,看一下高数就知道的。

剩下的公式大家自己推导吧。。。。这是核心之三

第三点:BP神经网络的改进

1.批量学习:顾名思义批量学习就是梯度成批量的计算, 总梯度的含义

          例如:批量数是10个样本,那就是W1的梯度是十个样本加起来。和一个一个        

          的计算是一样的,这里不过是选几个样本加起来求平均数而已。

2.遍历学习(在线):本文中使用的改进就是动量法,当前权值的更新需要上一次的和这一次   

          同时作用,达到平滑高效的作用。公式:,注意这

          里的是没有叠加的,因为上面w存在。是有叠加的,因为是所有的w项。核心之四

第四点:BP神经网络的程序

核心算法就是更新权值w和更新偏置b,参考了网上程序,但是基本都是有漏洞,可能没下载到好的程序吧,结合了部分网上历程还有一本书《神经网络在应用科学和工程中的应用-----从基本原理到复杂的模式识别》。我弄了一个星期,就是由于公式编写成代码出现很多问题,多细心一点可以减少很多未知的错误!!!

       BP神经网络下载

注意:看了Ng的视频,Sigmoid函数<tanh函数<ReLu函数<Leak ReLu函数

 

 

CPP文件:

  1 #include "BP.h"
  2 
  3 BP_network::BP_network()
  4 {
  5     srand((unsigned)time(NULL));
  6     memset(w, 0, sizeof(w));
  7     memset(b, 0, sizeof(b));
  8     memset(Yout, 0, sizeof(Yout));
  9     memset(DataIn, 0, sizeof(DataIn));
 10     memset(DataOut, 0, sizeof(DataOut));
 11     memset(dv, 0, sizeof(dv));
 12     memset(dw, 0, sizeof(dw));
 13 }
 14 
 15 BP_network::~BP_network()
 16 {
 17 
 18 }
 19 
 20 double BP_network::Random()
 21 {
 22     double Rand;
 23     Rand = (1.0*rand()) / (RAND_MAX + 1);
 24     return Rand;
 25 }
 26 //--------------写入数据-------------------//
 27 void BP_network::FwriteData()
 28 {
 29     FILE *fp1, *fp2;
 30     double data1 = 0.0, data2;
 31     if ((fp1 = fopen("G:\\in.txt", "w")) == NULL) printf("can't open in.txt");
 32     if ((fp2 = fopen("G:\\out.txt", "w")) == NULL) printf("can't open out.txt");
 33     for (int i = 0; i < SampleCount; i++)
 34     {
 35         //data1 = Random() % 1000 / 100;
 36         data1 = double(int(Random() * 1000) % 1000) / 100;
 37         data2 = double(int(Random() * 1000) % 1000) / 100;
 38         fprintf(fp1,"%lf %lf\n", data1, data2);
 39         data1 = data1 * data2;
 40         fprintf(fp2,"%lf \n", data1);
 41     }
 42     fclose(fp1);
 43     fclose(fp2);
 44 }
 45 //--------------读入数据-------------------//
 46 void BP_network::FreadData()
 47 {
 48     FILE *fp1, *fp2;
 49     if (((fp1 = fopen("G:\\in.txt", "r")) == NULL))
 50         printf("can't open in.txt");
 51     if((fp2 = fopen("G:\\out.txt", "r")) == NULL)
 52         printf("can't open in.txt");;
 53     for (int i = 0; i < SampleCount; i++)
 54     {
 55         for (int j = 0; j < InCount; j++)
 56         {
 57             fscanf(fp1, "%lf", &DataIn[i][j]);
 58         }
 59         fscanf(fp2, "%lf", &DataOut[i][0]);
 60     }
 61     fclose(fp1);
 62     fclose(fp2);
 63 }
 64 //---------归一化输入和输出的数值,随机化权值和偏置的值---------//
 65 //****************   对于隐藏层->输出层=w[i][j][k]     *************//
 66 //------------------  i:层数,j:输出层个数,k:隐藏层个数    ------//
 67 void BP_network::Init_network()
 68 {
 69     double InMax, InMin, OutMax, OutMin;
 70     InMax = DataIn[0][0];
 71     InMin = DataIn[0][0];
 72     OutMax = DataOut[0][0];
 73     OutMin = DataOut[0][0];
 74 
 75     for (int i = 0; i < SampleCount; i++)
 76     {
 77         for (int j = 0; j < InCount; j++)
 78         {
 79             InMax = InMax > DataIn[i][j] ? InMax : DataIn[i][j];
 80             InMin = InMin < DataIn[i][j] ? InMin : DataIn[i][j];
 81         }
 82         OutMax = OutMax > DataOut[i][0] ? OutMax : DataOut[i][0];
 83         OutMin = OutMin < DataOut[i][0] ? OutMin : DataOut[i][0];
 84     }
 85     for (int i = 0; i < SampleCount; i++)
 86     {
 87         for (int j = 0; j < InCount; j++)
 88         {
 89             DataIn[i][j] = (DataIn[i][j] - InMin + 1) / (InMax - InMin + 1);
 90         }
 91         DataOut[i][0] = (DataOut[i][0] - OutMin + 1) / (OutMax - OutMin + 1);
 92     }
 93     for (int j = 0; j < HiddenCount; j++)
 94     {
 95         //----------随机化W和B的值------------//
 96         for (int i = 0; i < LayerCount - 1; i++)
 97         {
 98             if (i == 0)//第一层
 99             {
100                 for (int k = 0; k < InCount; k++)  w[i][k][j] = 2 * (0.5 - Random());
101             }
102             if (i == 1)//第二层
103             {
104                 w[i][j][0] = 2 * (0.5 - Random());
105             }
106         }
107         b[0][j] = 1;//由于数比较少,不需要做循环,直接赋值
108         b[1][0] = 1;
109     }    
110     inMax = InMax;
111     inMin = InMin;
112     outMax = OutMax;
113     outMin = OutMin;
114 }
115 //---------激励函数输出----------//
116 void BP_network::DrivingOut(int m)
117 {
118     Yout[1][0] = 0.0;//!!!!!!!!!!!!!注释:未能清除数据,导致检查两天!!!!!!!!!!!!!!!!!!!!!
119     for (int j = 0; j < HiddenCount; j++)
120     {
121         Yout[0][j] = 0.0;
122         for (int k = 0; k < 2; k++)
123         {
124             Yout[0][j] += DataIn[m][k] * w[0][k][j];    
125         }
126         Yout[0][j] += b[0][j];
127         Yout[0][j] = Sigmoid(Yout[0][j]);
128         Yout[1][0] += Yout[0][j] * w[1][j][0];
129     }
130     Yout[1][0] += b[1][0];
131     Yout[1][0] = Sigmoid(Yout[1][0]);
132 }
133 //-----------对W和B进行调整---------------//
134 void BP_network::BackAdjust(int m)
135 {
136 #if 1//加动量法
137     double StudyRate = 0.0, f = 0.0;
138     double Sum = 0.0;
139     StudyRate = (Yout[1][0] - DataOut[m][0]) * Yout[1][0] * (1 - Yout[1][0]);
140     db0[1][0] = U1*db0[1][0] + (1 - U1)*B_Rate*StudyRate;
141     b[1][0] -= db0[1][0];
142     for (int i = 0; i < HiddenCount; i++)
143     {
144         dv[0][i] = U1*dv[0][i] + (1 - U1)*W_Rate * StudyRate * Yout[0][i];
145         w[1][i][0] -= dv[0][i];
146     }
147     for (int i = 0; i < HiddenCount; i++)
148     {
149         f = 0.0;
150         f = StudyRate * w[1][i][0] * Yout[0][i] * (1 - Yout[0][i]);//改正之后
151         for (int j = 0; j < InCount; j++)
152         {
153             dw[j][i] = U1*dw[j][i] + (1 - U1)*W_Rate * f * DataIn[m][j];
154             w[0][j][i] -= dw[j][i];
155         }
156         db1[0][i] = U1*db0[0][i] + (1 - U1)*B_Rate*f;
157         b[0][i] -= db1[0][i];
158     }
159 #endif
160 #if 0//网上找到的加了一点动量,但是程序不稳定
161     int i, j;
162     double t;
163     for (i = 0; i < HiddenCount; ++i)
164     {
165         t = 0;
166         for (j = 0; j < OutCount; ++j) {
167             t += (Yout[1][j] - DataOut[m][j])*w[1][i][j];
168             dv[i][j] = U1*dv[i][j] + (1-U1)*W_Rate*(Yout[1][j] - DataOut[m][j])*Yout[0][i];
169             w[1][i][j] -= dv[i][j];
170         }
171         for (j = 0; j < InCount; ++j) {
172             dw[j][i] = U1*dw[j][i] + (1 - U1)*W_Rate*t*Yout[0][i] * (1 - Yout[0][i])*DataIn[m][j];
173             w[0][j][i] -= dw[j][i];
174         }
175 }
176 #endif
177 #if 0//未加动量法
178     double StudyRate = 0.0, f = 0.0;
179     double Sum = 0.0;
180     StudyRate = ( Yout[1][0] - DataOut[m][0]) * Yout[1][0] * (1 - Yout[1][0]);
181     b[1][0] -= ETA_W*StudyRate;
182     for (int i = 0; i < HiddenCount; i++)  
183         w[1][i][0] -= W_Rate * StudyRate * Yout[0][i];
184     for (int i = 0; i < HiddenCount; i++)
185     {        
186         f = 0.0;
187         f = StudyRate * w[1][i][0] * Yout[0][i] * (1 - Yout[0][i]);//改正之后
188         for (int j = 0; j < InCount; j++)
189         {
190             w[0][j][i] -= W_Rate* f *DataIn[m][j];
191         }
192        b[0][i] -= ETA_B * f;
193     }
194 #endif
195 }
196 //-----------训练神经网络-----------------//
197 void BP_network::Train_network()
198 {
199     int Tcount = 0;
200     double e = 1.0;
201     while (Tcount<TrainCount && e>Accuracy)
202     {
203         e = 0;
204         for (int i = 0; i < SampleCount; i++)
205         {
206             DrivingOut(i);
207             e += fabs((Yout[1][0]-DataOut[i][0])/ DataOut[i][0]);
208             BackAdjust(i);
209         }
210         Tcount++;
211         e = e / SampleCount;
212         cout << "" << Tcount << "代精度为:" << e << endl;
213     }
214 }
215 
216 double BP_network::Calculate(double x, double y)
217 {
218     x = (x - inMin + 1) / (inMax - inMin + 1);
219     y = (y - inMin + 1) / (inMax - inMin + 1);
220 #if true
221     double sum = 0.0, Tout = 0.0;
222     for (int i = 0; i < HiddenCount; i++)
223     {
224         Yout[0][i] = w[0][0][i] * x + w[0][1][i] * y + b[0][i];
225         Yout[0][i] = Sigmoid(Yout[0][i]);
226         Tout += Yout[0][i] * w[1][i][0];
227     }
228     Tout += b[1][0];
229     Tout = Sigmoid(Tout);
230     return (Tout * (outMax - outMin + 1) + outMin - 1);
231 #endif
232 }
233 
234 double BP_network::Sigmoid(double t)
235 {
236     double sum;
237     sum = 1.0 / (1.0+exp(-t));
238     return sum;
239 }

 

H文件:

 1 #pragma once
 2 #define _CRT_SECURE_NO_WARNINGS
 3 
 4 #include <iostream>
 5 #include <vector>
 6 #include "time.h"
 7 #include "math.h"
 8 
 9 using namespace std;
10 
11 const int SampleCount = 820;//定义样本个数
12 const int InCount = 2;//输入神经元个数
13 const int OutCount = 1;//输出神经元个数
14 const int HiddenCount = 45;//隐藏层神经元个数
15 const int TrainCount = 6000;//训练次数
16 const int LayerCount = 3;//神经网络层数
17 const int NeuronMax = 45;//每层最多的神经元个数(也可以直接定义个数)
18 
19 const double U0 = 0.15;
20 const double U1 = 0.0;//0.15
21 const double W_Rate = 0.8;//权值调整率//0.8
22 const double B_Rate = 0.8;//阈值调整率
23 const double Accuracy = 0.01;
24 
25 #define ETA_W 0.2
26 #define ETA_B 0.1
27 
28 class BP_network
29 {
30 public:
31     BP_network();
32     ~BP_network();    
33     void FwriteData();
34     void FreadData();
35     void Init_network();
36     void Train_network();
37     double Calculate(double x, double y);
38 private:
39     double DataIn[SampleCount][InCount];//输入的数据
40     double DataOut[SampleCount][OutCount];//输出的数据
41     double w[LayerCount-1][HiddenCount][HiddenCount];//权值(定义的是最大范围,为了移植方便,用不完)
42     double b[LayerCount-1][NeuronMax];//偏置(第几层,第几个神经元,对应的下一的神经元)
43     double Yout[LayerCount-1][NeuronMax];//经过激励函数的输出
44     double inMax, outMax, inMin, outMin;
45     double dv[HiddenCount][HiddenCount], dw[HiddenCount][HiddenCount];
46     double db0[2][2], db1[HiddenCount][HiddenCount];
47 
48 
49     double Sigmoid(double t);
50     void DrivingOut(int i);
51     void BackAdjust(int t);
52     double Random();
53 };

main文件:

 1 #include "BP.h"
 2 
 3 int main(int argc, char*argv)
 4 {
 5     BP_network test;
 6     test.FwriteData();
 7     test.FreadData();
 8     test.Init_network();
 9     test.Train_network();
10     cout << test.Calculate(5,5);
11     while (1);return 0;
12 }

不训练直接使用文件:

注:这是没有经过测试,可能程序有点小Bug,主题思路是没问题的!

 1 //----@InData:    输入为一维的数据 
 2 //----@Weight:    权重
 3 //                []        :层数, 
 4 //                            [0]:      输入层到隐藏层的权重
 5 //                            [1]:      隐藏层到输出层的权重
 6 //                [][]    :每层个数
 7 //                            [0][i]:      输入层的个数
 8 //                            [1][h]:      隐藏层个数
 9 //                [][][]    :每层个数        
10 //                            [0][i][h]:隐藏层个数        
11 //                            [1][h][o]:输出层个数
12 //----@Bias:    偏置
13 //                [0][h]    :隐藏层偏置
14 //                [1][o]    :输出层偏置
15 //----@OutData:    输出为一维数据                        
16 void Calculate(double* InData,double*** Weight,double* Bias ,char* OutData)
17 {
18     double HidData[HiddenCount][OutCount],HidData_Temp=0;//HidData:存放临时隐藏层到输出层的数据,HidData_Temp:存放临时输入层到隐藏层的单个数据
19     unsigned char flag = 1;//加输出层偏置
20     for (char h = 0; h < HiddenCount; h++)
21     {
22         for(unsigned char i=0; i<sizeof(InData)/sizeof(double); i++)//单个隐藏层的输出
23         {
24             HidData_Temp += Weight[0][i][h] *InData[i];
25         }
26         HidData_Temp += Bias[0][h];
27         HidData_Temp = Sigmoid(HidData_Temp);
28         for(unsigned char o=0; o<sizeof(OutData)/sizeof(char); o++)//单个隐藏层对输出层的输出
29         {
30             HidData[h][o] = Weight[1][h][o]*HidData_Temp;
31             OutData[o] += HidData[h][o];
32             //OutData[o] = flag==1?(OutData[o]+Bias[1][o]):OutData[o];
33             if(flag) OutData[o]+=Bias[1][o];//只能加一次偏置,顾用标志位
34         }
35         flag=0;
36     }
37 }
38 //----@InData:    输入为一维的数据 
39 //----@MinMax:    数据最值
40 //                [0] :Maximun data
41 //                [1]    :Minimun data
42 //----@OutData:    输出为一维数据    
43 void Normlize(double* InDta,double* MinMax,double* OutData)
44 {
45     for(unsigned char i=0;i<sizeof(InData)/sizeof(double);i++)
46     {
47         OutData[i] = (InDta[i] - MinMax[0] + 1) / (MinMax[1] - MinMax[0] + 1);
48     }
49 }
50 //----Sigmoid函数
51 double Sigmoid(double t)
52 {
53     double sum;
54     sum = 1.0 / (1.0+exp(-t));
55     return sum;
56 }

 

 

posted on 2017-03-14 11:17  影醉阏轩窗  阅读(1635)  评论(0编辑  收藏  举报

导航

/* 线条鼠标集合 */ /* 鼠标点击求赞文字特效 */ //带头像评论