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 InicjalizujSiec(int[] numerki, double[] wejscia, int bias, int beta, bool CzyWagiZPliku, string path) { List SiecNeuronowa = new List(); 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 dodajWarstwy(List SiecNeuronowa, int ile) { for (int i = 0; i < ile; i++) SiecNeuronowa.Add(new Warstwa()); return SiecNeuronowa; } public static List dodajNeurony(List 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 dodajWartosciWejsciowe(List 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 obliczWyjscia(List 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 LosujWagi(int ile, int max, int min) { List nowy = new List(); for (int i = 0; i < ile; i++) nowy.Add(rand.NextDouble() * (max - min) + min); return nowy; } public static List dodajWagi(List 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 pobierzWagi(List 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 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 SiecNeuronowa, double[] d, double mi) { List blad = obliczBlad(SiecNeuronowa, d); List KorektaWag = new List(); for (int k = SiecNeuronowa.Count - 1; k >= 0; k--) { List KorektaWyj = korektaWyjsc(SiecNeuronowa, blad, KorektaWag, mi, k); List KorektaS = korektaS(SiecNeuronowa, KorektaWyj, k); zastosujZmiany(KorektaS,KorektaWyj,KorektaWag,SiecNeuronowa, k); } } //metody obsługujące propagację wsteczną public static List obliczBlad(List SiecNeuronowa, double[] d) { List blad = new List(); for (int i = 0; i < d.Length; i++) blad.Add(d[i] - SiecNeuronowa[SiecNeuronowa.Count - 1].Neurony[i].wyjscie); return blad; } public static List korektaWyjsc(List SiecNeuronowa, List blad, List KorektaWag, double mi, int k) { List KorektaWyj = new List(); 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 korektaS(List SiecNeuronowa, List KorektaWyj, int k) { List KorektaS = new List(); 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 korektaWejsc(List SiecNeuronowa, List KorektaS, int k, int j) { List KorektaWejsc = new List(); 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 KorektaS, List KorektaWyj, List KorektaWag, List SiecNeuronowa, int k) { for (int j = 0; j < KorektaS.Count; j++) { List 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 UczenieSieci(List SiecNeuronowa, List Options, List ExpectedValues, double mi, int ileEpok) { for (int i = 0; i < ileEpok; i++) { List tmp = new List(Options); List tmp2 = new List(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 Options = new List(); 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 ExpectedValues = new List(); 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 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 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 wagi = new List(); public List wejscie = new List(); 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 Neurony = new List(); } }