- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.IO;
- namespace ConsoleApplication6
- {
- public class Program
- {
- public static Random rand = new Random();
- // metoda odpowiedzialna za inicjalizację sieci
- public static List<Warstwa> InicjalizujSiec(int[] numerki, double[] wejscia, int bias, int beta, bool CzyWagiZPliku, string path)
- {
- List<Warstwa> SiecNeuronowa = new List<Warstwa>();
- SiecNeuronowa = dodajWarstwy(SiecNeuronowa, numerki.Length);
- SiecNeuronowa = dodajNeurony(SiecNeuronowa, numerki, bias, beta);
- if (CzyWagiZPliku)
- SiecNeuronowa = pobierzWagi(SiecNeuronowa, numerki, path);
- else
- SiecNeuronowa = dodajWagi(SiecNeuronowa, numerki);
- SiecNeuronowa = dodajWartosciWejsciowe(SiecNeuronowa, wejscia);
- SiecNeuronowa = obliczWyjscia(SiecNeuronowa);
- return SiecNeuronowa;
- }
- // metody obsługujące inicjalizację sieci
- public static List<Warstwa> dodajWarstwy(List<Warstwa> SiecNeuronowa, int ile)
- {
- for (int i = 0; i < ile; i++)
- SiecNeuronowa.Add(new Warstwa());
- return SiecNeuronowa;
- }
- public static List<Warstwa> dodajNeurony(List<Warstwa> SiecNeuronowa, int[] numerki, int bias, int beta)
- {
- for (int i = 0; i < numerki.Length; i++)
- for (int j = 0; j < numerki[i]; j++)
- SiecNeuronowa[i].Neurony.Add(new Neuron(bias, beta));
- return SiecNeuronowa;
- }
- public static List<Warstwa> dodajWartosciWejsciowe(List<Warstwa> SiecNeuronowa, double[] wejscia)
- {
- for (int i = 0; i < SiecNeuronowa[0].Neurony.Count; i++)
- {
- SiecNeuronowa[0].Neurony[i].wejscie.Clear();
- for (int j = 0; j < wejscia.Length; j++)
- SiecNeuronowa[0].Neurony[i].wejscie.Add(wejscia[j]);
- SiecNeuronowa[0].Neurony[i].obliczwyjscie();
- }
- return SiecNeuronowa;
- }
- public static List<Warstwa> obliczWyjscia(List<Warstwa> SiecNeuronowa)
- {
- for (int i = 0; i < SiecNeuronowa[0].Neurony.Count; i++)
- SiecNeuronowa[0].Neurony[i].obliczwyjscie();
- for (int i = 1; i < SiecNeuronowa.Count; i++)
- {
- for (int k = 0; k < SiecNeuronowa[i].Neurony.Count; k++)
- {
- SiecNeuronowa[i].Neurony[k].wejscie.Clear();
- for (int j = 0; j < SiecNeuronowa[i - 1].Neurony.Count; j++)
- {
- SiecNeuronowa[i].Neurony[k].wejscie.Add(SiecNeuronowa[i - 1].Neurony[j].wyjscie);
- SiecNeuronowa[i].Neurony[k].obliczwyjscie();
- }
- }
- }
- return SiecNeuronowa;
- }
- // metody obsługujące wagi
- public static List<double> LosujWagi(int ile, int max, int min)
- {
- List<double> nowy = new List<double>();
- for (int i = 0; i < ile; i++)
- nowy.Add(rand.NextDouble() * (max - min) + min);
- return nowy;
- }
- public static List<Warstwa> dodajWagi(List<Warstwa> SiecNeuronowa, int[] numerki)
- {
- for (int i = 0; i < SiecNeuronowa.Count; i++)
- for (int j = 0; j < numerki[i]; j++)
- if (i == 0)
- SiecNeuronowa[i].Neurony[j].wagi = LosujWagi(numerki[i] + 1, 1, -1);
- else
- SiecNeuronowa[i].Neurony[j].wagi = LosujWagi(numerki[i - 1] + 1, 1, -1);
- return SiecNeuronowa;
- }
- public static List<Warstwa> pobierzWagi(List<Warstwa> SiecNeuronowa, int[] numerki, string sciezka)
- {
- string[] lines = File.ReadAllLines(sciezka);
- int[] WzorSiecizPliku = lines[0].Split('/').Select(n => Convert.ToInt32(n)).ToArray();
- if (numerki.Length != WzorSiecizPliku.Length)
- throw new Exception("Ilość warstw się nie zgadza");
- for (int i = 0; i < numerki.Length; i++)
- if (numerki[i] != WzorSiecizPliku[i])
- throw new Exception("Ilość neuronów się nie zgadza");
- int k = 1;
- for (int i = 0; i < SiecNeuronowa.Count; i++)
- {
- for (int j = 0; j < SiecNeuronowa[i].Neurony.Count; j++)
- {
- SiecNeuronowa[i].Neurony[j].wagi = Array.ConvertAll(lines[k].Split('/'), Double.Parse).ToList();
- k++;
- }
- }
- return SiecNeuronowa;
- }
- public static void zapiszWagi(List<Warstwa> SiecNeuronowa, int[] numerki, string path)
- {
- string lines = "";
- lines += String.Join("/", numerki) + "\r\n";
- for (int i = 0; i < SiecNeuronowa.Count; i++)
- for (int j = 0; j < SiecNeuronowa[i].Neurony.Count; j++)
- lines += String.Join("/", SiecNeuronowa[i].Neurony[j].wagi.ToArray()) + "\r\n";
- System.IO.StreamWriter file = new System.IO.StreamWriter(path);
- file.WriteLine(lines);
- file.Close();
- }
- //Metoda odpowiedzialna za propagację wsteczną
- public static void propagacjaWsteczna(List<Warstwa> SiecNeuronowa, double[] d, double mi)
- {
- List<double> blad = obliczBlad(SiecNeuronowa, d);
- List<double> KorektaWag = new List<double>();
- for (int k = SiecNeuronowa.Count - 1; k >= 0; k--)
- {
- List<double> KorektaWyj = korektaWyjsc(SiecNeuronowa, blad, KorektaWag, mi, k);
- List<double> KorektaS = korektaS(SiecNeuronowa, KorektaWyj, k);
- zastosujZmiany(KorektaS,KorektaWyj,KorektaWag,SiecNeuronowa, k);
- }
- }
- //metody obsługujące propagację wsteczną
- public static List<double> obliczBlad(List<Warstwa> SiecNeuronowa, double[] d)
- {
- List<double> blad = new List<double>();
- for (int i = 0; i < d.Length; i++)
- blad.Add(d[i] - SiecNeuronowa[SiecNeuronowa.Count - 1].Neurony[i].wyjscie);
- return blad;
- }
- public static List<double> korektaWyjsc(List<Warstwa> SiecNeuronowa, List<double> blad, List<double> KorektaWag, double mi, int k)
- {
- List<double> KorektaWyj = new List<double>();
- if (k == SiecNeuronowa.Count - 1)
- for (int i = 0; i < SiecNeuronowa[k].Neurony.Count; i++)
- KorektaWyj.Add(mi * blad[i]);
- else
- for (int i = 0; i < KorektaWag.Count; i++)
- KorektaWyj.Add(KorektaWag[i]);
- return KorektaWyj;
- }
- public static List<double> korektaS(List<Warstwa> SiecNeuronowa, List<double> KorektaWyj, int k)
- {
- List<double> KorektaS = new List<double>();
- for (int i = 0; i < SiecNeuronowa[k].Neurony.Count; i++)
- KorektaS.Add(KorektaWyj[i] * SiecNeuronowa[k].Neurony[i].beta * SiecNeuronowa[k].Neurony[i].wyjscie * (1 - SiecNeuronowa[k].Neurony[i].wyjscie));
- return KorektaS;
- }
- public static List<double> korektaWejsc(List<Warstwa> SiecNeuronowa, List<double> KorektaS, int k, int j)
- {
- List<double> KorektaWejsc = new List<double>();
- KorektaWejsc.Add(SiecNeuronowa[k].Neurony[j].bias * KorektaS[j]);
- for (int i = 0; i < SiecNeuronowa[k].Neurony[j].wejscie.Count; i++)
- KorektaWejsc.Add(SiecNeuronowa[k].Neurony[j].wejscie[i] * KorektaS[j]);
- return KorektaWejsc;
- }
- public static void zastosujZmiany(List<double> KorektaS, List<double> KorektaWyj, List<double> KorektaWag, List<Warstwa> SiecNeuronowa, int k)
- {
- for (int j = 0; j < KorektaS.Count; j++)
- {
- List<double> KorektaWejsc = korektaWejsc(SiecNeuronowa, KorektaS, k, j);
- for (int i = 0; i < SiecNeuronowa[k].Neurony[j].wagi.Count; i++)
- {
- if (i != 0)
- KorektaWag.Add(SiecNeuronowa[k].Neurony[j].wagi[i] * KorektaS[j]);
- SiecNeuronowa[k].Neurony[j].wagi[i] += KorektaWejsc[i];
- }
- }
- }
- // Metoda ucząca sieć
- public static List<Warstwa> UczenieSieci(List<Warstwa> SiecNeuronowa, List<double[]> Options, List<double[]> ExpectedValues, double mi, int ileEpok)
- {
- for (int i = 0; i < ileEpok; i++)
- {
- List<double[]> tmp = new List<double[]>(Options);
- List<double[]> tmp2 = new List<double[]>(ExpectedValues);
- for (int j = 0; j < Options.Count; j++)
- {
- int index = rand.Next(tmp.Count);
- SiecNeuronowa = dodajWartosciWejsciowe(SiecNeuronowa, tmp[index]);
- SiecNeuronowa = obliczWyjscia(SiecNeuronowa);
- propagacjaWsteczna(SiecNeuronowa, tmp2[index], mi);
- tmp.RemoveAt(index);
- tmp2.RemoveAt(index);
- }
- }
- return SiecNeuronowa;
- }
- // main
- static void Main(string[] args)
- {
- List<double[]> Options = new List<double[]>();
- Options.Add(new double[] { 0, 0 });
- Options.Add(new double[] { 0, 1 });
- Options.Add(new double[] { 1, 0 });
- Options.Add(new double[] { 1, 1 });
- List<double[]> ExpectedValues = new List<double[]>();
- ExpectedValues.Add(new double[] { 0 });
- ExpectedValues.Add(new double[] { 1 });
- ExpectedValues.Add(new double[] { 1 });
- ExpectedValues.Add(new double[] { 0 });
- double[] wejscia = Options[2];
- double[] d = ExpectedValues[2];
- int[] numerki = new int[] { wejscia.Length, d.Length };
- string path = "d:\test2.txt";
- double mi = 0.1;
- int bias = 1;
- int beta = 1;
- int ileEpok = 3000;
- bool CzyWagiZPliku = false;
- bool CzyZapisacDoPliku = false;
- List<Warstwa> SiecNeuronowa = InicjalizujSiec(numerki, wejscia, bias, beta, CzyWagiZPliku, path);
- bool CzyNauczono = true;
- int ileUczen = 3000;
- while (CzyNauczono)
- {
- SiecNeuronowa = UczenieSieci(SiecNeuronowa, Options, ExpectedValues, mi, ileEpok);
- int counter = 0;
- for (int i = 0; i < Options.Count; i++)
- {
- double tmp = -1;
- SiecNeuronowa = dodajWartosciWejsciowe(SiecNeuronowa, Options[i]);
- SiecNeuronowa = obliczWyjscia(SiecNeuronowa);
- for (int j = 0; j < SiecNeuronowa[SiecNeuronowa.Count - 1].Neurony.Count; j++)
- {
- tmp = Math.Round(SiecNeuronowa[SiecNeuronowa.Count - 1].Neurony[j].wyjscie * 10);
- if (tmp == ExpectedValues[i][j] * 10)
- counter++;
- if (tmp - 1 == ExpectedValues[i][j] * 10)
- counter++;
- if (tmp + 1 == ExpectedValues[i][j] * 10)
- counter++;
- }
- }
- ileEpok = 100;
- Console.WriteLine("Uczenie: " + ileUczen);
- ileUczen += 100;
- if(ileUczen > 13000)
- if (counter == 8 || ileUczen > 20000)
- CzyNauczono = false;
- }
- for (int i = 0; i < Options.Count; i++)
- {
- Console.WriteLine("---------------------");
- SiecNeuronowa = dodajWartosciWejsciowe(SiecNeuronowa, Options[i]);
- SiecNeuronowa = obliczWyjscia(SiecNeuronowa);
- Console.WriteLine(SiecNeuronowa[1].Neurony[0].wyjscie);
- }
- if (CzyZapisacDoPliku)
- zapiszWagi(SiecNeuronowa, numerki, path);
- pokazSiec(SiecNeuronowa, numerki);
- Console.ReadLine();
- }
- // Wyświetlanie sieci w konsoli
- public static void pokazSiec(List<Warstwa> SiecNeuronowa, int[] numerki)
- {
- int max = numerki.Max();
- Console.WriteLine("Schemat sieci Neuronowej\r\n");
- Console.WriteLine(" L0 L1 L2 L3 L4 L5 L6 L7 L8 ...");
- for (int i = 0; i < max; i++)
- {
- if (i < 9)
- Console.Write(i + " ");
- else if (i < 12)
- Console.Write(". ");
- else
- Console.Write(" ");
- for (int j = 0; j < numerki.Length; j++)
- if (numerki[j] > i)
- Console.Write("N ");
- else
- Console.Write(" ");
- Console.WriteLine();
- }
- Console.WriteLine("\r\nWięcej informacji:");
- Console.WriteLine("1.dowiedz się więcej o wybranym neuronie");
- Console.WriteLine("2.kończy działanie programu");
- string inp = "";
- while (inp != "2")
- {
- Console.WriteLine("\r\nwybierz opcję");
- inp = Console.ReadLine();
- if (inp == "1")
- {
- Console.Write("podaj warstwę: ");
- string OX = Console.ReadLine();
- Console.Write("podaj neuron: ");
- string OY = Console.ReadLine();
- if (Convert.ToInt32(OX) < SiecNeuronowa.Count)
- if (Convert.ToInt32(OY) < SiecNeuronowa[Convert.ToInt32(OX)].Neurony.Count)
- {
- Console.WriteLine("\r\ninfo o neuronie: Warstwa " + OX + ", Numer: " + OY);
- Console.WriteLine("beta: " + SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].beta);
- Console.WriteLine("bias: " + SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].bias);
- Console.WriteLine("wagi: " + string.Join(" ", SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].wagi.ToArray()));
- Console.WriteLine("wejscia: " + string.Join(" ", SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].wejscie.ToArray()));
- Console.WriteLine("wyjście: " + SiecNeuronowa[Convert.ToInt32(OX)].Neurony[Convert.ToInt32(OY)].wyjscie);
- }
- else
- Console.WriteLine("Nie ma tylu neuronów");
- else
- Console.WriteLine("Nie ma tyle warstw!");
- }
- if (inp == "2")
- Console.WriteLine("Koniec programu");
- }
- }
- }
- public class Neuron
- {
- public List<double> wagi = new List<double>();
- public List<double> wejscie = new List<double>();
- public double beta;
- public double bias;
- public double wyjscie;
- public Neuron(int bias, int beta)
- {
- this.bias = bias;
- this.beta = beta;
- }
- public void obliczwyjscie()
- {
- double s = 0;
- s += bias * wagi[0];
- for (int i = 0; i < wejscie.Count; i++)
- s += wejscie[i] * wagi[i + 1];
- s = 1 / (1 + Math.Pow(Math.E, -beta * s));
- this.wyjscie = s;
- }
- }
- public class Warstwa
- {
- public List<Neuron> Neurony = new List<Neuron>();
- }
- }