neuralNetwork.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "neuralNetwork.h"
  4. //using namespace std;
  5. #ifndef M_PI
  6. #define M_PI 3.14159265358979323846
  7. #endif
  8. static float norm(void)//add desired mean, multiply to get desired SD
  9. {
  10. static float kept = 0;
  11. static bool in = 0;
  12. if(!in)
  13. {
  14. float x = (rand()+1)/float(RAND_MAX+1);
  15. float f = sqrtf( - 2.0f * log(x) );
  16. x = (rand()+1)/float(RAND_MAX+1);
  17. kept = f * cosf( 2.0f * M_PI * x );
  18. in = true;
  19. return f * sinf( 2.0f * M_PI * x );
  20. }
  21. else
  22. {
  23. in = false;
  24. return kept;
  25. }
  26. }
  27. /*******************************************************************
  28. * Constructors
  29. ********************************************************************/
  30. neuralNetwork::neuralNetwork() : nInput(0), nHidden1(0), nHidden2(0), nOutput(0)
  31. {
  32. inputNeurons = new double[1] ;
  33. hiddenNeurons1 = new double[1] ;
  34. hiddenNeurons2 = new double[1] ;
  35. outputNeurons = new double[1] ;
  36. wInputHidden = new double*[1] ;
  37. wInputHidden[0] = new double[1];
  38. wHidden2Hidden = new double*[1] ;
  39. wHidden2Hidden[0] = new (double[1]);
  40. wHiddenOutput = new double*[1] ;
  41. wHiddenOutput[0] = new double[1];
  42. }
  43. neuralNetwork::neuralNetwork(const neuralNetwork& other): nInput(0), nHidden1(0), nHidden2(0), nOutput(0)
  44. {
  45. inputNeurons = new double[1] ;
  46. hiddenNeurons1 = new double[1] ;
  47. hiddenNeurons2 = new double[1] ;
  48. outputNeurons = new double[1] ;
  49. wInputHidden = new double*[1] ;
  50. wInputHidden[0] = new double[1];
  51. wHidden2Hidden = new double*[1] ;
  52. wHidden2Hidden[0] = new (double[1]);
  53. wHiddenOutput = new double*[1] ;
  54. wHiddenOutput[0] = new double[1];
  55. *this = other;
  56. }
  57. neuralNetwork::neuralNetwork(int nI, int nH1, int nH2, int nO) : nInput(nI), nHidden1(nH1), nHidden2(nH2), nOutput(nO)
  58. {
  59. //create neuron lists
  60. //--------------------------------------------------------------------------------------------------------
  61. inputNeurons = new double[nInput + 1] ;
  62. for ( int i=0; i < nInput; i++ ) inputNeurons[i] = 0;
  63. //create input bias neuron
  64. inputNeurons[nInput] = -1;
  65. hiddenNeurons1 = new double[nHidden1 + 1] ;
  66. for ( int i=0; i < nHidden1; i++ ) hiddenNeurons1[i] = 0;
  67. //create hidden bias neuron
  68. hiddenNeurons1[nHidden1] = -1;
  69. hiddenNeurons2 = new double[nHidden2 + 1] ;
  70. for ( int i=0; i < nHidden2; i++ ) hiddenNeurons2[i] = 0;
  71. //create hidden bias neuron
  72. hiddenNeurons2[nHidden2] = -1;
  73. outputNeurons = new double[nOutput] ;
  74. for ( int i=0; i < nOutput; i++ ) outputNeurons[i] = 0;
  75. //create weight lists (include bias neuron weights)
  76. //--------------------------------------------------------------------------------------------------------
  77. wInputHidden = new double*[nInput + 1] ;
  78. for ( int i=0; i <= nInput; i++ )
  79. {
  80. wInputHidden[i] = new double[nHidden1];
  81. for ( int j=0; j < nHidden1; j++ ) wInputHidden[i][j] = 0;
  82. }
  83. wHidden2Hidden = new double*[nHidden1 + 1] ;
  84. for ( int i=0; i <= nHidden1; i++ )
  85. {
  86. wHidden2Hidden[i] = new (double[nHidden2]);
  87. for ( int j=0; j < nHidden2; j++ ) wHidden2Hidden[i][j] = 0;
  88. }
  89. wHiddenOutput = new double*[nHidden2 + 1] ;
  90. for ( int i=0; i <= nHidden2; i++ )
  91. {
  92. wHiddenOutput[i] = new double[nOutput];
  93. for ( int j=0; j < nOutput; j++ ) wHiddenOutput[i][j] = 0;
  94. }
  95. //initialize weights
  96. //--------------------------------------------------------------------------------------------------------
  97. initializeWeights();
  98. }
  99. void neuralNetwork::operator = (const neuralNetwork&cpy)//assumes same structure
  100. {
  101. if( nInput != cpy.nInput || nHidden1 != cpy.nHidden1 || nHidden2 != cpy.nHidden2 || nOutput != cpy.nOutput)
  102. {
  103. delete[] inputNeurons;
  104. delete[] hiddenNeurons1;
  105. delete[] hiddenNeurons2;
  106. delete[] outputNeurons;
  107. //delete weight storage
  108. for (int i=0; i <= nInput; i++) delete[] wInputHidden[i];
  109. delete[] wInputHidden;
  110. for (int j=0; j <= nHidden2; j++) delete[] wHiddenOutput[j];
  111. delete[] wHiddenOutput;
  112. for (int j=0; j <= nHidden1; j++) delete[] wHidden2Hidden[j];
  113. delete[] wHidden2Hidden;
  114. nInput = cpy.nInput;
  115. nHidden1 = cpy.nHidden1;
  116. nHidden2 = cpy.nHidden2;
  117. nOutput = cpy.nOutput;
  118. inputNeurons = new double[nInput + 1] ;
  119. inputNeurons[nInput] = -1;
  120. hiddenNeurons1 = new double[nHidden1 + 1] ;
  121. hiddenNeurons1[nHidden1] = -1;
  122. hiddenNeurons2 = new double[nHidden2 + 1] ;
  123. hiddenNeurons2[nHidden2] = -1;
  124. outputNeurons = new double[nOutput] ;
  125. //create weight lists (include bias neuron weights)
  126. //--------------------------------------------------------------------------------------------------------
  127. wInputHidden = new double*[nInput + 1] ;
  128. for ( int i=0; i <= nInput; i++ )
  129. wInputHidden[i] = new double[nHidden1];
  130. wHidden2Hidden = new double*[nHidden1 + 1] ;
  131. for ( int i=0; i <= nHidden1; i++ )
  132. wHidden2Hidden[i] = new (double[nHidden2]);
  133. wHiddenOutput = new double*[nHidden2 + 1] ;
  134. for ( int i=0; i <= nHidden2; i++ )
  135. wHiddenOutput[i] = new double[nOutput];
  136. }
  137. for ( int i=0; i < nInput; i++ ) inputNeurons[i] = cpy.inputNeurons[i];
  138. for ( int i=0; i < nHidden1; i++ ) hiddenNeurons1[i] = cpy.hiddenNeurons1[i];
  139. for ( int i=0; i < nHidden2; i++ ) hiddenNeurons2[i] = cpy.hiddenNeurons2[i];
  140. for ( int i=0; i < nOutput; i++ ) outputNeurons[i] = cpy.outputNeurons[i];
  141. for ( int i=0; i <= nInput; i++ )
  142. for ( int j=0; j < nHidden1; j++ )
  143. wInputHidden[i][j] = cpy.wInputHidden[i][j];
  144. for ( int i=0; i <= nHidden1; i++ )
  145. for ( int j=0; j < nHidden2; j++ )
  146. wHidden2Hidden[i][j] = cpy.wHidden2Hidden[i][j];
  147. for ( int i=0; i <= nHidden2; i++ )
  148. for ( int j=0; j < nOutput; j++ )
  149. wHiddenOutput[i][j] = cpy.wHiddenOutput[i][j];
  150. }
  151. /*******************************************************************
  152. * Destructor
  153. ********************************************************************/
  154. neuralNetwork::~neuralNetwork()
  155. {
  156. //delete neurons
  157. delete[] inputNeurons;
  158. delete[] hiddenNeurons1;
  159. delete[] hiddenNeurons2;
  160. delete[] outputNeurons;
  161. //delete weight storage
  162. for (int i=0; i <= nInput; i++) delete[] wInputHidden[i];
  163. delete[] wInputHidden;
  164. for (int j=0; j <= nHidden2; j++) delete[] wHiddenOutput[j];
  165. delete[] wHiddenOutput;
  166. for (int j=0; j <= nHidden1; j++) delete[] wHidden2Hidden[j];
  167. delete[] wHidden2Hidden;
  168. }
  169. double* neuralNetwork::feedForwardPattern(double *pattern)
  170. {
  171. feedForward(pattern);
  172. return outputNeurons;
  173. }
  174. void neuralNetwork::mate(const neuralNetwork&n1,const neuralNetwork&n2)
  175. {
  176. for(int i = 0; i <= nInput; i++)
  177. {
  178. for(int j = 0; j < nHidden1; j++)
  179. {
  180. if(rand()%2==0)
  181. wInputHidden[i][j] = n1.wInputHidden[i][j];
  182. else
  183. wInputHidden[i][j] = n2.wInputHidden[i][j];
  184. }
  185. }
  186. for(int i = 0; i <= nHidden1; i++)
  187. {
  188. for(int j = 0; j < nHidden2; j++)
  189. {
  190. if(rand()%2==0)
  191. wHidden2Hidden[i][j] =n1.wHidden2Hidden[i][j];
  192. else
  193. wHidden2Hidden[i][j] =n2.wHidden2Hidden[i][j];
  194. }
  195. }
  196. for(int i = 0; i <= nHidden2; i++)
  197. {
  198. for(int j = 0; j < nOutput; j++)
  199. {
  200. if(rand()%2==0)
  201. wHiddenOutput[i][j] =n1.wHiddenOutput[i][j];
  202. else
  203. wHiddenOutput[i][j] =n2.wHiddenOutput[i][j];
  204. }
  205. }
  206. }
  207. void neuralNetwork::tweakWeights(double howMuch)
  208. {
  209. //set range
  210. double rH = 1/sqrt( (double) nInput);
  211. double rO = 1/sqrt( (double) nHidden1);
  212. for(int i = 0; i <= nInput; i++)
  213. {
  214. for(int j = 0; j < nHidden1; j++)
  215. {
  216. wInputHidden[i][j] += howMuch*norm();
  217. }
  218. }
  219. for(int i = 0; i <= nHidden1; i++)
  220. {
  221. for(int j = 0; j < nHidden2; j++)
  222. {
  223. wHidden2Hidden[i][j] += howMuch*norm();
  224. }
  225. }
  226. for(int i = 0; i <= nHidden2; i++)
  227. {
  228. for(int j = 0; j < nOutput; j++)
  229. {
  230. wHiddenOutput[i][j] += howMuch* norm();
  231. }
  232. }
  233. //initializeWeights();
  234. }
  235. void neuralNetwork::initializeWeights()
  236. {
  237. //set range
  238. double rH = 2.0/sqrt( (double) nInput);
  239. double rO = 2.0/sqrt( (double) nHidden1);
  240. //set weights between input and hidden
  241. //--------------------------------------------------------------------------------------------------------
  242. for(int i = 0; i <= nInput; i++)
  243. {
  244. for(int j = 0; j < nHidden1; j++)
  245. {
  246. //set weights to random values
  247. wInputHidden[i][j] = norm()* rH;
  248. }
  249. }
  250. for(int i = 0; i <= nHidden1; i++)
  251. {
  252. for(int j = 0; j < nHidden2; j++)
  253. {
  254. //set weights to random values
  255. wHidden2Hidden[i][j] = norm()* rO;
  256. }
  257. }
  258. //set weights between hidden and output
  259. //--------------------------------------------------------------------------------------------------------
  260. for(int i = 0; i <= nHidden2; i++)
  261. {
  262. for(int j = 0; j < nOutput; j++)
  263. {
  264. //set weights to random values
  265. wHiddenOutput[i][j] = norm()* rO;
  266. }
  267. }
  268. }
  269. /*******************************************************************
  270. * Activation Function
  271. ********************************************************************/
  272. inline double neuralNetwork::activationFunction( double x )
  273. {
  274. //sigmoid function
  275. return 1/(1+exp(-x));
  276. }
  277. /*******************************************************************
  278. * Feed Forward Operation
  279. ********************************************************************/
  280. void neuralNetwork::feedForward(double* pattern)
  281. {
  282. //set input neurons to input values
  283. for(int i = 0; i < nInput; i++) inputNeurons[i] = pattern[i];
  284. //Calculate Hidden Layer values - include bias neuron
  285. //--------------------------------------------------------------------------------------------------------
  286. for(int j=0; j < nHidden1; j++)
  287. {
  288. //clear value
  289. hiddenNeurons1[j] = 0;
  290. //get weighted sum of pattern and bias neuron
  291. for( int i=0; i <= nInput; i++ ) hiddenNeurons1[j] += inputNeurons[i] * wInputHidden[i][j];
  292. //set to result of sigmoid
  293. hiddenNeurons1[j] = activationFunction( hiddenNeurons1[j] );
  294. }
  295. for(int j=0; j < nHidden2; j++)
  296. {
  297. //clear value
  298. hiddenNeurons2[j] = 0;
  299. //get weighted sum of pattern and bias neuron
  300. for( int i=0; i <= nHidden1; i++ ) hiddenNeurons2[j] += hiddenNeurons1[i] * wHidden2Hidden[i][j];
  301. //set to result of sigmoid
  302. hiddenNeurons2[j] = activationFunction( hiddenNeurons2[j] );
  303. }
  304. //Calculating Output Layer values - include bias neuron
  305. //--------------------------------------------------------------------------------------------------------
  306. for(int k=0; k < nOutput; k++)
  307. {
  308. //clear value
  309. outputNeurons[k] = 0;
  310. //get weighted sum of pattern and bias neuron
  311. for( int j=0; j <= nHidden2; j++ ) outputNeurons[k] += hiddenNeurons2[j] * wHiddenOutput[j][k];
  312. //set to result of sigmoid
  313. //outputNeurons[k] = activationFunction( outputNeurons[k] );
  314. }
  315. }
  316. void neuralNetwork::backpropigate(double* pattern, double OLR, double H2LR, double H1LR )
  317. {
  318. //inputError = new double[nInput + 1] ;
  319. double * hiddenError1 = new double[nHidden1 + 1] ;
  320. double * hiddenError2 = new double[nHidden2 + 1] ;
  321. double * outputError = new double[nOutput] ;
  322. memset(hiddenError1,0,sizeof(double)*nHidden1);
  323. memset(hiddenError2,0,sizeof(double)*nHidden2);
  324. for(int i = 0; i < nOutput; i++)
  325. {
  326. outputError[i] = (pattern[i]-outputNeurons[i]);//*(outputNeurons[i]*(1-outputNeurons[i]));
  327. for(int ii = 0; ii <= nHidden2;ii++)
  328. hiddenError2[ii]+=outputError[i]*wHiddenOutput[ii][i];
  329. for(int ii = 0; ii <= nHidden2;ii++)
  330. wHiddenOutput[ii][i]+=OLR*hiddenNeurons2[ii]*outputError[i];
  331. }
  332. for(int i = 0; i < nHidden2; i++)
  333. {
  334. hiddenError2[i] *= (hiddenNeurons2[i]*(1-hiddenNeurons2[i]));
  335. for(int ii = 0; ii <= nHidden1;ii++)
  336. hiddenError1[ii]+=hiddenError2[i]*wHidden2Hidden[ii][i];
  337. for(int ii = 0; ii <= nHidden1;ii++)
  338. wHidden2Hidden[ii][i]+=H2LR*hiddenNeurons1[ii]*hiddenError2[i];
  339. }
  340. for(int i = 0; i < nHidden1; i++)
  341. {
  342. hiddenError1[i] *= (hiddenNeurons1[i]*(1-hiddenNeurons1[i]));
  343. for(int ii = 0; ii <= nInput;ii++)
  344. wInputHidden[ii][i]+=H1LR*inputNeurons[ii]*hiddenError1[i];
  345. }
  346. delete [] hiddenError1;
  347. delete [] hiddenError2;
  348. delete [] outputError;
  349. }