Advertisement
Guest User

Untitled

a guest
May 24th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.41 KB | None | 0 0
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Drawing2D;
  4. using System.Drawing.Imaging;
  5. using System.Runtime.InteropServices;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. using System.Linq;
  9. using Image = System.Drawing.Image;
  10. using Rectangle = System.Drawing.Rectangle;
  11.  
  12. namespace CodingBackProp
  13. {
  14. class BackPropProgram
  15. {
  16. public static Bitmap ResizeImage(Image image, int width, int height)
  17. {
  18. var destRect = new Rectangle(0, 0, width, height);
  19. var destImage = new Bitmap(width, height);
  20.  
  21. destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
  22.  
  23. using (var graphics = Graphics.FromImage(destImage))
  24. {
  25. graphics.CompositingMode = CompositingMode.SourceCopy;
  26. graphics.CompositingQuality = CompositingQuality.HighQuality;
  27. graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
  28. graphics.SmoothingMode = SmoothingMode.HighQuality;
  29. graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
  30.  
  31. using (var wrapMode = new ImageAttributes())
  32. {
  33. wrapMode.SetWrapMode(WrapMode.TileFlipXY);
  34. graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
  35. }
  36. }
  37.  
  38. return destImage;
  39. }
  40.  
  41. public static byte[] BitmapToByteArray(Bitmap bitmap)
  42. {
  43. BitmapData bmpdata = null;
  44.  
  45. try
  46. {
  47. bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
  48. bitmap.PixelFormat);
  49. int numbytes = bmpdata.Stride * bitmap.Height;
  50. byte[] bytedata = new byte[numbytes];
  51. IntPtr ptr = bmpdata.Scan0;
  52.  
  53. Marshal.Copy(ptr, bytedata, 0, numbytes);
  54.  
  55. return bytedata;
  56. }
  57. finally
  58. {
  59. if (bmpdata != null)
  60. bitmap.UnlockBits(bmpdata);
  61. }
  62. }
  63.  
  64. private static double[] PrepareBitmapArray(Bitmap bmp)
  65. {
  66. double[] pix = new double[bmp.Width * bmp.Height];
  67.  
  68. int x, y, rgb;
  69. double val;
  70. for (y = 0; y < bmp.Height; y++)
  71. {
  72. for (x = 0; x < bmp.Width; x++)
  73. {
  74. System.Drawing.Color c = bmp.GetPixel(x, y);
  75. //rgb = c.ToKnownColor());
  76. if (c.R == 0 && c.B == 0 && c.G == 0) // if black
  77. {
  78. val = 1;
  79. }
  80. else if (c.R < 64 && c.B < 64 && c.G < 64)
  81. {
  82. val = 1;
  83. }
  84. else val = 0;
  85. Console.Write(val);
  86. pix[y * bmp.Width + x] = val;
  87. }
  88. Console.WriteLine("");
  89. }
  90. return pix;
  91. }
  92.  
  93. static void Main(string[] args)
  94. {
  95. int MAX_LITER = 37;
  96. int MAX_OBRAZKI = 50;
  97. int numInput = 625; // number features
  98. int numHidden = 300;
  99. int numOutput = 37; // number of classes for Y
  100. bool TrainedYes = true;
  101.  
  102. if (!TrainedYes)
  103. {
  104. Console.WriteLine("Reading training data...");
  105.  
  106. var readData = new List<double[]>();
  107.  
  108. for (int literka = 1; literka <= MAX_LITER; literka++)
  109. {
  110. var numberLiterka = "0";
  111. if (literka <= 9)
  112. {
  113. numberLiterka += "0" + literka;
  114. }
  115. else
  116. {
  117. numberLiterka += literka;
  118. }
  119. for (int id = 1; id <= MAX_OBRAZKI; id++)
  120. {
  121. string number = "0";
  122. if (id <= 9)
  123. {
  124. number += "0" + id;
  125. }
  126. else
  127. {
  128. number += id;
  129. }
  130.  
  131. Bitmap bitmap2 =
  132. ResizeImage(
  133. Image.FromFile(
  134. @"C:\Users\usr\Downloads\EnglishHnd (1)\EnglishHnd (1)\English\Hnd\Img\Sample" +
  135. numberLiterka + @"\img" + numberLiterka + "-" +
  136. number + ".png"), 25, 25);
  137. double[] preparedBitmap2 = PrepareBitmapArray(bitmap2);
  138. bitmap2.Dispose();
  139.  
  140. var row = new double[preparedBitmap2.Length + numOutput];
  141. for (var idx = 0; idx < preparedBitmap2.Length; ++idx)
  142. {
  143. row[idx] = preparedBitmap2[idx];
  144. }
  145.  
  146. for (var idx = 0; idx < numOutput; ++idx)
  147. {
  148. row[numOutput] = 0;
  149. }
  150.  
  151. row[preparedBitmap2.Length + literka - 1] = 1;
  152.  
  153. readData.Add(row);
  154. }
  155. }
  156. var readyData = readData.ToArray();
  157. Console.WriteLine("Done!");
  158. Console.WriteLine("Creating a " + numInput + "-" + numHidden + "-" + numOutput + " neural network");
  159. NeuralNetwork nn = new NeuralNetwork(numInput, numHidden, numOutput);
  160. nn.LoadData();
  161. int maxEpochs = 1000;
  162. double learnRate = 0.01;
  163. double momentum = 0.01;
  164. Console.WriteLine("\nSetting maxEpochs = " + maxEpochs);
  165. Console.WriteLine("Setting learnRate = " + learnRate.ToString("F2"));
  166. Console.WriteLine("Setting momentum = " + momentum.ToString("F2"));
  167.  
  168. Console.WriteLine("\nStarting training...");
  169. double[] weights = nn.Train(readyData, maxEpochs, learnRate, momentum);
  170.  
  171.  
  172. double trainAcc = nn.Accuracy(readyData);
  173. Console.WriteLine("\nFinal accuracy on training data = " + trainAcc.ToString("F4"));
  174.  
  175. double testAcc = nn.Accuracy(readyData);
  176. Console.WriteLine("Final accuracy on test data = " + testAcc.ToString("F4"));
  177. }
  178.  
  179. if (TrainedYes)
  180. {
  181. NeuralNetwork nn = new NeuralNetwork(numInput, numHidden, numOutput);
  182.  
  183. int maxEpochs = 1000;
  184. double learnRate = 0.05;
  185. double momentum = 0.01;
  186. Console.WriteLine("Warming up...");
  187. Console.WriteLine("Loading neural network ...");
  188. nn.LoadData();
  189. Console.WriteLine("Loaded!");
  190. while (Console.ReadKey().Key != ConsoleKey.Q)
  191. {
  192. Console.WriteLine("Please enter path for image file to be recognized");
  193. var file = Console.ReadLine();
  194. Console.WriteLine("\nStarting...");
  195. //double[] weights = nn.Train(readyData, maxEpochs, learnRate, momentum);
  196. Bitmap bitmap2x =
  197. ResizeImage(
  198. Image.FromFile(
  199. file),
  200. 25, 25);
  201. Console.WriteLine("Prepared image: \n");
  202. double[] preparedBitmap2x = PrepareBitmapArray(bitmap2x);
  203. bitmap2x.Dispose();
  204.  
  205. var rowx = new double[preparedBitmap2x.Length];
  206. for (var idx = 0; idx < preparedBitmap2x.Length; ++idx)
  207. {
  208. rowx[idx] = preparedBitmap2x[idx];
  209. }
  210. double[] weights = nn.ComputeOutputs(rowx);
  211. string recognized = "ERROR";
  212. string[] values = new[]
  213. {
  214. "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C",
  215. "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P",
  216. "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "0",
  217. };
  218. for (int i = 0; i < weights.Length; i++)
  219. {
  220. if (weights[i] == weights.Max())
  221. {
  222. recognized = values[i];
  223. }
  224. // Console.WriteLine(i + " : " + weights[i]);
  225. }
  226. Console.WriteLine("Done\n");
  227. Console.WriteLine("Recognized: " + recognized);
  228. }
  229. }
  230.  
  231.  
  232. Console.WriteLine("Done");
  233.  
  234. //Console.WriteLine("\nFinal neural network model weights and biases:\n");
  235. //ShowVector(weights, 2, 10, true);
  236.  
  237.  
  238.  
  239. Console.ReadLine();
  240. }
  241.  
  242. public static void ShowMatrix(double[][] matrix, int numRows,
  243. int decimals, bool indices)
  244. {
  245. int len = matrix.Length.ToString().Length;
  246. for (int i = 0; i < numRows; ++i)
  247. {
  248. if (indices == true)
  249. Console.Write("[" + i.ToString().PadLeft(len) + "] ");
  250. for (int j = 0; j < matrix[i].Length; ++j)
  251. {
  252. double v = matrix[i][j];
  253. if (v >= 0.0)
  254. Console.Write(" "); // '+'
  255. Console.Write(v.ToString("F" + decimals) + " ");
  256. }
  257. Console.WriteLine("");
  258. }
  259.  
  260. if (numRows < matrix.Length)
  261. {
  262. Console.WriteLine(". . .");
  263. int lastRow = matrix.Length - 1;
  264. if (indices == true)
  265. Console.Write("[" + lastRow.ToString().PadLeft(len) + "] ");
  266. for (int j = 0; j < matrix[lastRow].Length; ++j)
  267. {
  268. double v = matrix[lastRow][j];
  269. if (v >= 0.0)
  270. Console.Write(" "); // '+'
  271. Console.Write(v.ToString("F" + decimals) + " ");
  272. }
  273. }
  274. Console.WriteLine("\n");
  275. }
  276.  
  277. public static void ShowVector(double[] vector, int decimals,
  278. int lineLen, bool newLine)
  279. {
  280. for (int i = 0; i < vector.Length; ++i)
  281. {
  282. if (i > 0 && i % lineLen == 0) Console.WriteLine("");
  283. if (vector[i] >= 0) Console.Write(" ");
  284. Console.Write(vector[i].ToString("F" + decimals) + " ");
  285. }
  286. if (newLine == true)
  287. Console.WriteLine("");
  288. }
  289. }
  290.  
  291. public class NeuralNetwork
  292. {
  293. private int numInput; // number input nodes
  294. private int numHidden;
  295. private int numOutput;
  296.  
  297. private double[] inputs;
  298. private double[][] ihWeights; // input-hidden
  299. private double[] hBiases;
  300. private double[] hOutputs;
  301.  
  302. private double[][] hoWeights; // hidden-output
  303. private double[] oBiases;
  304. private double[] outputs;
  305.  
  306. private Random rnd;
  307.  
  308.  
  309. public void SaveData()
  310. {
  311. string saveData = "";
  312. saveData += numInput + "\t" + numHidden + "\t" + numOutput + "\t";
  313.  
  314. for (int i = 0; i < ihWeights.Length; i++)
  315. {
  316. saveData += String.Join("\t", ihWeights[i].Select(p => p.ToString()).ToArray()) + "\t";
  317. }
  318.  
  319. for (int j = 0; j < hBiases.Length; j++)
  320. {
  321. saveData += hBiases[j] + "\t";
  322. }
  323.  
  324. for (int j = 0; j < hOutputs.Length; j++)
  325. {
  326. saveData += hOutputs[j] + "\t";
  327. }
  328.  
  329. for (int i = 0; i < hoWeights.Length; i++)
  330. {
  331. saveData += String.Join("\t", hoWeights[i].Select(p => p.ToString()).ToArray()) + "\t";
  332. }
  333.  
  334. for (int j = 0; j < oBiases.Length; j++)
  335. {
  336. saveData += oBiases[j] + "\t";
  337. }
  338.  
  339.  
  340. File.WriteAllText("network.net", saveData);
  341. }
  342.  
  343. public void LoadData()
  344. {
  345. string data = File.ReadAllText("network - 37 - error 00506.net");
  346. var data0 = data.Split('\t');
  347. this.numInput = Convert.ToInt32(data.Split('\t')[0]);
  348. this.numHidden = Convert.ToInt32(data.Split('\t')[1]);
  349. this.numOutput = Convert.ToInt32(data.Split('\t')[2]);
  350.  
  351.  
  352. int counter = 3;
  353. for (int i = 0; i < this.numInput; i++)
  354. {
  355. for (int j = 0; j < this.numHidden; j++)
  356. {
  357. this.ihWeights[i][j] = Convert.ToDouble(data0[counter++]);
  358. }
  359. }
  360.  
  361.  
  362. for (int j = 0; j < this.numHidden; j++)
  363. {
  364. hBiases[j] = Convert.ToDouble(data0[counter++]);
  365. }
  366.  
  367. for (int j = 0; j < this.numHidden; j++)
  368. {
  369. hOutputs[j] = Convert.ToDouble(data0[counter++]);
  370. }
  371.  
  372.  
  373. for (int i = 0; i < this.numHidden; i++)
  374. {
  375. for (int j = 0; j < this.numOutput; j++)
  376. {
  377. this.hoWeights[i][j] = Convert.ToDouble(data0[counter++]);
  378. }
  379. }
  380.  
  381. for (int j = 0; j < this.numOutput; j++)
  382. {
  383. oBiases[j] = Convert.ToDouble(data0[counter++]);
  384. }
  385.  
  386. Console.WriteLine("Load OK!");
  387. }
  388.  
  389. public NeuralNetwork(int numInput, int numHidden, int numOutput)
  390. {
  391. this.numInput = numInput;
  392. this.numHidden = numHidden;
  393. this.numOutput = numOutput;
  394.  
  395. this.inputs = new double[numInput];
  396.  
  397. this.ihWeights = MakeMatrix(numInput, numHidden, 0.0);
  398. this.hBiases = new double[numHidden];
  399. this.hOutputs = new double[numHidden];
  400.  
  401. this.hoWeights = MakeMatrix(numHidden, numOutput, 0.0);
  402. this.oBiases = new double[numOutput];
  403. this.outputs = new double[numOutput];
  404.  
  405. this.rnd = new Random(0);
  406. this.InitializeWeights(); // all weights and biases
  407. } // ctor
  408.  
  409. private static double[][] MakeMatrix(int rows, int cols, double v) // helper for ctor, Train
  410. {
  411. double[][] result = new double[rows][];
  412. for (int r = 0; r < result.Length; ++r)
  413. result[r] = new double[cols];
  414. for (int i = 0; i < rows; ++i)
  415. for (int j = 0; j < cols; ++j)
  416. result[i][j] = v;
  417. return result;
  418. }
  419.  
  420. private void InitializeWeights() // helper for ctor
  421. {
  422. // initialize weights and biases to small random values
  423. int numWeights = (numInput * numHidden) +
  424. (numHidden * numOutput) + numHidden + numOutput;
  425. double[] initialWeights = new double[numWeights];
  426. for (int i = 0; i < initialWeights.Length; ++i)
  427. initialWeights[i] = (0.001 - 0.0001) * rnd.NextDouble() + 0.0001;
  428. this.SetWeights(initialWeights);
  429. }
  430.  
  431. public void SetWeights(double[] weights)
  432. {
  433. // copy serialized weights and biases in weights[] array
  434. // to i-h weights, i-h biases, h-o weights, h-o biases
  435. int numWeights = (numInput * numHidden) +
  436. (numHidden * numOutput) + numHidden + numOutput;
  437. if (weights.Length != numWeights)
  438. throw new Exception("Bad weights array in SetWeights");
  439.  
  440. int k = 0; // points into weights param
  441.  
  442. for (int i = 0; i < numInput; ++i)
  443. for (int j = 0; j < numHidden; ++j)
  444. ihWeights[i][j] = weights[k++];
  445. for (int i = 0; i < numHidden; ++i)
  446. hBiases[i] = weights[k++];
  447. for (int i = 0; i < numHidden; ++i)
  448. for (int j = 0; j < numOutput; ++j)
  449. hoWeights[i][j] = weights[k++];
  450. for (int i = 0; i < numOutput; ++i)
  451. oBiases[i] = weights[k++];
  452. }
  453.  
  454. public double[] GetWeights()
  455. {
  456. int numWeights = (numInput * numHidden) +
  457. (numHidden * numOutput) + numHidden + numOutput;
  458. double[] result = new double[numWeights];
  459. int k = 0;
  460. for (int i = 0; i < ihWeights.Length; ++i)
  461. for (int j = 0; j < ihWeights[0].Length; ++j)
  462. result[k++] = ihWeights[i][j];
  463. for (int i = 0; i < hBiases.Length; ++i)
  464. result[k++] = hBiases[i];
  465. for (int i = 0; i < hoWeights.Length; ++i)
  466. for (int j = 0; j < hoWeights[0].Length; ++j)
  467. result[k++] = hoWeights[i][j];
  468. for (int i = 0; i < oBiases.Length; ++i)
  469. result[k++] = oBiases[i];
  470. return result;
  471. }
  472.  
  473. public double[] ComputeOutputs(double[] xValues)
  474. {
  475. double[] hSums = new double[numHidden]; // hidden nodes sums scratch array
  476. double[] oSums = new double[numOutput]; // output nodes sums
  477.  
  478. for (int i = 0; i < xValues.Length; ++i) // copy x-values to inputs
  479. this.inputs[i] = xValues[i];
  480. // note: no need to copy x-values unless you implement a ToString.
  481. // more efficient is to simply use the xValues[] directly.
  482.  
  483. for (int j = 0; j < numHidden; ++j) // compute i-h sum of weights * inputs
  484. for (int i = 0; i < numInput; ++i)
  485. hSums[j] += this.inputs[i] * this.ihWeights[i][j]; // note +=
  486.  
  487. for (int i = 0; i < numHidden; ++i) // add biases to hidden sums
  488. hSums[i] += this.hBiases[i];
  489.  
  490. for (int i = 0; i < numHidden; ++i) // apply activation
  491. this.hOutputs[i] = HyperTan(hSums[i]); // hard-coded
  492.  
  493. for (int j = 0; j < numOutput; ++j) // compute h-o sum of weights * hOutputs
  494. for (int i = 0; i < numHidden; ++i)
  495. oSums[j] += hOutputs[i] * hoWeights[i][j];
  496.  
  497. for (int i = 0; i < numOutput; ++i) // add biases to output sums
  498. oSums[i] += oBiases[i];
  499.  
  500. double[] softOut = Softmax(oSums); // all outputs at once for efficiency
  501. Array.Copy(softOut, outputs, softOut.Length);
  502.  
  503. double[] retResult = new double[numOutput]; // could define a GetOutputs
  504. Array.Copy(this.outputs, retResult, retResult.Length);
  505. return retResult;
  506. }
  507.  
  508. private static double HyperTan(double x)
  509. {
  510. if (x < -20.0) return -1.0; // approximation is correct to 30 decimals
  511. else if (x > 20.0) return 1.0;
  512. else return Math.Tanh(x);
  513. }
  514.  
  515. private static double[] Softmax(double[] oSums)
  516. {
  517. // does all output nodes at once so scale
  518. // doesn't have to be re-computed each time
  519.  
  520. double sum = 0.0;
  521. for (int i = 0; i < oSums.Length; ++i)
  522. sum += Math.Exp(oSums[i]);
  523.  
  524. double[] result = new double[oSums.Length];
  525. for (int i = 0; i < oSums.Length; ++i)
  526. result[i] = Math.Exp(oSums[i]) / sum;
  527.  
  528. return result; // now scaled so that xi sum to 1.0
  529. }
  530.  
  531. public double[] Train(double[][] trainData, int maxEpochs, double learnRate, double momentum)
  532. {
  533. // train using back-prop
  534. // back-prop specific arrays
  535. double[][] hoGrads = MakeMatrix(numHidden, numOutput, 0.0); // hidden-to-output weight gradients
  536. double[] obGrads = new double[numOutput]; // output bias gradients
  537.  
  538. double[][] ihGrads = MakeMatrix(numInput, numHidden, 0.0); // input-to-hidden weight gradients
  539. double[] hbGrads = new double[numHidden]; // hidden bias gradients
  540.  
  541. double[] oSignals = new double[numOutput];
  542. // local gradient output signals - gradients w/o associated input terms
  543. double[] hSignals = new double[numHidden]; // local gradient hidden node signals
  544.  
  545. // back-prop momentum specific arrays
  546. double[][] ihPrevWeightsDelta = MakeMatrix(numInput, numHidden, 0.0);
  547. double[] hPrevBiasesDelta = new double[numHidden];
  548. double[][] hoPrevWeightsDelta = MakeMatrix(numHidden, numOutput, 0.0);
  549. double[] oPrevBiasesDelta = new double[numOutput];
  550.  
  551. int epoch = 0;
  552. double[] xValues = new double[numInput]; // inputs
  553. double[] tValues = new double[numOutput]; // target values
  554. double derivative = 0.0;
  555. double errorSignal = 0.0;
  556.  
  557. int[] sequence = new int[trainData.Length];
  558. for (int i = 0; i < sequence.Length; ++i)
  559. sequence[i] = i;
  560.  
  561. while (epoch < maxEpochs)
  562. {
  563. ++epoch;
  564.  
  565.  
  566. double trainErr = Error(trainData);
  567. Console.WriteLine("epoch = " + epoch + " error = " + trainErr.ToString("F4"));
  568. if (trainErr < 5e-3)
  569. break;
  570.  
  571. Shuffle(sequence); // visit each training data in random order
  572. for (int ii = 0; ii < trainData.Length; ++ii)
  573. {
  574. int idx = sequence[ii];
  575. Array.Copy(trainData[idx], xValues, numInput);
  576. Array.Copy(trainData[idx], numInput, tValues, 0, numOutput);
  577. ComputeOutputs(xValues); // copy xValues in, compute outputs
  578.  
  579. // indices: i = inputs, j = hiddens, k = outputs
  580.  
  581. // 1. compute output node signals (assumes softmax)
  582. for (int k = 0; k < numOutput; ++k)
  583. {
  584. errorSignal = tValues[k] - outputs[k]; // Wikipedia uses (o-t)
  585. derivative = (1 - outputs[k]) * outputs[k]; // for softmax
  586. oSignals[k] = errorSignal * derivative;
  587. }
  588.  
  589. // 2. compute hidden-to-output weight gradients using output signals
  590. for (int j = 0; j < numHidden; ++j)
  591. for (int k = 0; k < numOutput; ++k)
  592. hoGrads[j][k] = oSignals[k] * hOutputs[j];
  593.  
  594. // 2b. compute output bias gradients using output signals
  595. for (int k = 0; k < numOutput; ++k)
  596. obGrads[k] = oSignals[k] * 1.0; // dummy assoc. input value
  597.  
  598. // 3. compute hidden node signals
  599. for (int j = 0; j < numHidden; ++j)
  600. {
  601. derivative = (1 + hOutputs[j]) * (1 - hOutputs[j]); // for tanh
  602. double sum = 0.0; // need sums of output signals times hidden-to-output weights
  603. for (int k = 0; k < numOutput; ++k)
  604. {
  605. sum += oSignals[k] * hoWeights[j][k]; // represents error signal
  606. }
  607. hSignals[j] = derivative * sum;
  608. }
  609.  
  610. // 4. compute input-hidden weight gradients
  611. for (int i = 0; i < numInput; ++i)
  612. for (int j = 0; j < numHidden; ++j)
  613. ihGrads[i][j] = hSignals[j] * inputs[i];
  614.  
  615. // 4b. compute hidden node bias gradients
  616. for (int j = 0; j < numHidden; ++j)
  617. hbGrads[j] = hSignals[j] * 1.0; // dummy 1.0 input
  618.  
  619. // == update weights and biases
  620.  
  621. // update input-to-hidden weights
  622. for (int i = 0; i < numInput; ++i)
  623. {
  624. for (int j = 0; j < numHidden; ++j)
  625. {
  626. double delta = ihGrads[i][j] * learnRate;
  627. ihWeights[i][j] += delta; // would be -= if (o-t)
  628. ihWeights[i][j] += ihPrevWeightsDelta[i][j] * momentum;
  629. ihPrevWeightsDelta[i][j] = delta; // save for next time
  630. }
  631. }
  632.  
  633. // update hidden biases
  634. for (int j = 0; j < numHidden; ++j)
  635. {
  636. double delta = hbGrads[j] * learnRate;
  637. hBiases[j] += delta;
  638. hBiases[j] += hPrevBiasesDelta[j] * momentum;
  639. hPrevBiasesDelta[j] = delta;
  640. }
  641.  
  642. // update hidden-to-output weights
  643. for (int j = 0; j < numHidden; ++j)
  644. {
  645. for (int k = 0; k < numOutput; ++k)
  646. {
  647. double delta = hoGrads[j][k] * learnRate;
  648. hoWeights[j][k] += delta;
  649. hoWeights[j][k] += hoPrevWeightsDelta[j][k] * momentum;
  650. hoPrevWeightsDelta[j][k] = delta;
  651. }
  652. }
  653.  
  654. // update output node biases
  655. for (int k = 0; k < numOutput; ++k)
  656. {
  657. double delta = obGrads[k] * learnRate;
  658. oBiases[k] += delta;
  659. oBiases[k] += oPrevBiasesDelta[k] * momentum;
  660. oPrevBiasesDelta[k] = delta;
  661. }
  662. } // each training item
  663. if (epoch%10 == 0)
  664. {
  665. Console.WriteLine("Saving ...");
  666. SaveData();
  667. Console.WriteLine("Saved!");
  668. }
  669. } // while
  670. double[] bestWts = GetWeights();
  671.  
  672.  
  673.  
  674. return bestWts;
  675. } // Train
  676.  
  677. private void Shuffle(int[] sequence) // instance method
  678. {
  679. for (int i = 0; i < sequence.Length; ++i)
  680. {
  681. int r = this.rnd.Next(i, sequence.Length);
  682. int tmp = sequence[r];
  683. sequence[r] = sequence[i];
  684. sequence[i] = tmp;
  685. }
  686. } // Shuffle
  687.  
  688. private double Error(double[][] trainData)
  689. {
  690. // average squared error per training item
  691. double sumSquaredError = 0.0;
  692. double[] xValues = new double[numInput]; // first numInput values in trainData
  693. double[] tValues = new double[numOutput]; // last numOutput values
  694.  
  695. // walk thru each training case. looks like (6.9 3.2 5.7 2.3) (0 0 1)
  696. for (int i = 0; i < trainData.Length; ++i)
  697. {
  698. Array.Copy(trainData[i], xValues, numInput);
  699. Array.Copy(trainData[i], numInput, tValues, 0, numOutput); // get target values
  700. double[] yValues = this.ComputeOutputs(xValues); // outputs using current weights
  701. for (int j = 0; j < numOutput; ++j)
  702. {
  703. double err = tValues[j] - yValues[j];
  704. sumSquaredError += err * err;
  705. }
  706. }
  707. return sumSquaredError / trainData.Length;
  708. } // MeanSquaredError
  709.  
  710. public double Accuracy(double[][] testData)
  711. {
  712. // percentage correct using winner-takes all
  713. int numCorrect = 0;
  714. int numWrong = 0;
  715. double[] xValues = new double[numInput]; // inputs
  716. double[] tValues = new double[numOutput]; // targets
  717. double[] yValues; // computed Y
  718.  
  719. for (int i = 0; i < testData.Length; ++i)
  720. {
  721. Array.Copy(testData[i], xValues, numInput); // get x-values
  722. Array.Copy(testData[i], numInput, tValues, 0, numOutput); // get t-values
  723. yValues = this.ComputeOutputs(xValues);
  724. int maxIndex = MaxIndex(yValues); // which cell in yValues has largest value?
  725. int tMaxIndex = MaxIndex(tValues);
  726.  
  727. if (maxIndex == tMaxIndex)
  728. ++numCorrect;
  729. else
  730. ++numWrong;
  731. }
  732. return (numCorrect * 1.0) / (numCorrect + numWrong);
  733. }
  734.  
  735. private static int MaxIndex(double[] vector) // helper for Accuracy()
  736. {
  737. // index of largest value
  738. int bigIndex = 0;
  739. double biggestVal = vector[0];
  740. for (int i = 0; i < vector.Length; ++i)
  741. {
  742. if (vector[i] > biggestVal)
  743. {
  744. biggestVal = vector[i];
  745. bigIndex = i;
  746. }
  747. }
  748. return bigIndex;
  749. }
  750. }
  751. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement