Advertisement
Guest User

Untitled

a guest
Sep 1st, 2015
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.24 KB | None | 0 0
  1. #include <vector>
  2. #include <iostream>
  3. #include <cstdlib>
  4. #include <cassert>
  5. #include <cmath>
  6. #include <fstream>
  7. #include <sstream>
  8.  
  9. using namespace std;
  10.  
  11. /* --- --- --- Training --- --- --- */
  12.  
  13. class TrainingData
  14. {
  15. public:
  16. TrainingData(vector<unsigned> topology);
  17. void getTopology(vector<unsigned> &topology);
  18.  
  19. unsigned getNextInputs(vector<double> &inputVals);
  20. unsigned getTargetOutputs(vector<double> &targetOutputVals);
  21.  
  22. private:
  23. vector<double> _inputVals;
  24. vector<double> _outputVals;
  25. vector<unsigned> _topology;
  26. };
  27.  
  28. TrainingData::TrainingData(vector<unsigned> topology)
  29. {
  30. _topology = topology;
  31. }
  32.  
  33. void TrainingData::getTopology(vector<unsigned> &topology)
  34. {
  35. for (unsigned i = 0; i < _topology.size(); i++)
  36. {
  37. topology.push_back(_topology[i]);
  38. }
  39. }
  40.  
  41. unsigned TrainingData::getNextInputs(vector<double> &inputVals)
  42. {
  43. _inputVals.clear();
  44. _outputVals.clear();
  45. inputVals.clear();
  46. int n1 = (int)(2.0 * rand() / double(RAND_MAX));
  47. int n2 = (int)(2.0 * rand() / double(RAND_MAX));
  48. int t = n1 ^ n2; //should be 1 or 0
  49. _inputVals.push_back(n1);
  50. _inputVals.push_back(n2);
  51. _outputVals.push_back(t);
  52.  
  53. inputVals.push_back(n1);
  54. inputVals.push_back(n2);
  55. return inputVals.size();
  56. }
  57.  
  58. unsigned TrainingData::getTargetOutputs(vector<double> &targetOutputVals)
  59. {
  60. targetOutputVals.clear();
  61. for (unsigned i = 0; i < _outputVals.size(); i++)
  62. {
  63. targetOutputVals.push_back(_outputVals[i]);
  64. }
  65. return targetOutputVals.size();
  66. }
  67.  
  68. struct Connection
  69. {
  70. double weight;
  71. double deltaWeight;
  72. };
  73.  
  74. class Neuron;
  75.  
  76. typedef vector<Neuron> Layer;
  77.  
  78.  
  79. /* --- --- --- Neuron --- --- --- */
  80.  
  81. class Neuron
  82. {
  83. public:
  84. Neuron(unsigned numOutputs, unsigned myIndex);
  85. void setOutputVal(double val) { _outputVal = val; }
  86. double getOutputVal(void) const { return _outputVal; }
  87. void feedForward(const Layer &prevLayer);
  88. void calOutputGradients(double targetVal);
  89. void calcOutputHiddenGradients(const Layer &nextLayer);
  90. void updateInputWeights(Layer &prevLayer);
  91.  
  92. private:
  93. static double _eta;
  94. static double _alpha;
  95. static double _transferFunction(double x);
  96. static double _transferFunctionDerivative(double x);
  97. static double _randomWeight(void) { return rand() / double(RAND_MAX); }
  98. double _sumDow(const Layer &nextLayer) const;
  99. double _outputVal;
  100. vector<Connection> _outputWeights;
  101. unsigned _myIndex;
  102. double _gradient;
  103. };
  104.  
  105. /*-- Neuron::public --*/
  106.  
  107. double Neuron::_eta = 0.15; //overall learning rate
  108. double Neuron::_alpha = 0.5;
  109.  
  110. Neuron::Neuron(unsigned numOutputs, unsigned myIndex)
  111. {
  112. for (unsigned c = 0; c < numOutputs; c++)
  113. {
  114. _outputWeights.push_back(Connection());
  115. _outputWeights.back().weight = _randomWeight();
  116. }
  117.  
  118. _myIndex = myIndex;
  119. }
  120.  
  121. void Neuron::feedForward(const Layer &prevLayer)
  122. {
  123. double sum = 0.0;
  124.  
  125. for (unsigned n = 0; n < prevLayer.size(); n++)
  126. {
  127. sum += prevLayer[n].getOutputVal() *
  128. prevLayer[n]._outputWeights[_myIndex].weight;
  129. }
  130.  
  131. _outputVal = Neuron::_transferFunction(sum);
  132. }
  133.  
  134. void Neuron::calOutputGradients(double targetVal)
  135. {
  136. double delta = targetVal - _outputVal;
  137. _gradient = delta * Neuron::_transferFunctionDerivative(_outputVal);
  138. }
  139.  
  140. void Neuron::calcOutputHiddenGradients(const Layer &nextLayer)
  141. {
  142. double dow = _sumDow(nextLayer);
  143. _gradient = dow * Neuron::_transferFunctionDerivative(_outputVal);
  144. }
  145.  
  146. void Neuron::updateInputWeights(Layer &prevLayer)
  147. {
  148. for (unsigned n = 0; n < prevLayer.size(); ++n)
  149. {
  150. Neuron &neuron = prevLayer[n];
  151. double oldDeltaWeight = neuron._outputWeights[_myIndex].deltaWeight;
  152.  
  153. double newDeltaWeight =
  154. _eta *
  155. neuron.getOutputVal() *
  156. _gradient +
  157. _alpha *
  158. oldDeltaWeight;
  159.  
  160. neuron._outputWeights[_myIndex].deltaWeight = newDeltaWeight;
  161. neuron._outputWeights[_myIndex].weight += newDeltaWeight;
  162. }
  163. }
  164.  
  165. /*-- Neuron::private --*/
  166.  
  167. double Neuron::_transferFunction(double x)
  168. {
  169. return tanh(x);
  170. }
  171.  
  172. double Neuron::_transferFunctionDerivative(double x)
  173. {
  174. return 1.0 - x*x;
  175. }
  176.  
  177. double Neuron::_sumDow(const Layer &nextLayer) const
  178. {
  179. double sum = 0.0;
  180.  
  181. for (unsigned n = 0; n < nextLayer.size() - 1; n++)
  182. {
  183. sum += _outputWeights[n].weight * nextLayer[n]._gradient;
  184. }
  185.  
  186. return sum;
  187. }
  188.  
  189. /* --- --- --- Net --- --- --- */
  190.  
  191. class Net
  192. {
  193. public:
  194. Net(const vector<unsigned> &topology);
  195. void feedForward(const vector<double> &inputVals);
  196. void backProp(const vector<double> &targetVals);
  197. void getResults(vector<double> &resultVals) const;
  198. double gerRecentAverageError(void) const { return _recentAverageError; }
  199.  
  200. private:
  201. vector<Layer> _layers;
  202. double _error;
  203. double _recentAverageError;
  204. double _recentAverageSmoothingFactor;
  205.  
  206. };
  207.  
  208. /*-- Net::public --*/
  209.  
  210. Net::Net(const vector<unsigned> &topology)
  211. {
  212. unsigned numLayers = topology.size();
  213. for (unsigned layerNum = 0; layerNum < numLayers; layerNum++)
  214. {
  215. _layers.push_back(Layer());
  216. unsigned numOutputs = layerNum == topology.size() - 1 ? 0 : topology[layerNum + 1];
  217.  
  218. for (unsigned neuronNum = 0; neuronNum <= topology[layerNum]; neuronNum++)
  219. {
  220. _layers.back().push_back(Neuron(numOutputs, neuronNum));
  221. cout << "Made a neuron! Layer: " << layerNum << "\n";
  222. }
  223. }
  224. }
  225.  
  226. void Net::feedForward(const vector<double> &inputVals)
  227. {
  228. assert(inputVals.size() == _layers.size() - 1);
  229.  
  230. for (unsigned i = 0; i < inputVals.size(); i++)
  231. {
  232. _layers[0][i].setOutputVal(inputVals[i]);
  233. }
  234.  
  235. //Forward propagate
  236.  
  237. for (unsigned layerNum = 1; layerNum < _layers.size() - 1; layerNum++)
  238. {
  239. Layer &prevLayer = _layers[layerNum - 1];
  240. for (unsigned n = 0; n < _layers[layerNum].size() - 1; n++)
  241. {
  242. _layers[layerNum][n].feedForward(prevLayer); //Neuron::feedForward()
  243. }
  244. }
  245.  
  246. }
  247.  
  248. void Net::backProp(const vector<double> &targetVals)
  249. {
  250. //RMSE [sqrt(MSE)]
  251. Layer &outputLayer = _layers.back();
  252. _error = 0.0;
  253.  
  254. for (unsigned n = 0; n < outputLayer.size() - 1; n++)
  255. {
  256. double delta = targetVals[n] - outputLayer[n].getOutputVal();
  257. _error += delta * delta;
  258. }
  259. _error /= outputLayer.size() - 1;
  260. _error = sqrt(_error);
  261.  
  262. //running average of an error
  263.  
  264. _recentAverageError =
  265. (_recentAverageError * _recentAverageSmoothingFactor + _error)
  266. / (_recentAverageSmoothingFactor + 1.0);
  267.  
  268. //calc output layer gradient
  269.  
  270. for (unsigned n = 0; n < outputLayer.size() - 1; n++)
  271. {
  272. outputLayer[n].calOutputGradients(targetVals[n]);
  273. }
  274.  
  275. //calc gradient on hidden layers
  276. for (unsigned layerNum = _layers.size() - 2; layerNum > 0; --layerNum)
  277. {
  278. Layer &hiddenLayer = _layers[layerNum];
  279. Layer &nextLayer = _layers[layerNum + 1];
  280.  
  281. for (unsigned n = 0; n < hiddenLayer.size(); n++)
  282. {
  283. hiddenLayer[n].calcOutputHiddenGradients(nextLayer);
  284. }
  285. }
  286.  
  287. for (unsigned layerNum = _layers.size() - 1; layerNum > 0; --layerNum)
  288. {
  289. Layer &layer = _layers[layerNum];
  290. Layer &prevLayer = _layers[layerNum - 1];
  291.  
  292. for (unsigned n = 0; n < layer.size() - 1; ++n)
  293. {
  294. layer[n].updateInputWeights(prevLayer);
  295. }
  296. }
  297. }
  298.  
  299. void Net::getResults(vector<double> &resultVals) const
  300. {
  301. resultVals.clear();
  302.  
  303. for (unsigned n = 0; n < _layers.back().size() - 1; ++n)
  304. {
  305. resultVals.push_back(_layers.back()[n].getOutputVal());
  306. }
  307. }
  308.  
  309. /*-- Net::private --*/
  310. /* -=NULL=- */
  311.  
  312. void showVectorVals(string label, vector<double> &v)
  313. {
  314. cout << label << " ";
  315. for (unsigned i = 0; i < v.size(); i++)
  316. {
  317. cout << v[i] << " ";
  318. }
  319. cout << "\n";
  320. }
  321.  
  322. int main()
  323. {
  324. vector<unsigned> topology;
  325. topology.push_back(2);
  326. topology.push_back(4);
  327. topology.push_back(1);
  328. TrainingData trainData(topology);
  329.  
  330. Net myNet(topology);
  331.  
  332. vector<double> inputVals, targetVals, resultVals;
  333. int trainingPass = 0;
  334.  
  335. bool end = false;
  336.  
  337. for (; 2 < 3;)
  338. {
  339. ++trainingPass;
  340. cout << "\n" << "Pass: " << trainingPass;
  341.  
  342. if (trainData.getNextInputs(inputVals) != topology[0])
  343. {
  344. break;
  345. }
  346.  
  347. showVectorVals(": Inputs:", inputVals);
  348. myNet.feedForward(inputVals);
  349.  
  350. //collect net's actual results
  351. myNet.getResults(resultVals);
  352. showVectorVals("Outputs:", resultVals);
  353.  
  354. //train the net
  355. trainData.getTargetOutputs(targetVals);
  356. showVectorVals("Targets:", targetVals);
  357. assert(targetVals.size() == topology.back());
  358.  
  359. myNet.backProp(targetVals);
  360.  
  361. cout << "Ten recent avg error: " << myNet.gerRecentAverageError() << "\n";
  362. system("PAUSE");
  363. }
  364. system("PAUSE");
  365. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement