BP理论部分参考:http://blog.csdn.net/itplus/article/details/11022243

参考http://www.cnblogs.com/ronny/p/ann_02.html#!comments,结合BP算法的理论部分,可以真正理解了ANN。

代码部分我加了部分注释

  1. #include<vector>
  2. using namespace std;
  3.  
  4. //单个连接线
  5. class NNconnection
  6. {
  7. public:
  8. //两个索引,一个与该结点相连(前一层)的前一层结点的索引,
  9. //一个对应的权值索引在整个单层网络中权值向量中的索引
  10. unsigned weightIdx;
  11. unsigned neuralIdx;
  12. };
  13.  
  14. //单个神经元,包括一个输出和多个连接线
  15. class NNneural
  16. {
  17. public:
  18. double output;//输出
  19. vector<NNconnection> m_connection;
  20. };
  21.  
  22. //单层网络
  23. class NNlayer
  24. {
  25. public:
  26. NNlayer *preLayer;//该层网络的前一层
  27. NNlayer(){ preLayer = NULL; }
  28. vector<NNneural> m_neurals;//每层网络多个神经元
  29. vector<double> m_weights;//权值向量
  30. //加多少个神经元,及经前一层神经元的个数
  31. void addNeurals(unsigned num, unsigned preNumNeurals);
  32. //反向传播
  33. void backPropagate(vector<double>& ,vector<double>&,double);
  34.  
  35. };
  36.  
  37. class NeuralNetwork
  38. {
  39. private:
  40. unsigned nLayer;//网络层数
  41. vector<unsigned> nodes;//每层的结点数
  42. vector<double> actualOutput;//每次迭代的输出结果
  43. double etaLearningRate;//权值学习率
  44. unsigned iterNum;//迭代次数
  45. public:
  46. vector<NNlayer*>m_layers;//由多个单层网络组成
  47. //创建网络,第二个参数为[48,25,30],则表明该网络有三层,每层结点数分别为48,25,30
  48. void create(unsigned num_layers, unsigned *ar_nodes);
  49. void initializeNetwork();//初始化网络,包括权值设置等
  50.  
  51. void forwardCalculate(vector<double> &invect, vector<double> &outvect);//向前计算
  52.  
  53. void backPropagate(vector<double>& tVect, vector<double>& oVect);//反向传播
  54.  
  55. void train(vector<vector<double>>& inputVec, vector<vector<double>>& outputVec);//训练
  56.  
  57. void classifier(vector<vector<double>>& inputVec, vector<vector<double>>& outputVec);//分类
  58.  
  59. };
  60.  
  61. void NeuralNetwork::initializeNetwork()
  62. {
  63. //初始化网络,创建各层和各层结点,初始化权值
  64. // i为何如此定义?
  65. for (vector<NNlayer*>::size_type i = ; i != nLayer; i++)
  66. {
  67. NNlayer *ptrLayer = new NNlayer;
  68. if (i == )
  69. {
  70. ptrLayer->addNeurals(nodes[i], );//第一层之前的结点数为0
  71. }
  72. else
  73. {
  74. ptrLayer->preLayer = m_layers[i - ];
  75. //每个神经元的初值包括与前一层神经元的连接索引和该层权重索引
  76. ptrLayer->addNeurals(nodes[i], nodes[i - ]);
  77. //连结权重个数
  78. unsigned num_weights = nodes[i] * (nodes[i - ] + );//+bias
  79. //初始化权重
  80. for (vector<NNlayer*>::size_type k = ; k != num_weights; k++)
  81. {
  82.  
  83. ptrLayer->m_weights.push_back(0.05*rand() / RAND_MAX);//0~0.05
  84. }
  85. }
  86. m_layers.push_back(ptrLayer);
  87. }
  88. }
  89.  
  90. void NNlayer::addNeurals(unsigned num, unsigned preNumNeural)
  91. {
  92. for (vector<NNneural>::size_type i = ; i != num; i++)
  93. {
  94. NNneural sneural;
  95. sneural.output = ;
  96. for (vector<NNconnection>::size_type k = ; k != preNumNeural; k++)
  97. {
  98. NNconnection sconnection;
  99. //给该神经元加上连接索引和权值索引
  100. sconnection.weightIdx = i*(preNumNeural + ) + k;//加1给偏置留一个索引位置
  101. sconnection.neuralIdx = k;
  102. sneural.m_connection.push_back(sconnection);
  103. }
  104. m_neurals.push_back(sneural);
  105. }
  106. }
  107. void NeuralNetwork::forwardCalculate(vector<double> &invect, vector<double> &outvect)
  108. {
  109. actualOutput.clear();
  110. vector<NNlayer*>::iterator layerIt = m_layers.begin();
  111. while (layerIt != m_layers.end())
  112. {
  113. if (layerIt == m_layers.begin())
  114. {
  115. for (vector<NNneural>::size_type k = ; k != (*layerIt)->m_neurals.size(); k++)
  116. {
  117. //对第一层的神经元来说,输出即为输入
  118. (*layerIt)->m_neurals[k].output = invect[k];
  119. }
  120. }
  121. else
  122. {
  123. vector<NNneural>::iterator neuralIt = (*layerIt)->m_neurals.begin();
  124. int neuralIdx = ;
  125. while (neuralIt != (*layerIt)->m_neurals.end())
  126. {
  127. //每个神经元的连接线数
  128. vector<NNconnection>::size_type num_connection = (*neuralIt).m_connection.size();
  129. //偏置
  130. double dsum = (*layerIt)->m_weights[num_connection*(neuralIdx + ) - ];
  131. for (vector<NNconnection>::size_type i = ; i != num_connection; i++)
  132. {
  133. //sum=sum+w*x;
  134. unsigned wgtIdx = (*neuralIt).m_connection[i].weightIdx;
  135. unsigned neuralIdx = (*neuralIt).m_connection[i].neuralIdx;
  136.  
  137. dsum += (*layerIt)->preLayer->m_neurals[neuralIdx].output*
  138. (*layerIt)->m_weights[wgtIdx];
  139. }
  140. neuralIt->output = SIGMOID(dsum);
  141.  
  142. neuralIt++;//下一个神经元
  143. neuralIdx++;//每个神经元的偏置不同
  144. }
  145. }
  146. layerIt++;//下一层网络
  147. }
  148. //将最后一层的结果保存至输出
  149. NNlayer * lastLayer = m_layers[m_layers.size() - ];
  150. vector<NNneural>::iterator neuralIt = lastLayer->m_neurals.begin();
  151. while (neuralIt != lastLayer->m_neurals.end())
  152. {
  153. outvect.push_back(neuralIt->output);
  154. neuralIt++;
  155. }
  156. }
  157.  
  158. void NeuralNetwork::backPropagate(vector<double>& tVect, vector<double>& oVect)
  159. {
  160. //首先取得最后一层迭代器
  161. vector<NNlayer *>::iterator lit = m_layers.end() - ;
  162. //用于保存最后一层所有结点误差
  163. vector<double> dErrWrtDxLast((*lit)->m_neurals.size());
  164. for (vector<NNneural>::size_type i = ; i != (*lit)->m_neurals.size(); i++)
  165. {
  166. dErrWrtDxLast[i]=oVect[i] - tVect[i];
  167. }
  168. //所有层的误差
  169. vector<vector<double>> diffVect(nLayer);
  170. diffVect[nLayer - ] = dErrWrtDxLast;
  171.  
  172. //先将其他层误差设为0
  173. for (unsigned int i = ; i < nLayer - ; i++)
  174. {
  175. //每层误差的个数要与神经元相等
  176. diffVect[i].resize(m_layers[i]->m_neurals.size(), 0.0);
  177. }
  178.  
  179. vector<NNlayer>::size_type i = m_layers.size() - ;
  180. //对每一层调用BP算法,第一个参数为第i层输出误差
  181. //第二个参数可作为下次调用的返回值
  182. for (lit; lit>m_layers.begin(); lit--)
  183. {
  184. (*lit)->backPropagate(diffVect[i], diffVect[i - ], etaLearningRate);
  185. i--;
  186. }
  187. diffVect.clear();
  188. }
  189.  
  190. void NNlayer::backPropagate(vector<double>& dErrWrtDxn, vector<double>& dErrWrtDxnm, double eta)
  191. {
  192. //三个参数分别代表第i层的误差,第i-1层的误差,学习速率
  193. //计算每个神经元的误差
  194. double output;
  195. vector<double> dErrWrtDyn(dErrWrtDxn.size());//每个神经元的残差
  196. for (vector<NNneural>::size_type i = ; i != m_neurals.size(); i++)
  197. {
  198. output = m_neurals[i].output;
  199. //计算第i层的残差,对于输出层,dErrWrtDxn表示误差,对于
  200. //其他层,dErrWrtDxn表示w*(i+1层残差)
  201. dErrWrtDyn[i] = DSIGMOD(output)*dErrWrtDxn[i];
  202. }
  203. //计算每个w的偏导数
  204. unsigned ii();
  205. vector<NNneural>::iterator nit = m_neurals.begin();
  206. vector<double> dErrWrtDwn(m_weights.size(), );
  207.  
  208. while (nit != m_neurals.end())
  209. {
  210. //对于每个神经元
  211. for (vector<NNconnection>::size_type k = ; k != (*nit).m_connection.size(); k++)
  212. {
  213. //对于每个权重连接
  214. if (k == (*nit).m_connection.size() - )
  215. output = ;//如果是偏置,则为1
  216. else//与该权重相连的前一层神经元的输出
  217. output = preLayer->m_neurals[(*nit).m_connection[k].neuralIdx].output;
  218. //计算该权重的偏导数值(随着迭代的进行,偏导也是逐渐累加的)
  219. dErrWrtDwn[((*nit).m_connection[k].weightIdx)] += output*dErrWrtDyn[ii];
  220. }
  221. nit++;
  222. ii++;
  223. }
  224.  
  225. //dErrWrtDxnm作为下一层的dErrWrtDxn,用于计算残差
  226. unsigned j();
  227. nit = m_neurals.begin();
  228. while (nit != m_neurals.end())
  229. {
  230. for (vector<NNconnection>::size_type k = ; k != (*nit).m_connection.size()-; k++)
  231. {
  232. dErrWrtDxnm[(*nit).m_connection[k].neuralIdx] += dErrWrtDyn[j] *
  233. m_weights[(*nit).m_connection[k].weightIdx];
  234. }
  235. j++;
  236. nit++;
  237. }
  238.  
  239. for (vector<double>::size_type i = ; i != m_weights.size(); i++)
  240. {
  241. m_weights[i] -= eta*dErrWrtDwn[i];
  242. }
  243. }

