1

J'essaie d'implémenter un autoencodeur rétro-propagateur feed-forward (entraînement avec descente de gradient) et je voulais vérifier que je calculais correctement le dégradé. Cette tutorial suggère de calculer la dérivée de chaque paramètre un à la fois: grad_i(theta) = (J(theta_i+epsilon) - J(theta_i-epsilon))/(2*epsilon). J'ai écrit un exemple de code dans Matlab pour le faire, mais sans grande chance - les différences entre le gradient calculé à partir de la dérivée et le gradient trouvé numériquement ont tendance à être grandes (>> 4 chiffres significatifs).Vérification du dégradé lors de la descente en dégradé

Si quelqu'un peut offrir des suggestions, j'apprécierais grandement l'aide (soit dans mon calcul du gradient ou comment j'effectue le contrôle). Parce que j'ai beaucoup simplifié le code pour le rendre plus lisible, je n'ai pas inclus de biais, et je ne suis plus en train d'attacher les matrices de poids.

D'abord, j'initialiser les variables:

numHidden = 200; 
numVisible = 784; 
low = -4*sqrt(6./(numHidden + numVisible)); 
high = 4*sqrt(6./(numHidden + numVisible)); 
encoder = low + (high-low)*rand(numVisible, numHidden); 
decoder = low + (high-low)*rand(numHidden, numVisible); 

Suivant, donné une image d'entrée x, ne propagation précompensation:

a = sigmoid(x*encoder); 
z = sigmoid(a*decoder); % (reconstruction of x) 

La fonction de perte que je utilise est la norme Σ (0,5 * (z - x)^2)):

% first calculate the error by finding the derivative of sum(0.5*(z-x).^2), 
% which is (f(h)-x)*f'(h), where z = f(h), h = a*decoder, and 
% f = sigmoid(x). However, since the derivative of the sigmoid is 
% sigmoid*(1 - sigmoid), we get: 
error_0 = (z - x).*z.*(1-z); 

% The gradient \Delta w_{ji} = error_j*a_i 
gDecoder = error_0'*a; 

% not important, but included for completeness 
% do back-propagation one layer down 
error_1 = (error_0*encoder).*a.*(1-a); 
gEncoder = error_1'*x; 

et fIN donne des résultats tels que

epsilon = 10e-5; 
check = gDecoder(:); % the values we obtained above 
for i = 1:size(decoder(:), 1) 
    % calculate J+ 
    theta = decoder(:); % unroll 
    theta(i) = theta(i) + epsilon; 
    decoderp = reshape(theta, size(decoder)); % re-roll 
    a = sigmoid(x*encoder); 
    z = sigmoid(a*decoderp); 
    Jp = sum(0.5*(z - x).^2); 

    % calculate J- 
    theta = decoder(:); 
    theta(i) = theta(i) - epsilon; 
    decoderp = reshape(theta, size(decoder)); 
    a = sigmoid(x*encoder); 
    z = sigmoid(a*decoderp); 
    Jm = sum(0.5*(z - x).^2); 

    grad_i = (Jp - Jm)/(2*epsilon); 
    diff = abs(grad_i - check(i)); 
    fprintf('%d: %f <=> %f: %f\n', i, grad_i, check(i), diff); 
end 

L'exécution de ce sur l'ensemble de données MNIST (pour la première entrée)::

2: 0.093885 <=> 0.028398: 0.065487 
3: 0.066285 <=> 0.031096: 0.035189 
5: 0.053074 <=> 0.019839: 0.033235 
6: 0.108249 <=> 0.042407: 0.065843 
7: 0.091576 <=> 0.009014: 0.082562 
allié, vérifiez que le gradient est correct (dans ce cas, il suffit de faire pour le décodeur)

Répondre

0

Ne pas sigmoïder à la fois sur a et sur z. Il suffit de l'utiliser sur z.

a = x*encoder; 
z = sigmoid(a*decoderp);