C# Rete Neurale in C#

Stato
Discussione chiusa ad ulteriori risposte.

1T1

Utente Silver
6 Gennaio 2017
117
41
0
98
Sto cercando di scrivere una rete neurale in C#, purtroppo però mi sono "bloccato" all'allenamento. Cioè sono riuscito a scriverlo, ma una volta avviato il programma gli output ogni tanto sono giusti mentre altre volte sono totalmente sballati! Potreste aiutarmi nell'impresa? Anche perché l'allenamento non mi è ancora completamente chiaro. Non fate caso ad eventuali prove che sto facendo, e grazie a chi mi aiuterà...

C#:
public static void retiNeurali(int nNeuroniInput, int nNeuroniHidden, int nNeuroniOutput)
        {
            //valori dei neuroni
            double[] input = new double[nNeuroniInput];
            double[] hidden = new double[nNeuroniHidden];
            double[] output = new double[nNeuroniOutput];

            //pesi
            double[][] pesoInputHidden = new double[nNeuroniInput][];
            double[][] pesoHiddenOutput = new double[nNeuroniHidden][];

            //bias
            double[] biasInputHidden = new double[nNeuroniHidden];
            double[] biasHiddenOutput = new double[nNeuroniOutput];

            Random random = new Random();

            //assegnazione esempio
            input[0] = 0.55;
            input[1] = 82;

            //assegnamento casuale dei pesi
            for (int i = 0; i < pesoInputHidden.Length; i++)
            {
                pesoInputHidden[i] = new double[nNeuroniHidden];
                for (int j = 0; j < pesoInputHidden[i].Length; j++)
                    pesoInputHidden[i][j] = random.NextDouble();
            }
            for (int i = 0; i < pesoHiddenOutput.Length; i++)
            {
                pesoHiddenOutput[i] = new double[nNeuroniOutput];
                for (int j = 0; j < pesoHiddenOutput[i].Length; j++)
                    pesoHiddenOutput[i][j] = random.NextDouble();
            }

            //assegnamento bias
            for (int i = 0; i < biasInputHidden.Length; i++)
                biasInputHidden[i] = random.NextDouble();
            for (int i = 0; i < biasHiddenOutput.Length; i++)
                biasHiddenOutput[i] = random.NextDouble();


            //calcolo
            hidden = attivazione(hidden, input, pesoInputHidden, biasInputHidden);
            output = attivazione(output, hidden, pesoHiddenOutput, biasHiddenOutput);

            for (int i = 0; i < 100000; i++)
            {
                allenamento(input, hidden, output,
                            pesoInputHidden, pesoHiddenOutput,
                                biasInputHidden, biasHiddenOutput);
            }
            Strumenti strumenti = new Strumenti();

            string strOutput = "";

            strOutput += "|Input:" + input[0].ToString() + "-" + input[1].ToString() + " | output" + output[0].ToString() + "|\n";
            strumenti.scrivi_file("lol.txt", strOutput);
        }

        /// <summary>
        /// sigmoide matematica
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        private static double sig(double x)
        {
            return 1 / (1 + Math.Exp(-x));
        }

        private static double[] attivazione(double[] valori, double[] valoriPrecedenti, double[][] pesoValori, double[] biasValori)
        {
            double[] risultato = new double[valori.Length];

            //a1 = sig(pesoA * a0) + b
            for(int i = 0; i < valori.Length; i++)
            {
                for (int j = 0; j < valoriPrecedenti.Length; j++)
                    risultato[i] += pesoValori[j][i] * valoriPrecedenti[j];
                risultato[i] += biasValori[i];
            }

            /*//applica la sigmoide
            for (int i = 0; i < risultato.Length; i++)
                risultato[i] = sig(risultato[i]);*/

            return risultato;
        }

        private static void allenamento(double[] neuroniIn, double[] neuroniH, double[] neuroniOut,
                                    double[][] pesoIH, double[][] pesoHO,
                                        double[] biasIH, double[] biasHO)
        {
            double[] errore = new double[neuroniOut.Length];
            double[][] errorePesoIH = new double[neuroniIn.Length][];
            double[][] errorePesoHO = new double[neuroniH.Length][];

            double outputGiusto = 0/* = new double[neuroniOut.Length]*/;

            double[] deltaIH = new double[neuroniH.Length];
            double[] deltaHO = new double[neuroniOut.Length];

            double[][] nuoviPesi;
            double[] nuoviBias;

            const double learnRate = 0.5;

            Random random = new Random();

            for (int i = 0; i < neuroniIn.Length; i++)
            {
                neuroniIn[i] = random.Next(0, 100);
                outputGiusto += neuroniIn[i];
            }

            for (int i = 0; i < errorePesoHO.Length; i++)
                errorePesoHO[i] = new double[neuroniOut.Length];
            for (int i = 0; i < errorePesoIH.Length; i++)
                errorePesoIH[i] = new double[neuroniH.Length];
            

            //calcolo dell'errore
            for (int i = 0; i < errore.Length; i++)
                errore[i] = outputGiusto/*[i] */- neuroniOut[i];

            //assegna il delta(da hidden a output) dell'errore
            for(int i = 0; i < deltaHO.Length; i++)
                deltaHO[i] = errore[i] * (neuroniOut[i] * (1 - neuroniOut[i]));

            //calcola ed assegna l'errore ad ogni peso
            for (int i = 0; i < pesoHO.Length; i++)
                for (int j = 0; j < pesoHO[i].Length; j++)
                    errorePesoHO[i][j] = deltaHO[j] * pesoHO[i][j];

            //regola il deltaIH ------------------------------------------------------------ non credo vada bene
            for (int i = 0; i < pesoHO.Length; i++)
                for (int j = 0; j < pesoHO[i].Length; j++)
                    deltaIH[i] += errorePesoHO[i][j] * (neuroniH[i] * (1 - neuroniH[i]));

            //set (hidden - output)
            nuoviPesi = pesoHO;
            for (int i = 0; i < nuoviPesi.Length; i++)
                for (int j = 0; j < nuoviPesi[i].Length; j++)
                    nuoviPesi[i][j] = aggiustaPeso(neuroniOut[j], pesoHO[i][j], learnRate, deltaHO[j]);
           pesoHO = nuoviPesi;

            //set (hidden - output) nuovi bias
            nuoviBias = biasHO;
            for (int i = 0; i < nuoviBias.Length; i++)
                nuoviBias[i] += learnRate * deltaHO[i];
            biasHO = nuoviBias;

            //set (input - hidden) nuovi pesi
            nuoviPesi = pesoIH;
            for (int i = 0; i < nuoviPesi.Length; i++)
                for (int j = 0; j < nuoviPesi[i].Length; j++)
                    nuoviPesi[i][j] = aggiustaPeso(neuroniH[i], pesoIH[i][j], learnRate, deltaIH[i]);
            pesoIH = nuoviPesi;

            //set (input - hidden) nuovi bias
            nuoviBias = biasIH;
            for (int i = 0; i < nuoviBias.Length; i++)
                nuoviBias[i] += learnRate * deltaIH[i];
            biasIH = nuoviBias;
        }
        private static double aggiustaPeso(double neuroneSuccessivo, double peso, double learnRate, double delta)
        {
            return peso + (neuroneSuccessivo * learnRate * delta);
        }
    }
 
Il risultato dipende dai valori che ti genera l'allenamento, così facendo a volte ti va bene e a volte no, ti devi monitorare il risultato e fargli rifare l'allenamento fino a che non "impara" a dare il risultato corretto.
In pratica la rete neurale opera in modo casuale fino a che non inizia ad operare correttamente, ma prima di arrivare al risultato fa tanti errori e qualcuno deve dirgli che gli errori sono tali.
Tu lanci il programma e vedi il risultato e poi lo riapri in pratica mi sembra di capire. Quindi non impara nulla e ricomincia sempre da capo.
Quando sbaglia in backpropagation deve dire al neurone precedente di cambiare.
Se A comunica con B e B riceve un dato sbagliato deve dire ad A di cambiare e fin qui ci siamo, però deve durare l'allenamento fino a che tu non sei soddisfatto.
Mi pare che il termine sia backpropagation supervisionata se vuoi cercare qualcosa, purtroppo non è argomento che conosco più di tanto.
 
  • Mi piace
Reazioni: </Singh>™
Stato
Discussione chiusa ad ulteriori risposte.