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