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);
}
}