2009-08-17 15 views
5

Pracuję nad stworzeniem 2-warstwowej sieci neuronowej z propagacją wsteczną. NN powinien pobierać dane z wektora 20001x17, który przechowuje następujące informacje w każdym wierszu:Matlab - szkolenie z sieci neuronowej

- Pierwsze 16 komórek zawiera liczby całkowite od 0 do 15, które działają jak zmienne, aby pomóc nam określić, która z 26 liter alfabetu, który chcemy wyrazić podczas oglądania tych zmiennych. Na przykład serie 16 wartości w następujący sposób mają reprezentować literę A: [2 8 4 5 2 7 5 3 1 6 0 8 2 7 2 7].

-na siedemnastej komórce zawiera liczbę od 1 do 26 przedstawiającą literę alfabetu, którą chcemy. 1 oznacza A, 2 oznacza B itd.

Warstwa wyjściowa NN składa się z 26 wyjść. Za każdym razem, gdy NN jest zasilane wejściem podobnym do opisanego powyżej, ma wyprowadzać wektor 1x26 zawierający zera we wszystkich oprócz jednej komórki, która odpowiada literze, którą miały reprezentować wartości wejściowe. na przykład wyjście [1 0 0 ... 0] to litera A, natomiast [0 0 0 ... 1] to litera Z.

Kilka ważnych rzeczy, zanim przedstawię kod: I trzeba użyć funkcji traingdm i ukryty numer warstwy jest stały (na razie) na 21.

Próbując stworzyć powyższą koncepcję napisałem następujący kod Matlaba:

%%%%%%%% 
%Start of code% 
%%%%%%%% 

% 
%Initialize the input and target vectors 
% 
p = zeros(16,20001); 
t = zeros(26,20001); 

% 
%Fill the input and training vectors from the dataset provided 
% 
for i=2:20001 
    for k=1:16 
     p(k,i-1) = data(i,k); 
    end 
    t(data(i,17),i-1) = 1; 
end 

net = newff(minmax(p),[21 26],{'logsig' 'logsig'},'traingdm'); 

y1 = sim(net,p); 

net.trainParam.epochs = 200; 
net.trainParam.show = 1; 
net.trainParam.goal = 0.1; 
net.trainParam.lr = 0.8; 
net.trainParam.mc = 0.2; 
net.divideFcn = 'dividerand'; 
net.divideParam.trainRatio = 0.7; 
net.divideParam.testRatio = 0.2; 
net.divideParam.valRatio = 0.1; 

%[pn,ps] = mapminmax(p); 
%[tn,ts] = mapminmax(t); 

net = init(net); 
[net,tr] = train(net,p,t); 

y2 = sim(net,pn); 

%%%%%%%% 
%End of code% 
%%%%%%%% 

teraz mój problem: i chcę, aby moje wyniki były zgodne z opisem, a mianowicie każda kolumna wektora y2 powinna być na przykład reprezentacją litery. Mój kod tego nie robi. Zamiast tego uzyskano wyniki, które różnią się znacznie między 0 a 1, wartości od 0,1 do 0,9.

Moje pytanie brzmi: czy jest jakieś nawrócenie, które muszę wykonać, nie jestem? Czy muszę konwertować dane wejściowe i/lub wyjściowe na formę, dzięki której mogę zobaczyć, czy mój NN uczy się poprawnie?

Wszelkie dane wejściowe będą mile widziane.

Odpowiedz

2

Jest to normalne. Twoja warstwa wyjściowa używa funkcji przesyłania log-sigmoid, która zawsze daje pewną pośrednią wartość wyjściową między 0 a 1.

To, co zwykle robisz, to szukać wyjścia o największej wartości - w innym słowa, najbardziej prawdopodobny charakter.

Oznaczałoby to, że dla każdej kolumny w y2 szukasz indeksu wiersza zawierającego największą wartość w tym wierszu. Można obliczyć to w następujący sposób:

[dummy, I]=max(y2); 

I jest wówczas wektor zawierający indeksy o największej wartości w każdym wierszu.

+0

Martin, dzięki za odpowiedź. Używając max (y2) mogę teraz uzyskać kilka informacji o tym, ile razy sieć miała rację, identyfikując litery. To, co zrobiłem, jednak przed wprowadzeniem do sieci danych, które posiadałem, skalowałem tak, aby 0 <= p (x) <= 1. Jako, że minimalna wartość p wynosiła 0, a maksymalna wynosiła 15, zrobiłem nowy wektor wejściowy scaledp = p/15. –

+0

Nie powinieneś używać max jako funkcji działania, ponieważ twoja funkcja błędu powinna być zdefiniowana na podstawie aktywności, a nie aktywacji, a max nie jest różniczkowalna, co oznacza, że ​​nie możesz użyć back-prop. Potrzebujesz softmax, zobacz moją odpowiedź poniżej. –

1

