2012-11-06 23 views
6

Próbuję zaimplementować regresję NN, która ma 3 warstwy (1 wejście, 1 ukryta i 1 warstwa wyjściowa z ciągłym wynikiem). Jako podstawę wziąłem klasyfikacji NN z coursera.org klasy, ale zmieniło funkcję kosztów i obliczenia gradientu tak aby dopasować problem regresji (a nie klasyfikacji jeden):Gradient w ciągłej regresji przy użyciu sieci neuronowej

Moja nnCostFunction teraz brzmi:

function [J grad] = nnCostFunctionLinear(nn_params, ... 
            input_layer_size, ... 
            hidden_layer_size, ... 
            num_labels, ... 
            X, y, lambda) 

Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), ... 
       hidden_layer_size, (input_layer_size + 1)); 

Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), ... 
       num_labels, (hidden_layer_size + 1)); 

m = size(X, 1); 

a1 = X; 
a1 = [ones(m, 1) a1]; 
a2 = a1 * Theta1'; 
a2 = [ones(m, 1) a2]; 
a3 = a2 * Theta2'; 
Y = y; 

J = 1/(2*m)*sum(sum((a3 - Y).^2)) 

th1 = Theta1; 
th1(:,1) = 0; %set bias = 0 in reg. formula 
th2 = Theta2; 
th2(:,1) = 0; 

t1 = th1.^2; 
t2 = th2.^2; 
th = sum(sum(t1)) + sum(sum(t2)); 
th = lambda * th/(2*m); 
J = J + th; %regularization 


del_3 = a3 - Y; 
t1 = del_3'*a2; 
Theta2_grad = 2*(t1)/m + lambda*th2/m; 

t1 = del_3 * Theta2; 
del_2 = t1 .* a2; 
del_2 = del_2(:,2:end); 
t1 = del_2'*a1; 
Theta1_grad = 2*(t1)/m + lambda*th1/m; 

grad = [Theta1_grad(:) ; Theta2_grad(:)]; 
end 

Następnie używam tego func w algorytmie fmincg, ale w pierwszych iteracjach fmincg koniec to działa. Myślę, że mój gradient jest nieprawidłowy, ale nie mogę znaleźć błędu.

Czy ktoś może pomóc?

+0

Cześć Michaił, to było pytanie ponad rok temu, ale zastanawiałem się, czy już rozwiązałeś ten problem? Właściwie inny facet zadał to samo, a ja dostarczyłem tam mój kod, w porównaniu z testem NNGradients Andrew Nga (lambda) i uzyskałem relatywną różnicę 1e-4: http://stackoverflow.com/questions/20648422/neural-networks-sigmoid- Funkcja aktywująca-do-ciągłej-zmiennej-wyjściowej/20650561 # 20650561 Jeśli już rozwiązałeś ten problem i uzyskałeś jeszcze mniej względną różnicę, zaktualizuj go, odpowiadając na własne pytanie; w przeciwnym razie mam nadzieję, że mój kod jest pomocny. Dzięki – lennon310

+0

jaki to jest język? to jest * nie * oktawa/matlab (to jest to, czego wykładał Prof. Ng ..) – javadba

+0

@javadba, oktawa –

Odpowiedz

1

Jeśli dobrze rozumiem, twój pierwszy blok kodu (patrz poniżej) -

m = size(X, 1); 

a1 = X; 
a1 = [ones(m, 1) a1]; 
a2 = a1 * Theta1'; 
a2 = [ones(m, 1) a2]; 
a3 = a2 * Theta2'; 
Y = y; 

jest dostać wyjście (3) w warstwie wyjściowej.

Slajdy Ng dotyczące NN mają poniższą konfigurację do obliczenia (3). Różni się od tego, co przedstawia Twój kod.

  • w warstwie środkowy/wyjścia, nie robią funkcję aktywacji g, na przykład, sigmoid funkcję.

enter image description here

Pod względem funkcji kosztu J bez warunków legalizacji, zjeżdżalnie NG zawiera wzoru:

enter image description here

ja nie rozumiem, dlaczego można obliczyć go za pomocą:

J = 1/(2*m)*sum(sum((a3 - Y).^2)) 

ponieważ jesteś z wyłączeniem funkcji log.

+0

log() i sigmoid() - podejście do regresji logicznej NN. W przykładach kursu jest to wykrywanie raka, ale chcę przewidzieć koszty domu –

1

