Guest User

Untitled

a guest
Jan 9th, 2016
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.49 KB | None | 0 0
  1. using namespace std;
  2.  
  3.  
  4. struct Connection
  5. {
  6. double weight;
  7. double deltaWeight;
  8. };
  9.  
  10.  
  11. class Neuron;
  12.  
  13. typedef vector<Neuron> Layer;
  14.  
  15. // ****************** class Neuron ******************
  16. class Neuron
  17. {
  18. public:
  19. Neuron(unsigned numOutputs, unsigned myIndex);
  20. void setOutputVal(double val) { m_outputVal = val; }
  21. double getOutputVal(void) const { return m_outputVal; }
  22. void feedForward(const vector<Neuron> &prevLayer);
  23. void calcOutputGradients(double targetVal);
  24. void calcHiddenGradients(const vector<Neuron> &nextLayer);
  25. void updateInputWeights(vector<Neuron> &prevLayer);
  26.  
  27. private:
  28. static double eta; // [0.0..1.0] overall net training rate
  29. static double alpha; // [0.0..n] multiplier of last weight change (momentum)
  30. static double transferFunction(double x);
  31. static double transferFunctionDerivative(double x);
  32. static double randomWeight(void) { return rand() / double(RAND_MAX); }
  33. double sumDOW(const vector<Neuron> &nextLayer) const;
  34. double m_outputVal;
  35. vector<Connection> m_outputWeights;
  36. unsigned m_myIndex;
  37. double m_gradient;
  38. };
  39.  
  40. double Neuron::eta = 0.15; // overall net learning rate, [0.0..1.0]
  41. double Neuron::alpha = 0.5; // momentum, multiplier of last deltaWeight, [0.0..1.0]
  42.  
  43.  
  44. void Neuron::updateInputWeights(vector<Neuron> &prevLayer)
  45. {
  46. // The weights to be updated are in the Connection container
  47. // in the neurons in the preceding layer
  48.  
  49. for (unsigned n = 0; n < prevLayer.size(); ++n) {
  50. Neuron &neuron = prevLayer[n];
  51. double oldDeltaWeight = neuron.m_outputWeights[m_myIndex].deltaWeight;
  52.  
  53. double newDeltaWeight = eta * neuron.getOutputVal() * m_gradient + alpha * oldDeltaWeight;
  54. neuron.m_outputWeights[m_myIndex].deltaWeight = newDeltaWeight;
  55. neuron.m_outputWeights[m_myIndex].weight += newDeltaWeight;
  56. }
  57. }
  58.  
  59. double Neuron::sumDOW(const vector<Neuron> &nextLayer) const
  60. {
  61. double sum = 0.0;
  62.  
  63. // Sum our contributions of the errors at the nodes we feed.
  64.  
  65. for (unsigned n = 0; n < nextLayer.size() - 1; ++n) {
  66. sum += m_outputWeights[n].weight * nextLayer[n].m_gradient;
  67. }
  68.  
  69. return sum;
  70. }
  71.  
  72. void Neuron::calcHiddenGradients(const vector<Neuron> &nextLayer)
  73. {
  74. double dow = sumDOW(nextLayer);
  75. m_gradient = dow * Neuron::transferFunctionDerivative(m_outputVal);
  76. }
  77.  
  78. void Neuron::calcOutputGradients(double targetVal)
  79. {
  80. double delta = targetVal - m_outputVal;
  81. m_gradient = delta * Neuron::transferFunctionDerivative(m_outputVal);
  82. }
  83.  
  84. double Neuron::transferFunction(double x)
  85. {
  86. // tanh - output range [-1.0..1.0]
  87.  
  88. return tanh(x);
  89. }
  90.  
  91. double Neuron::transferFunctionDerivative(double x)
  92. {
  93. // tanh derivative
  94. return 1.0 - x * x;
  95. }
  96.  
  97. void Neuron::feedForward(const vector<Neuron> &prevLayer)
  98. {
  99. double sum = 0.0;
  100.  
  101. // Sum the previous layer's outputs (which are our inputs)
  102. // Include the bias node from the previous layer.
  103.  
  104. for (unsigned n = 0; n < prevLayer.size(); ++n) {
  105. sum += prevLayer[n].getOutputVal() *
  106. prevLayer[n].m_outputWeights[m_myIndex].weight;
  107. }
  108.  
  109. m_outputVal = Neuron::transferFunction(sum);
  110. }
  111.  
  112. Neuron::Neuron(unsigned numOutputs, unsigned myIndex)
  113. {
  114. /*
  115. unsigned numLayers = topology.size();
  116. for (unsigned layerNum = 0; layerNum < numLayers; ++layerNum) {
  117. m_layers.push_back(Layer());
  118.  
  119.  
  120. // unsigned numOutputs = layerNum == topology.size() - 1 ? 0 : topology[layerNum + 1];
  121. unsigned numOutputs;
  122. if (layerNum == topology.size() - 1) numOutputs = 0;
  123. else numOutputs = topology[layerNum + 1];
  124.  
  125.  
  126. // We have a new layer, now fill it with neurons, and
  127. // add a bias neuron in each layer.
  128. for (unsigned neuronNum = 0; neuronNum <= topology[layerNum]; ++neuronNum) {
  129. m_layers.back().push_back(Neuron(numOutputs, neuronNum));
  130. */
  131.  
  132. for (unsigned c = 0; c < numOutputs; ++c) {
  133. m_outputWeights.push_back(Connection());
  134. m_outputWeights.back().weight = randomWeight();
  135. }
  136.  
  137. m_myIndex = myIndex;
  138. }
  139.  
  140.  
  141. // ****************** class Net ******************
  142. class Net
  143. {
  144. public:
  145. Net(const vector<unsigned> &topology);
  146. void feedForward(const vector<double> &inputVals);
  147. void backProp(const vector<double> &targetVals);
  148. void getResults(vector<double> &resultVals) const;
  149. double getRecentAverageError(void) const { return m_recentAverageError; }
  150.  
  151. private:
  152. vector<vector<Neuron>> m_layers; // m_layers[layerNum][neuronNum]
  153. double m_error;
  154. double m_recentAverageError;
  155. static double m_recentAverageSmoothingFactor;
  156. };
  157.  
  158.  
  159. double Net::m_recentAverageSmoothingFactor = 100.0; // Number of training samples to average over
  160.  
  161.  
  162. void Net::getResults(vector<double> &resultVals) const
  163. {
  164. resultVals.clear();
  165.  
  166. for (unsigned n = 0; n < m_layers.back().size() - 1; ++n) {
  167. resultVals.push_back(m_layers.back()[n].getOutputVal());
  168. }
  169. }
  170.  
  171. void Net::backProp(const vector<double> &targetVals)
  172. {
  173. // Calculate overall net error (RMS of output neuron errors)
  174.  
  175. vector<Neuron> &outputLayer = m_layers.back();
  176. m_error = 0.0;
  177.  
  178. for (unsigned n = 0; n < outputLayer.size() - 1; ++n) {
  179. double delta = targetVals[n] - outputLayer[n].getOutputVal();
  180. m_error += delta * delta;
  181. }
  182. m_error /= outputLayer.size() - 1; // get average error squared
  183. m_error = sqrt(m_error); // RMS
  184.  
  185. // Implement a recent average measurement
  186.  
  187. m_recentAverageError =
  188. (m_recentAverageError * m_recentAverageSmoothingFactor + m_error)
  189. / (m_recentAverageSmoothingFactor + 1.0);
  190.  
  191. // Calculate output layer gradients
  192.  
  193. for (unsigned n = 0; n < outputLayer.size() - 1; ++n) {
  194. outputLayer[n].calcOutputGradients(targetVals[n]);
  195. }
  196.  
  197. // Calculate hidden layer gradients
  198.  
  199. for (unsigned layerNum = m_layers.size() - 2; layerNum > 0; --layerNum) {
  200. Layer &hiddenLayer = m_layers[layerNum];
  201. Layer &nextLayer = m_layers[layerNum + 1];
  202.  
  203. for (unsigned n = 0; n < hiddenLayer.size(); ++n) {
  204. hiddenLayer[n].calcHiddenGradients(nextLayer);
  205. }
  206. }
  207.  
  208. // For all layers from outputs to first hidden layer,
  209. // update connection weights
  210.  
  211. for (unsigned layerNum = m_layers.size() - 1; layerNum > 0; --layerNum) {
  212. vector<Neuron> &layer = m_layers[layerNum];
  213. vector<Neuron> &prevLayer = m_layers[layerNum - 1];
  214.  
  215. for (unsigned n = 0; n < layer.size() - 1; ++n) {
  216. layer[n].updateInputWeights(prevLayer);
  217. }
  218. }
  219. }
  220.  
  221. void Net::feedForward(const vector<double> &inputVals)
  222. {
  223. assert(inputVals.size() == m_layers[0].size() - 1);
  224.  
  225. // Assign (latch) the input values into the input neurons
  226. for (unsigned i = 0; i < inputVals.size(); ++i) {
  227. m_layers[0][i].setOutputVal(inputVals[i]);
  228. }
  229.  
  230. // forward propagate
  231. for (unsigned layerNum = 1; layerNum < m_layers.size(); ++layerNum) {
  232. vector<Neuron> &prevLayer = m_layers[layerNum - 1];
  233. for (unsigned n = 0; n < m_layers[layerNum].size() - 1; ++n) {
  234. m_layers[layerNum][n].feedForward(prevLayer);
  235. }
  236. }
  237. }
  238.  
  239. Net::Net(const vector<unsigned> &topology)
  240. {
  241. unsigned numLayers = topology.size();
  242. for (unsigned layerNum = 0; layerNum < numLayers; ++layerNum) {
  243. m_layers.push_back(Layer());
  244.  
  245.  
  246. // unsigned numOutputs = layerNum == topology.size() - 1 ? 0 : topology[layerNum + 1];
  247. unsigned numOutputs;
  248. if (layerNum == topology.size() - 1) numOutputs = 0;
  249. else numOutputs = topology[layerNum + 1];
  250.  
  251.  
  252. // We have a new layer, now fill it with neurons, and
  253. // add a bias neuron in each layer.
  254. for (unsigned neuronNum = 0; neuronNum <= topology[layerNum]; ++neuronNum) {
  255. m_layers.back().push_back(Neuron(numOutputs, neuronNum));
  256. cout << "Made a Neuron!" << endl;
  257. }
  258.  
  259. // Force the bias node's output to 1.0 (it was the last neuron pushed in this layer):
  260. m_layers.back().back().setOutputVal(1.0);
  261. }
  262. }
Add Comment
Please, Sign In to add comment