多层神经网络与C++实现的更多相关文章

  1. 多层神经网络BP算法 原理及推导

    首先什么是人工神经网络?简单来说就是将单个感知器作为一个神经网络节点,然后用此类节点组成一个层次网络结构,我们称此网络即为人工神经网络(本人自己的理解).当网络的层次大于等于3层(输入层+隐藏层(大于 ...

  2. TensorFlow 训练MNIST数据集(2)—— 多层神经网络

    在我的上一篇随笔中,采用了单层神经网络来对MNIST进行训练,在测试集中只有约90%的正确率.这次换一种神经网络(多层神经网络)来进行训练和测试. 1.获取MNIST数据 MNIST数据集只要一行代码 ...

  3. 用Tensorflow实现多层神经网络

    用Tensorflow实现多层神经网络 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 Tensorflow机器学习实战指南 源代码请点击下方链接欢迎加星 ReLU激活函数/L1范数 ...

  4. Spark2.0机器学习系列之7: MLPC(多层神经网络)

    Spark2.0 MLPC(多层神经网络分类器)算法概述 MultilayerPerceptronClassifier(MLPC)这是一个基于前馈神经网络的分类器,它是一种在输入层与输出层之间含有一层 ...

  5. ufldl学习笔记与编程作业:Multi-Layer Neural Network(多层神经网络+识别手写体编程)

    ufldl学习笔记与编程作业:Multi-Layer Neural Network(多层神经网络+识别手写体编程) ufldl出了新教程,感觉比之前的好,从基础讲起,系统清晰,又有编程实践. 在dee ...

  6. MXNET:多层神经网络

    多层感知机(multilayer perceptron,简称MLP)是最基础的深度学习模型. 多层感知机在单层神经网络的基础上引入了一到多个隐藏层(hidden layer).隐藏层位于输入层和输出层 ...

  7. MLP(多层神经网络)介绍

    写在前面的 接触神经网络(ANN)的时间很长了,以前也只是学了学原理,做过一个BPN的练习,没有系统的总结过,最近看Torch的源码,对MLP有了更多的了解,写写自己学到的东西吧,算是做了一次总结! ...

  8. 学习笔记TF011:多层神经网络

    线性回归.对数几率回归模型,本质上是单个神经元.计算输入特征加权和.偏置视为每个样本输入特征为1权重,计算特征线性组合.激活(传递)函数 计算输出.线性回归,恒等式(值不变).对数几率回归,sigmo ...

  9. 简单多层神经网络实现异或XOR

    最近在看<Neural Network Design_Hagan> 然后想自己实现一个XOR 的网络. 由于单层神经网络不能将异或的判定分为两类. 根据 a^b=(a&~b)|(~ ...

  10. ubuntu之路——day14 只用python的numpy在底层实现多层神经网络

    首先感谢这位博主整理的Andrew Ng的deeplearning.ai的相关作业:https://blog.csdn.net/u013733326/article/details/79827273 ...

随机推荐

  1. 全解┃OpenStack Newton发布,23家中国企业上榜(转载)

    (转载自Openstack中文社区) 陈, 翔 2016-10-8 | 暂无评论 美国奥斯汀时间10月6日(北京时间6日24点),OpenStack Newton版本正式发布,在可扩展性.可靠性和用户 ...

  2. [bzoj 1911][Apio 2010]特别行动队(斜率优化DP)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 分析: 首先可以的到裸的方程f[i]=max{f[j]+a*(Si-Sj)^2+b*(S ...

  3. 第四章:Javascript表达式和运算符

    表达式是javascript中的一个短语,javascript解释器会将其计算出一个结果.程序中常用量是最简单的一类表达式就是变量.变量名也是一种简单的表达式,它的值就是赋值给变量的值.复杂的表达式是 ...

  4. java通过地址获取主机名

    关键代码: try { String str=Chat.getJt().getText().toString();//获取输入内容 String[] ipstr=str.split("[.] ...

  5. easyUI API(version 1.5)

    不分先后,只做记录. jquery+easyui培训文档下载地址: 链接: https://pan.baidu.com/s/1dFgFXk9 密码: jj5d 1 easyui-draggable(拖 ...

  6. WebService 入门程序(一)

    第一步:定义webService接口 package com.robert.ws.service; import javax.jws.WebService; @WebService public in ...

  7. shell 命令遇到的一些问题

    1.  command not found 一般都是未安装,需要root 权限去安装服务,就可正常使用.比如rz, sz, crontab, sendemail, lftp等 2. rz 传输失败,输 ...

  8. BZOJ-1975 魔法猪学院 K短路 (A*+SPFA)

    1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1323 Solved: 433 [Submit][Statu ...

  9. Android视频直播解决方案(rstp、udp)

    做局域网视频直播有两种方案,通过rstp或udp协议. 1.rstp协议,网络上有个开源项目,基于Android,且这个项目也是一个服务端,里面也集成了http访问页面,可以通过http或者rstp直 ...

  10. 让Jayrock插上翅膀(加入输入输出参数注释,测试页面有注释,下拉框可以搜索)

    继上一篇文章介绍了Jayrock组件开发接口的具体步骤和优缺点之后,今天给大家带来的就是,如何修复这些缺点. 首先来回顾一下修复的缺点有哪些: 1.每个接口的只能写大概的注释,不能分开来写,如接口的主 ...