Mikhaill, Grałem też z NN dla ciągłej regresji i miałem podobne problemy w pewnym momencie. Najlepszym rozwiązaniem byłoby przetestowanie obliczeń gradientowych na podstawie obliczeń numerycznych przed uruchomieniem modelu. Jeśli to nie jest poprawne, fmincg nie będzie w stanie wyszkolić modelu. (Btw, zniechęcam cię do korzystania z gradientu liczbowego, ponieważ czas jest znacznie większy).

Biorąc pod uwagę, że wziąłeś tę ideę z klasy Coursea Ng, wprowadzę możliwe rozwiązanie, aby spróbować użyć tej samej notacji dla Octave.

% Cost function without regularization. 
    J = 1/2/m^2*sum((a3-Y).^2); 

    % In case it´s needed, regularization term is added (i.e. for Training). 
    if (reg==true); 
J=J+lambda/2/m*(sum(sum(Theta1(:,2:end).^2))+sum(sum(Theta2(:,2:end).^2))); 
    endif; 

    % Derivatives are computed for layer 2 and 3. 
    d3=(a3.-Y); 
    d2=d3*Theta2(:,2:end); 

    % Theta grad is computed without regularization. 
    Theta1_grad=(d2'*a1)./m; 
    Theta2_grad=(d3'*a2)./m; 

    % Regularization is added to grad computation. 
    Theta1_grad(:,2:end)=Theta1_grad(:,2:end)+(lambda/m).*Theta1(:,2:end); 
    Theta2_grad(:,2:end)=Theta2_grad(:,2:end)+(lambda/m).*Theta2(:,2:end); 

    % Unroll gradients. 
    grad = [Theta1_grad(:) ; Theta2_grad(:)]; 

zauważyć, że ponieważ zostały wyjęte wszystkie aktywację esicy, obliczenie pochodnej jest dość prosta i wynika z uproszczenia oryginalnego kodu.

Kolejne kroki: 1. Sprawdź ten kod, aby zrozumieć, czy ma to sens dla twojego problemu. 2. Użyj sprawdzania gradientu, aby przetestować obliczenia gradientu. 3. Na koniec użyj polecenia fmincg i sprawdź, czy uzyskasz różne wyniki.

0

Spróbuj użyć funkcji sigmoid do obliczenia wartości drugiej warstwy (ukrytej warstwy) i uniknięcia sigmoidu w obliczaniu wartości docelowej (wyjściowej).

function [J grad] = nnCostFunction1(nnParams, ... 
            inputLayerSize, ... 
            hiddenLayerSize, ... 
            numLabels, ... 
            X, y, lambda) 

Theta1 = reshape(nnParams(1:hiddenLayerSize * (inputLayerSize + 1)), ... 
       hiddenLayerSize, (inputLayerSize + 1)); 

Theta2 = reshape(nnParams((1 + (hiddenLayerSize * (inputLayerSize + 1))):end), ... 
       numLabels, (hiddenLayerSize + 1)); 

Theta1Grad = zeros(size(Theta1)); 
Theta2Grad = zeros(size(Theta2)); 

m = size(X,1); 

a1 = [ones(m, 1) X]'; 
z2 = Theta1 * a1; 
a2 = sigmoid(z2); 
a2 = [ones(1, m); a2]; 
z3 = Theta2 * a2; 
a3 = z3; 

Y = y'; 

r1 = lambda/(2 * m) * sum(sum(Theta1(:, 2:end) .* Theta1(:, 2:end))); 
r2 = lambda/(2 * m) * sum(sum(Theta2(:, 2:end) .* Theta2(:, 2:end))); 

J = 1/(2 * m) * (a3 - Y) * (a3 - Y)' + r1 + r2; 

delta3 = a3 - Y; 
delta2 = (Theta2' * delta3) .* sigmoidGradient([ones(1, m); z2]); 
delta2 = delta2(2:end, :); 

Theta2Grad = 1/m * (delta3 * a2'); 
Theta2Grad(:, 2:end) = Theta2Grad(:, 2:end) + lambda/m * Theta2(:, 2:end); 
Theta1Grad = 1/m * (delta2 * a1'); 
Theta1Grad(:, 2:end) = Theta1Grad(:, 2:end) + lambda/m * Theta1(:, 2:end); 

grad = [Theta1Grad(:) ; Theta2Grad(:)]; 

end 

Normalizuj wejścia przed przekazaniem go w funkcji nnCostFunction.

Powiązane problemy