Přiložená ukázka je ten nejjednodušší gradientní algoritmus (tj. backpropagation v základní podobě). Kritérium optimality je MSE. Aktivační funkce je z-funkce, což je zrcadlově převrácená sigma-funkce: z(x) = σ(-x). (Ušetří se jedno mínus.) Neuronová síť se učí všech 16 možných binárních funkcí najednou. Kód v Matlabu přikládám. Tento skript je jen pro ověření funkčnosti návrhu algoritmu. Je to docela dobré cvičení, pokud se učíte parciálně derivovat a operace s maticemi. Je to úplně jednoduché a měl by to zvládnout i začátečník. (Což ale neznamená, že jsem neudělal chybu.)
% počet vstupů NN dimx = 2; % počty neuronů v jednotlivých vrstvách (poslední číslo = počet výstupů) ns = [5, 12, 16]; % počet vrstev NN (vstupy nejsou vrstva) nL = length(ns); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % počet příkladů v trénovací množině T = 4; % příklady vstupů (příklady jsou v řádcích) X = [ 0 0 1 0 0 1 1 1 ]; % příklady požadovaných výstupů (příklady jsou v řádcích) Y = [ 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ]; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Alokace paměti a inicializace NN dimsx = [dimx, ns(1:(nL - 1))]; Ws = {}; bs = {}; for i = 1:nL Ws{i} = 0.1 * randn(dimsx(i), ns(i)); bs{i} = 0.1 * randn(1, ns(i)); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Alokace paměti Bs = {}; Xis = {}; Xs = {}; dXdXis = {}; dedXs = {}; dedXis = {}; dedWs = {}; dedbs = {}; for i = 1:nL Xis{i} = zeros(T, ns(i)); Xs{i} = zeros(T, ns(i)); Bs{i} = zeros(T, ns(i)); dXdXis{i} = zeros(T, ns(i)); dedXs{i} = zeros(T, ns(i)); dedXis{i} = zeros(T, ns(i)); dedWs{i} = zeros(dimsx(i), ns(i)); dedbs{i} = zeros(1, ns(i)); end for icycle = 1:10000000 % počítání výstupů for i = 1:nL Bs{i} = ones(T, 1) * bs{i}; end for i = 1:nL if i == 1 Xis{i} = X * Ws{i} + Bs{i}; else Xis{i} = Xs{i - 1} * Ws{i} + Bs{i}; end Xs{i} = 1 ./ (1 + exp(Xis{i})); end % tisk výstupů disp(Xs{nL}) % počítání chyby e = sum(sum((Xs{nL} - Y).^2)) if e < 0.01 break end % počítání gradientu for i = 1:nL dXdXis{i} = Xs{i} .* (Xs{i} - 1); end dedXs{nL} = 2 * (Xs{nL} - Y); dedXis{nL} = dedXs{nL} .* dXdXis{nL}; for i = (nL - 1):(-1):1 dedXs{i} = dedXis{i + 1} * Ws{i + 1}'; dedXis{i} = dedXs{i} .* dXdXis{i}; end dedWs{1} = X' * dedXis{1}; for i = 2:nL dedWs{i} = Xs{i - 1}' * dedXis{i}; end for i = 1:nL dedbs{i} = sum(dedXis{i}); end % změna parametrů NN LR = 0.01; for i = 1:nL Ws{i} = Ws{i} - LR * dedWs{i}; bs{i} = bs{i} - LR * dedbs{i}; end end
Žádné komentáře:
Okomentovat