2 Stimmen

Warum erhalte ich eine Gewichtsmatrix voller NaNs?

(Hebbianisches Lernen)

Ich hatte die Aufgabe, die Oja-Lernregel und die Sanger-Lernregel in Matlab zu programmieren, um ein neuronales Netz zu trainieren. Dieses NN hat 6 Eingänge und 4 Ausgänge, und meine Trainingsmenge stammt aus einer multivariaten Gleichverteilung, wie Xi ~ U(-ai,ai) und ai!=aj, für alle i!=j

Dies sind die wichtigsten Dateien (die meisten Kommentare und oja.m wurden nicht berücksichtigt)

main.m

TS = generarVectoresUnif(6, [1, 4, 9, 36, 25, 16], 512);
TS = TS';
W = unifrnd(0,1,[4,6]);
% it not very fast. That's why I put 500 iterations
W_sanger = sanger(W,TS,500, 0.05)

generarVectoresUnif.m

function [ TS ] = generarVectoresUnif( dim, rangos, n )
dimensiones = int8(dim);
tamanio = int32(n);
TS = [];

for i = 1:dimensiones
   TS = [TS, unifrnd(-rangos(i), rangos(i), [tamanio, 1]) ];
end

sanger.m

( ANMERKUNG: W ist eine 4 x 6 große Matrix. Wi ist der Gewichtsvektor für die i -Stellungnahme. Wij \= (Wi)j . In diesem Beispiel, TS ist eine 6 x 512 große Matrix )

function [ W ] = sanger( W_init, trainingset, iteraciones , eta)

W = W_init;

% obtiene los tamaños desde los parametros de entrada
size_input = size(W,2);
size_output = size(W,1);
n_patterns = size(trainingset, 2);

% one-tenth part
diezmo = iteraciones/10;

for it = 1:iteraciones

   if 0 == mod(it, diezmo)
      disp(horzcat('Iteracion numero ', num2str(it), ' de ',num2str(iteraciones)));
   end

   % for each pattern
   for u = 1:n_patrones

      DeltaW = zeros(size(W));

      % Vi = sum{j=1...N} Wij * Xj
      V = W * trainingset(:,u);

      % sumatorias(i,j) is going to replace sum{k=1..i} Vk*Wkj
      sumatorias = zeros(size_output,size_input);
      for j = 1:size_input
         for k = 1:size_output
             % sumar de 1 hasta i, sin hacer otro ciclo
             sumatorias(k,j) = (V' .* [ones(1,k), zeros(1,size_output-k)]) * W(:,j);
         end
      end

       % calcula la variacion
       for i = 1:size_output
          for j=1:size_input
             % Delta Wij = eta * Vi * ( xj - sum{k=1..i} Vk*Wkj )
              DeltaW(i,j) = eta * V(i,1) * (trainingset(j,u) - sumatorias(i,j));
          end
       end

       W = W + DeltaW;      
       %W = 1/norm(W) * W; %<---is it necessary? [Hertz] doesn't mention it

  end

end

Können Sie mir bitte sagen, was ich falsch mache? Die Werte der Matrix wachsen sehr schnell. Ich habe das gleiche Problem mit oja.m

Ich habe es versucht:

  • Ersetzen von eta por 1/it --->NaN
  • Ersetzen von eta durch eine Exponentialfunktion der Anzahl der Iterationen --->ok, aber es ist nicht das, was ich erwartet habe
  • Unkommentiert W = 1/norm(W) * W; . Das funktioniert tatsächlich, aber es sollte nicht notwendig sein, oder doch?

1voto

mbatchkarov Punkte 14708

Sie brauchen kleine Werte von eta. Betrachten Sie Ihre Aktualisierungsregel:

DeltaW(i,j) = eta * V(i,1) * (trainingset(j,u) - sumatorias(i,j));

Wenn eta groß ist, DeltaW wird wahrscheinlich einen großen absoluten Wert haben (d.h. sehr groß, z.B. 100000, oder sehr klein, z.B. -111111). Beim nächsten Durchlauf der Schleife sumatorias(i,j) wird ziemlich groß sein, da sie eine Funktion der Gewichte ist. Je mehr Iterationen Sie haben, desto größer werden Ihre Gewichte, was schließlich zu einem Überlauf führt.

0voto

A.J. Punkte 938

Gut. Nach mehrere versucht, habe ich es geschafft.

Ich wähle einen relativ kleinen Wert von eta : 0.00001

W_sanger = sanger(W,TS,1000, 0.00001) 

Es ist immer noch langsam, weil es die Vorteile der Matrixmultiplikation nicht nutzt, die von Matlab optimiert wird.

Ich hoffe, es hilft anderen, nicht den gleichen Fehler zu machen.

Herzliche Grüße!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X