Można myśleć o y2 jako rozkład prawdopodobieństwa wyjścia dla każdego wejścia jest jednym z 26 alfabetu znaków, na przykład jeśli jedna kolumna y2 mówi:

.2 
.5 
.15 
.15 

wtedy jego 50% prawdopodobieństwo że ten znak to B (jeśli przyjmujemy tylko 4 możliwe wyjścia).



UWAGA == ==

Warstwę wyjściowy NN składa 26 wyjść. Za każdym razem, gdy jest podawany NN wejście jak ten opisany powyżej to miało wyjściu 1x26 wektor zawierające zer we wszystkich, ale ten jeden komórkę odpowiadającą literze że wartości wejściowe zostały przeznaczone do reprezentować. Na przykład wyjście [1 0 0 ... 0] będzie literą A, podczas gdy [0 0 0 ... 1] byłoby litery Z.

Korzystnie wartości docelowe unikać 0,1 do kodowania wyjścia sieci.
Powodem unikania wartości docelowych 0 i 1 jest to, że funkcja przenoszenia sigmoidów "logsig" nie może wytworzyć tych wartości wyjściowych o skończonej masie. Jeśli spróbujesz wyszkolić sieć tak, aby pasowała do wartości docelowych dokładnie 0 i 1, nachylenie gradientu zmusi ciężary do wzrostu bez ograniczeń.
Więc zamiast wartości 0 i 1 spróbuj użyć wartości 0,04 i 0,9, na przykład [0,9,0.04, ..., 0,04] ​​jest docelowym wektorem wyjściowym dla litery A.


referencyjny:
Thomas M. Mitchell, Machine Learning, McGraw-Hill Higher Education, 1997, p114-115

+0

Nie sądzę, że to prawda. Każdy element wektora wyjściowego będzie miał wartość zmieniającą się w przedziale od 0,00 do 1,00, ale suma dowolnej kolumny (lub dowolnego elementu w tej kolumnie) nigdy nie będzie stanowić procentu. –

+0

możesz zawsze normalizować samodzielnie: y2Normalizowane = y2 ./ repmat (suma (y2), 26, 1) – Amro

+0

Alternatywnie możesz użyć różnicy między najwyższą wartością y2 a drugą najwyższą wartością jako miarą pewności Prognoza. – Amro

1
  1. Zastosowanie hardlin fcn w warstwie wyjściowej.
    1. Użyj trainlm lub trainrp do szkolenia sieci.
    2. Aby nauczyć się sieci, użyj pętli for i warunku porównującego dane wyjściowe i cel. Kiedy jest to najlepszy użytek, przerwij, aby wyjść z pętli nauki.
    3. Użyj innego sposobu zamiast mapminmax do wstępnego przetwarzania danych.
0

Nie wiem, czy to stanowi rzeczywistą odpowiedź lub nie: ale oto kilka uwag.

  • Nie rozumiem twojego schematu kodowania. W jaki sposób symbol "A" reprezentowany jest jako zbiór cyfr? Wygląda na to, że wpadasz w dość powszechną pułapkę używania dowolnych liczb do kodowania wartości kategorycznych. Nie rób tego: na przykład jeśli "a" to 1, "b" to 2, a "c" to 3, to twoje kodowanie domyślnie stwierdziło, że "a" jest bardziej podobne do "b" niż "c" (ponieważ sieć ma wartości rzeczywiste, a właściwości porządkowe mają znaczenie). Aby to zrobić właściwie, każda litera powinna być reprezentowana jako 26 wartości binarnych, gdzie tylko jedna jest zawsze aktywna, reprezentując literę.
  • Twoje dane wyjściowe są poprawne, aktywacja na warstwie wyjściowej nie będzie mieć wartości 0 lub 1, ale liczb rzeczywistych. Możesz użyć max jako swojej funkcji aktywności, ale jest to problematyczne, ponieważ nie jest różniczkowalne, więc nie możesz użyć back-prop. To, co powinieneś zrobić, to połączyć wyjścia z softmax function, tak aby ich suma wynosiła .Możesz wtedy traktować wyjścia jako warunkowe prawdopodobieństwa, jeśli masz na to ochotę. Chociaż sieć nie jest jawnie probabilistyczna, z prawidłową aktywnością i aktywacją funkcje będą miały identyczną strukturę do modelu logarytmiczno-liniowego (prawdopodobnie z ukrytymi zmiennymi odpowiadającymi ukrytej warstwie), i ludzie robią to cały czas .

Zapoznaj się z David Mackay's textbook dla miłego wprowadzenia do sieci neuronowych, które wyjaśnią probabilistyczne połączenie. Spójrz na this paper from Geoff Hinton's group, która opisuje zadanie przewidywania następnego znaku, biorąc pod uwagę kontekst, aby uzyskać szczegółowe informacje na temat prawidłowej reprezentacji i funkcji aktywacji/aktywności (chociaż uwaga: ich metoda jest nietrywialna i wykorzystuje sieć rekurencyjną z inną metodą szkolenia).

Powiązane problemy