声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 3163|回复: 3

[人工智能] BP神经网络源程序(VC++)

[复制链接]
发表于 2006-11-15 09:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
一个高精确度的神经网络算法

  1. #include "iostream.h"
  2. #include "iomanip.h"
  3. #include "stdlib.h"
  4. #include "math.h"
  5. #include "stdio.h"
  6. #include "time.h"
  7. #include "fstream.h"
  8. #define N 11 //学习样本个数
  9. #define IN 5 //输入层神经元数目
  10. #define HN 8 //隐层神经元数目
  11. #define HC 3 //隐层层数
  12. #define ON 3 //输出层神经元数目
  13. #define Z 200000 //旧权值保存-》每次study的权值都保存下来
  14. double P[IN]; //单个样本输入数据
  15. double T[ON]; //单个样本教师数据
  16. double U11[HN][IN]; //输入层至第一隐层权值
  17. double U12[HN][HN]; //第一隐层至第二隐层权值
  18. double U23[HN][HN]; //第二隐层至第三隐层权值
  19. double V[ON][HN]; //第三隐层至输出层权值
  20. double X1[HN]; //第一隐层的输入
  21. double X2[HN]; //第二隐层的输入
  22. double X3[HN]; //第三隐层的输入
  23. double Y[ON]; //输出层的输入
  24. double H1[HN]; //第一隐层的输出
  25. double H2[HN]; //第二隐层的输出
  26. double H3[HN]; //第三隐层的输出
  27. double O[ON]; //输出层的输出
  28. double YU_HN1[HN]; //第一隐层的阈值
  29. double YU_HN2[HN]; //第二隐层的阈值
  30. double YU_HN3[HN]; //第三隐层的阈值
  31. double YU_ON[ON]; //输出层的阈值
  32. double err_m[N]; //第m个样本的总误差
  33. double a; //学习效率
  34. double alpha;  //动量因子

  35. //定义一个放学习样本的结构
  36. struct {
  37. double input[IN]; //输入在上面定义是五个       
  38. double teach[ON]; //输出在上面定义是三个
  39. }Study_Data[N];//学习样本

  40. //bp算法用来保存每次计算的权值
  41. struct {
  42. double old_U11[HN][IN];  //保存输入层至隐层权值旧权
  43. double old_U12[HN][HN]; //保存第一隐层至第二隐层权值
  44. double old_U23[HN][HN]; //保存第二隐层至第三隐层权值
  45. double old_V[ON][HN];  //保存第三隐层至输出层旧权
  46. }Old_WV[Z];


  47. saveWV(int m)
  48. {
  49.         for(int i=0;i<HN;i++)
  50.         {
  51.                 for(int j=0;j<IN;j++)
  52.                 {
  53.                         Old_WV[m].old_U11[i][j] = U11[i][j];
  54.                 }
  55.         }

  56.         for(int i1=0;i1<HN;i1++)
  57.         {
  58.                 for(int j1=0;j1<HN;j1++)
  59.                 {
  60.                         Old_WV[m].old_U12[i1][j1] = U12[i1][j1];
  61.                 }
  62.         }

  63.         for(int i2=0;i2<HN;i2++)
  64.         {
  65.                 for(int j2=0;j2<HN;j2++)
  66.                 {
  67.                         Old_WV[m].old_U23[i2][j2] = U23[i2][j2];
  68.                 }
  69.         }
  70.         for(int i3=0;i3<ON;i3++)
  71.         {
  72.                 for(int j3=0;j3<HN;j3++)
  73.                 {
  74.                         Old_WV[m].old_V[i3][j3] = V[i3][j3];
  75.                 }
  76.         }
  77.         return 1;
  78. }
  79. ///////////////////////////
  80. //初始化权、阈值子程序/////
  81. ///////////////////////////
  82. initial()
  83. {
  84. //隐层权、阈值初始化//
  85.         srand( (unsigned)time( NULL ) );

  86.         for(int i=0;i<HN;i++)
  87.         {
  88.                 for(int j=0;j<IN;j++)
  89.                         U11[i][j]= (double)((rand()/32767.0)*2-1); //初始化输入层到第一隐层的权值,随机模拟0 和 1 -1       
  90.         }
  91.         for(int i1=0;i1<HN;i1++)
  92.         {
  93.                 for(int j1=0;j1<HN;j1++)
  94.                         U12[i1][j1]= (double)((rand()/32767.0)*2-1); //初始化第一隐层到第二隐层权值,随机模拟0 和 1 -1       
  95.         }
  96.         for(int i2=0;i2<HN;i2++)
  97.         {
  98.                 for(int j2=0;j2<HN;j2++)
  99.                         U23[i2][j2]= (double)((rand()/32767.0)*2-1); //初始化第二隐层到第三隐层权值,随机模拟0 和 1 -1       
  100.         }
  101.         for(int i3=0;i3<ON;i3++)
  102.         {
  103.                 for(int j3=0;j3<HN;j3++)
  104.                         V[i3][j3]= (double)((rand()/32767.0)*2-1); //初始化隐层到输出层的权值,随机模拟0 和 1 -1
  105.         }
  106.         for(int k=0;k<HN;k++)
  107.         {
  108.                 YU_HN1[k] = (double)((rand()/32767.0)*2-1);  //第一隐层阈值初始化 ,-0.01 ~ 0.01 之间
  109.         }
  110.         for(int k1=0;k1<HN;k1++)
  111.         {
  112.                 YU_HN2[k] = (double)((rand()/32767.0)*2-1);  //第二隐层阈值初始化 ,-0.01 ~ 0.01 之间
  113.         }
  114.     for(int k2=0;k2<HN;k2++)
  115.         {
  116.                 YU_HN3[k] = (double)((rand()/32767.0)*2-1);  //第三隐层阈值初始化 ,-0.01 ~ 0.01 之间
  117.         }
  118.         for(int kk=0;kk<ON;kk++)
  119.         {
  120.                 YU_ON[kk] = (double)((rand()/32767.0)*2-1); //输出层阈值初始化 ,-0.01 ~ 0.01 之间
  121.         }
  122.   return 1;
  123. }//子程序initial()结束


  124. ////////////////////////////////
  125. ////第m个学习样本输入子程序///
  126. ///////////////////////////////
  127. input_P(int m)
  128. {
  129. for (int i=0;i<IN;i++)
  130. P[i]=Study_Data[m].input[i];
  131. //获得第m个样本的数据
  132. return 1;
  133. }//子程序input_P(m)结束

  134. /////////////////////////////
  135. ////第m个样本教师信号子程序//
  136. /////////////////////////////
  137. input_T(int m)
  138. {
  139. for (int k=0;k<ON;k++)
  140. T[k]=Study_Data[m].teach[k];
  141. return 1;
  142. }//子程序input_T(m)结束


  143. /////////////////////////////////
  144. //隐层各单元输入、输出值子程序///
  145. /////////////////////////////////
  146. H_I_O()
  147. {
  148. double sigma1,sigma2,sigma3;
  149. int i,i1,i2,j,j1,j2;
  150. for (j=0;j<HN;j++)
  151. {
  152. sigma1=0.0;
  153.         for (i=0;i<IN;i++)
  154.                 sigma1+=U11[j][i]*P[i];//求第一隐层内积
  155.                
  156. X1[j]=sigma1 - YU_HN1[j];//求第一隐层净输入
  157. H1[j]=1.0/(1.0+exp(-X1[j]));//求第一隐层输出sigmoid算法
  158. }
  159. for (j1=0;j1<HN;j1++)
  160. {
  161. sigma2=0.0;
  162.         for (i1=0;i1<HN;i1++)
  163.                 sigma2+=U12[j1][i1]*H1[i];//求第二隐层内积
  164.                
  165. X2[j]=sigma2 - YU_HN2[j];//求第二隐层净输入
  166. H2[j]=1.0/(1.0+exp(-X2[j]));//求第二隐层输出sigmoid算法
  167. }
  168. for (j2=0;j2<HN;j2++)
  169. {
  170. sigma3=0.0;
  171.         for (i2=0;i2<HN;i2++)
  172.                 sigma3+=U23[j2][i2]*H2[i];//求第三隐层内积
  173.                
  174. X3[j]=sigma3 - YU_HN3[j];//求第三隐层净输入
  175. H3[j]=1.0/(1.0+exp(-X3[j]));//求第三隐层输出sigmoid算法
  176. }
  177. return 1;
  178. }//子程序H_I_O()结束


  179. ///////////////////////////////////
  180. //输出层各单元输入、输出值子程序///
  181. ///////////////////////////////////
  182. O_I_O()
  183. {
  184. double sigma;
  185. for (int k=0;k<ON;k++)
  186. {
  187. sigma=0.0;
  188. for (int j=0;j<HN;j++)
  189. {
  190. sigma+=V[k][j]*H3[k];//求输出层内积
  191. }
  192. Y[k]=sigma-YU_ON[k]; //求输出层净输入
  193. O[k]=1.0/(1.0+exp(-Y[k]));//求输出层输出
  194. }
  195. return 1;
  196. }//子程序O_I_O()结束


  197. ////////////////////////////////////
  198. //输出层至隐层的一般化误差子程序////
  199. ////////////////////////////////////
  200. double d_err[ON];
  201. Err_O_H(int m)
  202. {
  203. double abs_err[ON];//每个样本的绝对误差都是从0开始的
  204. double sqr_err=0;//每个样本的平方误差计算都是从0开始的
  205. for (int k=0;k<ON;k++)
  206. {
  207.   abs_err[k]=T[k]-O[k];
  208. //求第m个样本下的第k个神经元的绝对误差
  209. sqr_err+=(abs_err[k])*(abs_err[k]);//求第m个样本下输出层的平方误差
  210. d_err[k]=abs_err[k]*O[k]*(1.0-O[k]);//d_err[k]输出层各神经元的一般化误差
  211. }
  212. err_m[m]=sqr_err/2;//第m个样本下输出层的平方误差/2=第m个样本的均方误差
  213. return 1;
  214. }//子程序Err_O_H(m)结束


  215. ////////////////////////////////////
  216. //隐层至输入层的一般化误差子程序////
  217. ////////////////////////////////////
  218. double e_err3[HN];//定义第三隐层各神经元的一般化误差
  219. double e_err2[HN];//定义第二隐层各神经元的一般化误差
  220. double e_err1[HN];//定义第一隐层各神经元的一般化误差
  221. Err_H_I()
  222. {
  223. double sigma3,sigma2,sigma1;
  224. for (int j3=0;j3<HN;j3++)
  225. {
  226.   sigma3=0.0;
  227.   for (int k3=0;k3<ON;k3++)
  228.   {
  229.       sigma3=d_err[k3]*V[k3][j3];
  230.   }
  231.   e_err3[j3]=sigma3*H3[j3]*(1-H3[j3]);//第三隐层各神经元的一般化误差
  232. }
  233. for (int j2=0;j2<HN;j2++)
  234. {
  235.   sigma2=0.0;
  236.   for (int k2=0;k2<HN;k2++)
  237.   {
  238.       sigma2=d_err[k2]*V[k2][j2];
  239.   }
  240.   e_err2[j2]=sigma2*H2[j2]*(1-H2[j2]);//第二隐层各神经元的一般化误差
  241. }
  242. for (int j1=0;j1<HN;j1++)
  243. {
  244.   sigma1=0.0;
  245.   for (int k1=0;k1<HN;k1++)
  246.   {
  247.       sigma1=d_err[k1]*V[k1][j1];
  248.   }
  249.   e_err1[j1]=sigma1*H1[j1]*(1-H1[j1]);//第一隐层各神经元的一般化误差
  250. }
  251. return 1;
  252. }//子程序Err_H_I()结束


  253. ////////////////////////////////////////////////////////
  254. //输出层至第三隐层的权值调整、输出层阈值调整计算子程序//////
  255. ////////////////////////////////////////////////////////
  256. Delta_O_H3(int m,int n)
  257. {
  258. if(n<=1)
  259. {
  260.         for (int k=0;k<ON;k++)
  261.         {
  262.                 for (int j=0;j<HN;j++)
  263.                 {
  264.                         V[k][j]=V[k][j]-a*d_err[k]*H3[j];//输出层至第三隐层的权值调整
  265.                 }
  266.             YU_ON[k]-=a*d_err[k];//输出层阈值调整
  267.         }
  268. }
  269. else if(n>1)
  270. {
  271.         for (int k=0;k<ON;k++)
  272.         {
  273.                 for (int j=0;j<HN;j++)
  274.                 {
  275.                         V[k][j]=V[k][j]+a*d_err[k]*H3[j]+alpha*(V[k][j]-Old_WV[(n-1)].old_V[k][j]);//输出层至隐层的权值调整
  276.                 }
  277.             YU_ON[k]-=a*d_err[k];//输出层至隐层的阈值调整
  278.         }
  279. }
  280. return 1;
  281. }//子程序Delta_O_H3()结束



  282. ///////////////////////////////////////////////////////////////
  283. //第三隐层至第二隐层的权值调整、第三隐层阈值调整计算子程序/////
  284. ///////////////////////////////////////////////////////////////
  285. Delta_H3_H2(int m,int n)
  286. {
  287. if(n<=1)
  288. {
  289.         for (int k=0;k<HN;k++)
  290.         {
  291.                 for (int j=0;j<HN;j++)
  292.                 {
  293.                         U23[k][j]=U23[k][j]-a*e_err3[k]*H2[j];//第二隐层至第三隐层层的权值调整
  294.                 }
  295.             YU_HN3[k]-=a*e_err3[k];//第三隐层阈值调整
  296.         }
  297. }               
  298. else if(n>1)
  299. {
  300.         for (int k=0;k<HN;k++)
  301.         {
  302.                 for (int j=0;j<HN;j++)
  303.                 {
  304.                    U23[k][j]=U23[k][j]+a*e_err3[k]*H2[j]+alpha*(U23[k][j]-Old_WV[(n-1)].old_U23[k][j]);//第二隐层至第三隐层层的权值调整
  305.                 }
  306.             YU_HN3[k]-=a*e_err3[k];//第三隐层阈值调整
  307.         }
  308. }
  309. return 1;
  310. }//子程序Delta_H3_H2()结束


  311. ///////////////////////////////////////////////////////////////
  312. //第二隐层至第一隐层的权值调整、第二隐层阈值调整计算子程序/////
  313. ///////////////////////////////////////////////////////////////
  314. Delta_H2_H1(int m,int n)
  315. {
  316. if(n<=1)
  317. {
  318.         for (int k=0;k<HN;k++)
  319.         {
  320.                 for (int j=0;j<HN;j++)
  321.                 {
  322.                         U12[k][j]=U12[k][j]-a*e_err2[k]*H1[j];//第一隐层至第二隐层层的权值调整
  323.                 }
  324.             YU_HN2[k]-=a*e_err2[k];//第二隐层阈值调整
  325.         }
  326. }               
  327. else if(n>1)
  328. {
  329.         for (int k=0;k<HN;k++)
  330.         {
  331.                 for (int j=0;j<HN;j++)
  332.                 {
  333.                    U12[k][j]=U12[k][j]+a*e_err2[k]*H1[j]+alpha*(U12[k][j]-Old_WV[(n-1)].old_U12[k][j]);//第一隐层至第二隐层层的权值调整
  334.                 }
  335.             YU_HN2[k]-=a*e_err2[k];//第二隐层阈值调整
  336.         }
  337. }
  338. return 1;
  339. }//子程序Delta_H2_H1()结束


  340. /////////////////////////////////////////////////////////////
  341. //第一隐层至输入层的权值调整、第一隐层阈值调整计算子程序/////
  342. /////////////////////////////////////////////////////////////
  343. Delta_H1_I(int m,int n)
  344. {

  345. if(n<=1)
  346. {
  347.         for (int j=0;j<HN;j++)
  348.         {
  349.                 for (int i=0;i<IN;i++)
  350.                 {
  351.                         U11[j][i]=U11[j][i]+a*e_err1[j]*P[i];//第一隐层至输入层的权值调整
  352.                 }
  353.         YU_HN1[j]+=a*e_err1[j];//第一隐层阈值调整
  354.         }
  355. }
  356. else if(n>1)
  357. {
  358.         for (int j=0;j<HN;j++)
  359.         {
  360.                 for (int i=0;i<IN;i++)
  361.                 {
  362.                         U11[j][i]=U11[j][i]+a*e_err1[j]*P[i]+alpha*(U11[j][i]-Old_WV[(n-1)].old_U11[j][i]);//第一隐层至输入层的权值调整
  363.                 }
  364.         YU_HN1[j]+=a*e_err1[j];//第一隐层阈值调整
  365.         }
  366. }
  367. return 1;
  368. }//子程序Delta_H1_I()结束



  369. /////////////////////////////////
  370. //N个样本的全局误差计算子程序////
  371. /////////////////////////////////
  372. double Err_Sum()
  373. {
  374. double total_err=0;
  375. for (int m=0;m<N;m++)
  376. {
  377.   total_err+=err_m[m];//每个样本的均方误差加起来就成了全局误差
  378. }
  379. return total_err;
  380. }//子程序Err_sum()结束



  381. GetTrainingData()
  382. {
  383.         ifstream GetTrainingData ( "训练样本.txt", ios::in );

  384.         for(int m=0;m<N;m++)
  385.         {
  386.                 for(int i=0;i<IN;i++)
  387.                 {
  388.                         GetTrainingData>>Study_Data[m].input[i];  //取得输入数据
  389.                 }
  390.                 for(int j=0;j<ON;j++)
  391.                 {
  392.                         GetTrainingData>>Study_Data[m].teach[j];  //取得输出数据
  393.                 }
  394.         }

  395.         GetTrainingData.close();
  396.         return 1;
  397. }


  398. void savequan()
  399. {
  400.         ofstream outQuanFile( "权值.txt", ios::out );
  401.         ofstream outYuFile( "阈值.txt", ios::out );
  402.         outQuanFile<<"A\n";
  403.         for(int i=0;i<HN;i++)
  404.         {
  405.                 for(int j=0;j<IN;j++)
  406.                 {
  407.                         outQuanFile<<U11[i][j]<<"   ";
  408.                 }
  409.                 outQuanFile<<"\n";

  410.         }//取得输入层至第一隐层权值
  411.         outQuanFile<<"B\n";
  412.         for(int i1=0;i1<HN;i1++)
  413.         {
  414.                 for(int j1=0;j1<HN;j1++)
  415.                 {
  416.                         outQuanFile<<U12[i1][j1]<<"   ";
  417.                 }
  418.                 outQuanFile<<"\n";
  419.         }//取得第一隐层至第二隐层权值
  420.         outQuanFile<<"C\n";
  421.         for(int i2=0;i2<HN;i2++)
  422.         {
  423.                 for(int j2=0;j2<HN;j2++)
  424.                 {
  425.                         outQuanFile<<U23[i2][j2]<<"   ";
  426.                 }
  427.                 outQuanFile<<"\n";

  428.         }//取得第二隐层至第三隐层权值
  429.         outQuanFile<<"D\n";
  430.         for(int i3=0;i3<ON;i3++)
  431.         {
  432.                 for(int j3=0;j3<HN;j3++)
  433.                 {
  434.                         outQuanFile<<V[i3][j3]<<"   ";
  435.                 }
  436.                 outQuanFile<<"\n";
  437.         }//取得第三隐层至输出层权值
  438.         outYuFile<<"\n第一隐层的阈值为:\n";
  439.         for(int k1=0;k1<HN;k1++)
  440.         {
  441.                 outYuFile<<YU_HN1[k1]<<"  ";  //隐层阈值写入文本
  442.         }
  443.         outYuFile<<"\n第二隐层的阈值为:\n";
  444.         for(int k2=0;k2<HN;k2++)
  445.         {
  446.                 outYuFile<<YU_HN2[k2]<<"  ";  //隐层阈值写入文本
  447.         }
  448.         outYuFile<<"\n第三隐层的阈值为:\n";
  449.         for(int k3=0;k3<HN;k3++)
  450.         {
  451.                 outYuFile<<YU_HN3[k3]<<"  ";  //隐层阈值写入文本
  452.         }
  453.         outYuFile<<"输出层的阈值为:\n";
  454.         for(int k=0;k<ON;k++)
  455.         {
  456.                 outYuFile<<YU_ON[k]<<"  ";  //输出层阈值写入文本
  457.         }
  458.         outQuanFile.close();
  459. }
  460. /**********************/
  461. /**程序入口,即主程序**/
  462. /**********************/
  463. void main()
  464. {

  465. double sum_err;
  466. int study;//训练次数
  467. double a = 0.6;//学习速率,即步长
  468. double alpha = 0.8;  //动量因子
  469. study=0; //学习次数
  470. double Pre_error ; //预定误差
  471. Pre_error = 0.0001;
  472. int Pre_times;
  473. Pre_times = 200;
  474. GetTrainingData();//输入样本 (1)
  475. initial(); //隐层、输出层权、阈值初始化  (2)
  476. do
  477. {
  478. ++study;
  479. for (int m=0;m<N;m++)
  480. {
  481. input_P(m); //输入第m个学习样本
  482. input_T(m);//输入第m个样本的教师信号
  483. H_I_O(); //第m个学习样本隐层各神经元输入、输出值
  484. O_I_O(); //第m个学习样本输出层各神经元输入、输出值 (3)
  485. Err_O_H(m); //第m个学习样本输出层至隐层一般化误差  
  486. Err_H_I(); //第m个学习样本隐层至输入层一般化误差 (4)
  487. Delta_O_H3(m,study); //第m个学习样本输出层至第三隐层权值、阈值调整、修改
  488. Delta_H3_H2(m,study); //第m个学习样本第三隐层至第二隐层的权值、阈值调整、修改
  489. Delta_H2_H1(m,study); //第m个学习样本第二隐层至第一隐层的权值、阈值调整、修改
  490. Delta_H1_I(m,study); //第m个学习样本第一隐层至输入层的权值、阈值调整、修改  (5)  
  491. } //全部样本训练完毕
  492. sum_err=Err_Sum(); //全部样本全局误差计算  
  493. saveWV(study);  //把本次的学习权值全保存到数组
  494. cout<<"第"<<study<<"次学习的均方误差为"<<sum_err<<endl;
  495. }while (sum_err > Pre_error);           //  (6)
  496. cout<<"网络已经学习了"<<study<<"次,学习的均方误差为"<<sum_err<<endl;
  497. savequan();
  498. }
复制代码
回复
分享到:

使用道具 举报

发表于 2007-8-30 16:47 | 显示全部楼层
不错,有些启发...
发表于 2007-9-3 09:42 | 显示全部楼层
谢谢
发表于 2007-9-3 12:53 | 显示全部楼层
很有启发,其实只有自己编写程序了,才能对算法有深切的理解!!!感谢楼主的贡献!
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-11-10 22:18 , Processed in 0.070648 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表