Facebook
From Burly Cat, 3 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 132
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.IO;
  7.  
  8. namespace ConsoleApplication6
  9. {
  10.     public class Program
  11.     {
  12.         public static Random rand = new Random();
  13.  
  14.         // metoda odpowiedzialna za inicjalizację sieci
  15.  
  16.         public static List<Warstwa> InicjalizujSiec(int[] numerki, double[] wejscia, int bias, int beta, bool CzyWagiZPliku, string path)
  17.         {
  18.             List<Warstwa> SiecNeuronowa = new List<Warstwa>();
  19.             SiecNeuronowa = dodajWarstwy(SiecNeuronowa, numerki.Length);
  20.             SiecNeuronowa = dodajNeurony(SiecNeuronowa, numerki, bias, beta);
  21.             if (CzyWagiZPliku)
  22.                 SiecNeuronowa = pobierzWagi(SiecNeuronowa, numerki, path);
  23.             else
  24.                 SiecNeuronowa = dodajWagi(SiecNeuronowa, numerki);
  25.             SiecNeuronowa = dodajWartosciWejsciowe(SiecNeuronowa, wejscia);
  26.             SiecNeuronowa = obliczWyjscia(SiecNeuronowa);
  27.             return SiecNeuronowa;
  28.         }
  29.  
  30.         // metody obsługujące inicjalizację sieci
  31.  
  32.         public static List<Warstwa> dodajWarstwy(List<Warstwa> SiecNeuronowa, int ile)
  33.         {
  34.             for (int i = 0; i < ile; i++)
  35.                 SiecNeuronowa.Add(new Warstwa());
  36.             return SiecNeuronowa;
  37.         }
  38.  
  39.         public static List<Warstwa> dodajNeurony(List<Warstwa> SiecNeuronowa, int[] numerki, int bias, int beta)
  40.         {
  41.             for (int i = 0; i < numerki.Length; i++)
  42.                 for (int j = 0; j < numerki[i]; j++)
  43.                     SiecNeuronowa[i].Neurony.Add(new Neuron(bias, beta));
  44.             return SiecNeuronowa;
  45.         }
  46.  
  47.         public static List<Warstwa> dodajWartosciWejsciowe(List<Warstwa> SiecNeuronowa, double[] wejscia)
  48.         {
  49.             for (int i = 0; i < SiecNeuronowa[0].Neurony.Count; i++)
  50.             {
  51.                 SiecNeuronowa[0].Neurony[i].wejscie.Clear();
  52.                 for (int j = 0; j < wejscia.Length; j++)
  53.                     SiecNeuronowa[0].Neurony[i].wejscie.Add(wejscia[j]);
  54.                 SiecNeuronowa[0].Neurony[i].obliczwyjscie();
  55.             }
  56.             return SiecNeuronowa;
  57.         }
  58.  
  59.         public static List<Warstwa> obliczWyjscia(List<Warstwa> SiecNeuronowa)
  60.         {
  61.             for (int i = 0; i < SiecNeuronowa[0].Neurony.Count; i++)
  62.                 SiecNeuronowa[0].Neurony[i].obliczwyjscie();
  63.             for (int i = 1; i < SiecNeuronowa.Count; i++)
  64.             {
  65.                 for (int k = 0; k < SiecNeuronowa[i].Neurony.Count; k++)
  66.                 {
  67.                     SiecNeuronowa[i].Neurony[k].wejscie.Clear();
  68.                     for (int j = 0; j < SiecNeuronowa[i - 1].Neurony.Count; j++)
  69.                     {
  70.                         SiecNeuronowa[i].Neurony[k].wejscie.Add(SiecNeuronowa[i - 1].Neurony[j].wyjscie);
  71.                         SiecNeuronowa[i].Neurony[k].obliczwyjscie();
  72.                     }
  73.                 }
  74.             }
  75.             return SiecNeuronowa;
  76.         }
  77.  
  78.         // metody obsługujące wagi
  79.  
  80.         public static List<double> LosujWagi(int ile, int max, int min)
  81.         {
  82.             List<double> nowy = new List<double>();
  83.             for (int i = 0; i < ile; i++)
  84.                 nowy.Add(rand.NextDouble() * (max - min) + min);
  85.             return nowy;
  86.         }
  87.  
  88.         public static List<Warstwa> dodajWagi(List<Warstwa> SiecNeuronowa, int[] numerki)
  89.         {
  90.             for (int i = 0; i < SiecNeuronowa.Count; i++)
  91.                 for (int j = 0; j < numerki[i]; j++)
  92.                     if (i == 0)
  93.                         SiecNeuronowa[i].Neurony[j].wagi = LosujWagi(numerki[i] + 1, 1, -1);
  94.                     else
  95.                         SiecNeuronowa[i].Neurony[j].wagi = LosujWagi(numerki[i - 1] + 1, 1, -1);
  96.             return SiecNeuronowa;
  97.         }
  98.  
  99.         public static List<Warstwa> pobierzWagi(List<Warstwa> SiecNeuronowa, int[] numerki, string sciezka)
  100.         {
  101.             string[] lines = File.ReadAllLines(sciezka);
  102.             int[] WzorSiecizPliku = lines[0].Split('/').Select(n => Convert.ToInt32(n)).ToArray();
  103.  
  104.             if (numerki.Length != WzorSiecizPliku.Length)
  105.                 throw new Exception("Ilość warstw się nie zgadza");
  106.  
  107.             for (int i = 0; i < numerki.Length; i++)
  108.                 if (numerki[i] != WzorSiecizPliku[i])
  109.                     throw new Exception("Ilość neuronów się nie zgadza");
  110.  
  111.             int k = 1;
  112.             for (int i = 0; i < SiecNeuronowa.Count; i++)
  113.             {
  114.                 for (int j = 0; j < SiecNeuronowa[i].Neurony.Count; j++)
  115.                 {
  116.                     SiecNeuronowa[i].Neurony[j].wagi = Array.ConvertAll(lines[k].Split('/'), Double.Parse).ToList();
  117.                     k++;
  118.                 }
  119.             }
  120.  
  121.             return SiecNeuronowa;
  122.         }
  123.  
  124.         public static void zapiszWagi(List<Warstwa> SiecNeuronowa, int[] numerki, string path)
  125.         {
  126.             string lines = "";
  127.  
  128.             lines += String.Join("/", numerki) + "\r\n";
  129.             for (int i = 0; i < SiecNeuronowa.Count; i++)
  130.                 for (int j = 0; j < SiecNeuronowa[i].Neurony.Count; j++)
  131.                     lines += String.Join("/", SiecNeuronowa[i].Neurony[j].wagi.ToArray()) + "\r\n";
  132.  
  133.             System.IO.StreamWriter file = new System.IO.StreamWriter(path);
  134.             file.WriteLine(lines);
  135.             file.Close();
  136.         }
  137.  
  138.         //Metoda odpowiedzialna za propagację wsteczną
  139.  
  140.         public static void propagacjaWsteczna(List<Warstwa> SiecNeuronowa, double[] d, double mi)
  141.         {
  142.             List<double> blad = obliczBlad(SiecNeuronowa, d);
  143.             List<double> KorektaWag = new List<double>();
  144.  
  145.             for (int k = SiecNeuronowa.Count - 1; k >= 0; k--)
  146.             {
  147.                 List<double> KorektaWyj = korektaWyjsc(SiecNeuronowa, blad, KorektaWag, mi, k);
  148.                 List<double> KorektaS = korektaS(SiecNeuronowa, KorektaWyj, k);
  149.                 zastosujZmiany(KorektaS,KorektaWyj,KorektaWag,SiecNeuronowa, k);
  150.             }
  151.         }
  152.  
  153.  
  154.         //metody obsługujące propagację wsteczną
  155.  
  156.         public static List<double> obliczBlad(List<Warstwa> SiecNeuronowa, double[] d)
  157.         {
  158.             List<double> blad = new List<double>();
  159.             for (int i = 0; i < d.Length; i++)
  160.                 blad.Add(d[i] - SiecNeuronowa[SiecNeuronowa.Count - 1].Neurony[i].wyjscie);
  161.             return blad;
  162.         }
  163.  
  164.         public static List<double> korektaWyjsc(List<Warstwa> SiecNeuronowa, List<double> blad, List<double> KorektaWag, double mi, int k)
  165.         {
  166.             List<double> KorektaWyj = new List<double>();
  167.             if (k == SiecNeuronowa.Count - 1)
  168.                 for (int i = 0; i < SiecNeuronowa[k].Neurony.Count; i++)
  169.                     KorektaWyj.Add(mi * blad[i]);
  170.             else
  171.                 for (int i = 0; i < KorektaWag.Count; i++)
  172.                     KorektaWyj.Add(KorektaWag[i]);
  173.             return KorektaWyj;
  174.         }
  175.  
  176.         public static List<double> korektaS(List<Warstwa> SiecNeuronowa, List<double> KorektaWyj, int k)
  177.         {
  178.             List<double> KorektaS = new List<double>();
  179.             for (int i = 0; i < SiecNeuronowa[k].Neurony.Count; i++)
  180.                 KorektaS.Add(KorektaWyj[i] * SiecNeuronowa[k].Neurony[i].beta * SiecNeuronowa[k].Neurony[i].wyjscie * (1 - SiecNeuronowa[k].Neurony[i].wyjscie));
  181.             return KorektaS;
  182.         }
  183.  
  184.         public static List<double> korektaWejsc(List<Warstwa> SiecNeuronowa, List<double> KorektaS, int k, int j)
  185.         {
  186.             List<double> KorektaWejsc = new List<double>();
  187.             KorektaWejsc.Add(SiecNeuronowa[k].Neurony[j].bias * KorektaS[j]);
  188.             for (int i = 0; i < SiecNeuronowa[k].Neurony[j].wejscie.Count; i++)
  189.                 KorektaWejsc.Add(SiecNeuronowa[k].Neurony[j].wejscie[i] * KorektaS[j]);
  190.             return KorektaWejsc;
  191.         }
  192.  
  193.         public static void zastosujZmiany(List<double> KorektaS, List<double> KorektaWyj, List<double> KorektaWag, List<Warstwa> SiecNeuronowa, int k)
  194.         {
  195.             for (int j = 0; j < KorektaS.Count; j++)
  196.             {
  197.                 List<double> KorektaWejsc = korektaWejsc(SiecNeuronowa, KorektaS, k, j);
  198.                 for (int i = 0; i < SiecNeuronowa[k].Neurony[j].wagi.Count; i++)
  199.                 {
  200.                     if (i != 0)
  201.                         KorektaWag.Add(SiecNeuronowa[k].Neurony[j].wagi[i] * KorektaS[j]);
  202.                     SiecNeuronowa[k].Neurony[j].wagi[i] += KorektaWejsc[i];
  203.                 }
  204.             }
  205.         }
  206.  
  207.         // Metoda ucząca sieć
  208.  
  209.         public static List<Warstwa> UczenieSieci(List<Warstwa> SiecNeuronowa, List<double[]> Options, List<double[]> ExpectedValues, double mi, int ileEpok)
  210.         {
  211.             for (int i = 0; i < ileEpok; i++)
  212.             {
  213.                 List<double[]> tmp = new List<double[]>(Options);
  214.                 List<double[]> tmp2 = new List<double[]>(ExpectedValues);
  215.                 for (int j = 0; j < Options.Count; j++)
  216.                 {
  217.                     int index = rand.Next(tmp.Count);
  218.                     SiecNeuronowa = dodajWartosciWejsciowe(SiecNeuronowa, tmp[index]);
  219.                     SiecNeuronowa = obliczWyjscia(SiecNeuronowa);
  220.                     propagacjaWsteczna(SiecNeuronowa, tmp2[index], mi);
  221.                     tmp.RemoveAt(index);
  222.                     tmp2.RemoveAt(index);
  223.                 }
  224.             }
  225.             return SiecNeuronowa;
  226.         }
  227.  
  228.         // main
  229.  
  230.         static void Main(string[] args)
  231.         {
  232.             List<double[]> Options = new List<double[]>();
  233.             Options.Add(new double[] { 0, 0 });
  234.             Options.Add(new double[] { 0, 1 });
  235.             Options.Add(new double[] { 1, 0 });
  236.             Options.Add(new double[] { 1, 1 });
  237.             List<double[]> ExpectedValues = new List<double[]>();
  238.             ExpectedValues.Add(new double[] { 0 });
  239.             ExpectedValues.Add(new double[] { 1 });
  240.             ExpectedValues.Add(new double[] { 1 });
  241.             ExpectedValues.Add(new double[] { 0 });
  242.  
  243.  
  244.             double[] wejscia = Options[2];
  245.             double[] d = ExpectedValues[2];
  246.  
  247.             int[] numerki = new int[] { wejscia.Length, d.Length };
  248.  
  249.             string path = "d:\test2.txt";
  250.             double mi = 0.1;
  251.             int bias = 1;
  252.             int beta = 1;
  253.             int ileEpok = 3000;
  254.             bool CzyWagiZPliku = false;
  255.             bool CzyZapisacDoPliku = false;
  256.  
  257.             List<Warstwa> SiecNeuronowa = InicjalizujSiec(numerki, wejscia, bias, beta, CzyWagiZPliku, path);
  258.  
  259.  
  260.             bool CzyNauczono = true;
  261.             int ileUczen = 3000;
  262.  
  263.             while (CzyNauczono)
  264.             {
  265.                 SiecNeuronowa = UczenieSieci(SiecNeuronowa, Options, ExpectedValues, mi, ileEpok);
  266.                 int counter = 0;
  267.                 for (int i = 0; i < Options.Count; i++)
  268.                 {
  269.                     double tmp = -1;
  270.                     SiecNeuronowa = dodajWartosciWejsciowe(SiecNeuronowa, Options[i]);
  271.                     SiecNeuronowa = obliczWyjscia(SiecNeuronowa);
  272.                     for (int j = 0; j < SiecNeuronowa[SiecNeuronowa.Count - 1].Neurony.Count; j++)
  273.                     {
  274.                         tmp = Math.Round(SiecNeuronowa[SiecNeuronowa.Count - 1].Neurony[j].wyjscie * 10);
  275.                         if (tmp == ExpectedValues[i][j] * 10)
  276.                             counter++;
  277.                         if (tmp - 1 == ExpectedValues[i][j] * 10)
  278.                             counter++;
  279.                         if (tmp + 1 == ExpectedValues[i][j] * 10)
  280.                             counter++;
  281.                     }
  282.                 }
  283.                 ileEpok = 100;
  284.                 Console.WriteLine("Uczenie: " + ileUczen);
  285.                 ileUczen += 100;
  286.                 if(ileUczen > 13000)
  287.                     if (counter == 8 || ileUczen > 20000)
  288.                         CzyNauczono = false;
  289.             }
  290.  
  291.             for (int i = 0; i < Options.Count; i++)
  292.             {
  293.                 Console.WriteLine("---------------------");
  294.                 SiecNeuronowa = dodajWartosciWejsciowe(SiecNeuronowa, Options[i]);
  295.                 SiecNeuronowa = obliczWyjscia(SiecNeuronowa);
  296.                 Console.WriteLine(SiecNeuronowa[1].Neurony[0].wyjscie);
  297.             }
  298.  
  299.             if (CzyZapisacDoPliku)
  300.                 zapiszWagi(SiecNeuronowa, numerki, path);
  301.  
  302.             pokazSiec(SiecNeuronowa, numerki);
  303.  
  304.             Console.ReadLine();
  305.         }
  306.  
  307.  
  308.         // Wyświetlanie sieci w konsoli
  309.  
  310.         public static void pokazSiec(List<Warstwa> SiecNeuronowa, int[] numerki)
  311.         {
  312.             int max = numerki.Max();
  313.             Console.WriteLine("Schemat sieci Neuronowej\r\n");
  314.             Console.WriteLine("    L0   L1   L2   L3   L4   L5   L6   L7   L8   ...");
  315.             for (int i = 0; i < max; i++)
  316.             {
  317.                 if (i < 9)
  318.                     Console.Write(i + "   ");
  319.                 else if (i < 12)
  320.                     Console.Write(".   ");
  321.                 else
  322.                     Console.Write("    ");
  323.                 for (int j = 0; j < numerki.Length; j++)
  324.                     if (numerki[j] > i)
  325.                         Console.Write("N    ");
  326.                     else
  327.                         Console.Write("     ");
  328.                 Console.WriteLine();
  329.             }
  330.             Console.WriteLine("\r\nWięcej informacji:");
  331.             Console.WriteLine("1.dowiedz się więcej o wybranym neuronie");
  332.             Console.WriteLine("2.kończy działanie programu");
  333.  
  334.             string inp = "";
  335.             while (inp != "2")
  336.             {
  337.                 Console.WriteLine("\r\nwybierz opcję");
  338.                 inp = Console.ReadLine();
  339.                 if (inp == "1")
  340.                 {
  341.                     Console.Write("podaj warstwę: ");
  342.                     string OX = Console.ReadLine();
  343.                     Console.Write("podaj neuron: ");
  344.                     string OY = Console.ReadLine();
  345.                     if (Convert.ToInt32(OX) < SiecNeuronowa.Count)
  346.                         if (Convert.ToInt32(OY) < SiecNeuronowa[Convert.ToInt32(OX)].Neurony.Count)
  347.                         {
  348.                             Console.WriteLine("\r\ninfo o neuronie: Warstwa " + OX + ", Numer: " + OY);
  349.                             Console.WriteLine("beta: " + SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].beta);
  350.                             Console.WriteLine("bias: " + SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].bias);
  351.                             Console.WriteLine("wagi: " + string.Join(" ", SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].wagi.ToArray()));
  352.                             Console.WriteLine("wejscia: " + string.Join(" ", SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].wejscie.ToArray()));
  353.                             Console.WriteLine("wyjście: " + SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].wyjscie);
  354.                         }
  355.                         else
  356.                             Console.WriteLine("Nie ma tylu neuronów");
  357.                     else
  358.                         Console.WriteLine("Nie ma tyle warstw!");
  359.                 }
  360.                 if (inp == "2")
  361.                     Console.WriteLine("Koniec programu");
  362.             }
  363.         }
  364.  
  365.     }
  366.  
  367.     public class Neuron
  368.     {
  369.         public List<double> wagi = new List<double>();
  370.         public List<double> wejscie = new List<double>();
  371.         public double beta;
  372.         public double bias;
  373.         public double wyjscie;
  374.  
  375.         public Neuron(int bias, int beta)
  376.         {
  377.             this.bias = bias;
  378.             this.beta = beta;
  379.         }
  380.  
  381.         public void obliczwyjscie()
  382.         {
  383.             double s = 0;
  384.  
  385.             s += bias * wagi[0];
  386.             for (int i = 0; i < wejscie.Count; i++)
  387.                 s += wejscie[i] * wagi[i + 1];
  388.  
  389.             s = 1 / (1 + Math.Pow(Math.E, -beta * s));
  390.  
  391.             this.wyjscie = s;
  392.         }
  393.  
  394.     }
  395.  
  396.     public class Warstwa
  397.     {
  398.         public List<Neuron> Neurony = new List<Neuron>();
  399.     }
  400. }
  401.