Softmax() funktion in Gradienten Update Algo

Einloggen oder registrieren, um einen Kommentar zu schreiben
Bayne
745
Bayne  

Hallo,

(keine Angst sieht nur Viel aus, die eigentlichen Fragen sind ganz kurz und mit "XXX" gekennzeichnet (nur 2 stück)

einer der letzen schritte vor abschluss meines NN projektes ist die integration der Softmax funktion als aktivierungs der Outputneuronen.

folgender code ließ sich durch diverse interneteinträge zusammenbasteln:

double softmax(double x, double total)
   {
   return (x/total);
   }  
//derivative of softmax
double d_softmax(double x, double total, int j, int i)                       // XXX Frage1:    Was sind i & j ? Nummer des sendeneurons und Empfängerneurons ? oder vllt umgekehrt?
   {
   int delta_ij;
   if(i==j){delta_ij=1;}
   else{delta_ij=0;} // 0 Wert kann problematisch werden wenn wir die gewichtgradienten rausfinden wollen (ob negativ oder positiv, eine senkung der unerwünschten werte würde ja nicht statt finden oder?))
   
   return(softmax(x,total)*(delta_ij - softmax(x,total)));
   }  

Ich bin mir zu 90% sicher dass schonmal die feedforward integration korrekt ist. (für alle fälle poste ich ihn dennoch, der backropagation algo ist jedoch darunter)

         //feedforeward
         for (int l=0; l<outputlayer;l++)
              {
              for(int j=0; j<NeuronenArray[l+1]; j++) // calculate uncactivated Net values for receiving Neurons
                    {
                    double sumtemp = 0.0;
                    for(int i=0; i<NeuronenArray[l]; i++)
                            {
                            sumtemp += W[i][j][l] * aNet[i][l];
                            }
                    Net[j][l+1] = sumtemp + Bias[j][l+1]; // unactivated neuron
                                        
                    //calculate acitvation of neurons:                     
                    if(l== outputlayer)                     // calculate aNet (activated neurons) for the final layer
                          {
                          if(finalactivationfunction == "softmax") //calculate Softmax layer berechnen
                             {
                             if (j== NeuronenArray[l+1]-1)    //erst wenn wir alle Nets berechnet haben berechnen wir den Softmax layer (aNet werte) (solange werden nur die Net Werte berechnet)
                                {
                                double total =0; 
                                for(int jj=0; jj<NeuronenArray[l+1]; jj++)         // totalwert der Outputneuronen berechnen
                                   {
                                   total += Net[jj][l+1];
                                   }
                                for(int jjj=0; jjj<NeuronenArray[l+1]; jjj++)       // Neuronenwet durch totalwert teilen
                                   {
                                   aNet[jjj][l+1] = softmax(Net[jjj][l+1],total);
                                   }   
                                }   
                             }
                          else // if final activationfunction is !NOT! softmax: (e.g. tanh, ...) 
                             {
                             aNet[j][l+1] = finalactivation(Net[j][l+1]); //finalactivations are predefined
                             }
                          }  
             
                   else      // calculate aNet for layers before
                      {
                      aNet[j][l+1] = activation(Net[j][l+1]);}   
                      }        
              } 

Nun zum eigentlichen Ungestüm (im Weight update):

kann ich einfach so die funktion d_softmax für d_finalactivation einsetzen? (Sicher müsste ich noch den "total" wert der Neuronen berechnen, aber für welchen Layer l oder l-1 ?) ( XXX Frage 2)

       //backpropagation

         double E[][11]; ArrayResize(E,neuronenmax); // deklarierung einer ErrorMatrix die genauso groß ist wie Net oder aNet, mit ausßahme des ersten Layers bei aNet(==die X_Inputs des Netzes) E[][...][0] bleibt dann einfach immer null (& existiert nur zur vereinfachung der iteration)

         for (int l=outputlayer; l>0;l--) //l>1 weil über alle hiddenlayers iteriert wird, nicht aber über l==0, wobei es sich (in Net[][][]) um den InputLayer handelt
                {

                if (l==outputlayer) // Befüllung der Erromatrix miz outputerrorwerten
                   {
                   for (int j =0;j<NeuronenArray[l];j++)
                     {
                     E[j][l] = aNet[j][l]-Y_Vector[s][j];
                     }
                   } 

                 // Befüllung der Errormatrix
                 for (int i=0;i<NeuronenArray[l-1];i++) // ich gehe davon aus das das i in "i<neurons(j)" ein simpler tippfehler war und normal auch j wäre, stimmts? //XXX2
                     {
                     E[i][l-1]=0; // l ist hier das Layer, für das gerade der hidden error berechnet wird
                     for (int j=0; j<NeuronenArray[l]; j++)
                             {                                                     
                             E[i][l-1] += NormalizeDouble(E[j][l],10)*NormalizeDouble(W[i][j][l-1],10); // Normalizing only for computing purposes
                             }   
                     }    
                }

//Update Weights
 for (int l=outputlayer; l>0 ; l--)             // for every layer
                      {
                      for (int j=0; j<NeuronenArray[l];j++) //Empfängerneuron j   
                              {
                              for(int i=0; i<NeuronenArray[l-1];i++) //Sendeneuron i
                                      {
                                      if (l==outputlayer)        //calculate Gradients for
                                              {
                                              delta_W[i][j][l-1]= -(learningrate) * aNet[i][l-1] * d_finalactivation(Net[j][l]) * E[j][l];
                                              }
                                      else        //calculate Gradients for finalactivation                                              
                                              {
                                              delta_W[i][j][l-1]= -(learningrate) * aNet[i][l-1] * d_activation(Net[j][l]) * E[j][l];
                                              }
                                              
                                      W[i][j][l-1] += delta_W[i][j][l-1];         //Weight update

                                      if (i==NeuronenArray[l-1]-1)
                                         { Print("new Updated Weight W[",i,"][",j,"][",l,"] = ",W[i][j][l-1]);}
                                      }
                              }
                      }
Einloggen oder registrieren, um einen Kommentar zu schreiben