Softmax() funktion in Gradienten Update Algo

 

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