Le contenu est ["Deep Learning from scratch"](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4% BD% 9C% E3% 82% 8B Apprentissage en profondeur-% E2% 80% 95 Python% E3% 81% A7% E5% AD% A6% E3% 81% B6% E3% 83% 87% E3% 82% A3% E3 % 83% BC% E3% 83% 97% E3% 83% A9% E3% 83% BC% E3% 83% 8B% E3% 83% B3% E3% 82% B0% E3% 81% AE% E7% 90 % 86% E8% AB% 96% E3% 81% A8% E5% AE% 9F% E8% A3% 85-% E6% 96% 8E% E8% 97% A4-% E5% BA% B7% E6% AF % 85 / dp / 4873117585) 4.4.2 Gradient pour le réseau de neurones (par p.110). La question étant résolue, j'écrirai un article.
Ce que je me demandais, c'était le code au bas de la page 111. (Suivant)
>>> def f(W):
... return net.loss(x, t)
...
>>> dW = numerical_gradient(f, net.W)
>>> print(dW)
[[ 0.21924763 0.14356247 -0.36281009]
[ 0.32887144 0.2153437 -0.54421514]]
J'ai défini la fonction f
et je l'ai transmise comme argument à la fonction numerical_gradient
définie peu avant ce livre.
Lorsque j'ai changé le deuxième argument de cette fonction numerical_gradient
en une valeur appropriée, la valeur de dW
a changé. (Suivant)
#Net comme deuxième argument.Spécifiez W.(net.Pour W, p dans ce livre.Voir le commentaire du 110.)
>>> dW = numerical_gradient(f, net.W)
>>> print(dW)
[[ 0.06281915 0.46086202 -0.52368118]
[ 0.09422873 0.69129304 -0.78552177]]
#Stockez le tableau numpy dans a et spécifiez-le comme deuxième argument.
>>> a = np.array([[0.2, 0.1, -0.3],
[0.12, -0.17, 0.088]])
>>> dW = numerical_gradient(f, a)
>>> print(dW)
[[0. 0. 0.]
[0. 0. 0.]]
Je n'ai pas compris pourquoi la valeur de «dW» a changé. Cet article est la réponse à cette question.
Je vais expliquer pourquoi je me demandais pourquoi la valeur de dW
avait changé.
Tout d'abord, la valeur de retour de cette fonction f
n'a rien à voir avec la valeur de l'argument W
.
C'est parce que «W» n'apparaît pas après «return» dans la fonction «f».
Donc, quelle que soit la valeur que vous modifiez l'argument de la fonction f`` W
, la valeur de retour ne changera pas du tout. (Voir ci-dessous)
#Spécifiez 3 comme argument de la fonction f.
>>> f(3)
2.0620146712373737
#fonction net to f.Spécifiez W.
>>> f(net.W)
2.0620146712373737
#Définissez un tableau numpy et attribuez-le à un. Comparez quand a est passé à la fonction f et quand 3 est passé.
>>> a = np.array([[0.2, 0.1, -0.3],
[0.12, -0.17, 0.088]])
>>> f(a) == f(3)
True
Comme autre point, je présenterai la fonction numerical_gradient
. (Suivant)
def numerical_gradient(f, x):
h = 1e-4 # 0.0001
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index
tmp_val = x[idx]
x[idx] = tmp_val + h
fxh1 = f(x) # f(x+h)
x[idx] = tmp_val - h
fxh2 = f(x) # f(x-h)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val #Restaurer la valeur
it.iternext()
return grad
Cette fonction renvoie le grad
défini dans la fonction.
Si vous suivez du bas du code comment ce grad
est dérivé,
Vous pouvez trouver le code grad [idx] = (fxh1 --fxh2) / (2 * h)
.
Alors, que sont «fxh1» et «fxh2»?
Vous pouvez trouver le code fxh1 = f (x)
fxh2 = f (x) `.
A partir du point 2, la valeur de retour de la fonction `` numerical_gradient 'grad
peut être attribuée à la valeur de f (x)
.
A partir du point 1, la fonction f
renvoie une valeur constante quelle que soit la valeur de l'argument.
À partir des points 1 et 2, quelle que soit la valeur attribuée au deuxième argument x
de la fonction numerical_gradient
J'ai trouvé étrange que la valeur de retour de la fonction numerical_gradient
change.
Tout d'abord, examinons de plus près la fonction numerical_gradient
.
Et j'expliquerai la fonction f
plus en détail.
numerical_gradient
Un petit ajustement du code numerical_gradient
.
Plus précisément, sous fxh1 = f (x)
fxh2 = f (x)
respectivement
Entrez print (fxh1)
print (fxh2)
. (Suivant)
def numerical_gradient(f, x):
h = 1e-4
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index
print('idx:', idx)
tmp_val = x[idx]
x[idx] = tmp_val + h
fxh1 = f(x) # f(x+h)
print('fxh1:', fxh1) # print(fxh1)Entrer
x[idx] = tmp_val - h
fxh2 = f(x) # f(x-h)
print('fxh2:', fxh2) # print(fxh2)Entrer
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val
it.iternext()
return grad
Maintenant, déplaçons le code en changeant le deuxième argument.
Remplacez le deuxième argument par net.W
>>> dW = numerical_gradient(f, net.W)
fxh1: 2.062020953321506
fxh2: 2.0620083894906935
fxh1: 2.062060757760379
fxh2: 2.061968585355599
fxh1: 2.061962303319411
fxh2: 2.062067039554999
fxh1: 2.062024094490122
fxh2: 2.062005248743893
fxh1: 2.062083801262337
fxh2: 2.0619455426551796
fxh1: 2.061936119510309
fxh2: 2.06209322386368
Remplacez le deuxième argument par votre propre tableau numpy ʻa`
>>> a = np.array([[0.2, 0.1, -0.3],
[0.12, -0.17, 0.088]])
>>> dW = numerical_gradient(f, a)
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
Pour ceux qui ont assigné «net.W» au deuxième argument, les valeurs sont légèrement différentes entre «fxh1» et «fxh2».
D'un autre côté, lorsque vous remplacez votre propre tableau numpy ʻa,
fxh1 et
fxh2` ont la même valeur.
Pourquoi?
A partir de maintenant, j'expliquerai en considérant le cas où «net.W» est entré dans le deuxième argument.
Regardons de plus près la fonction numerical_gradient
.
Il y a le code suivant au milieu.
Ce code change le numéro d'index de ʻidx, récupère le
x` de ce numéro d'index, et
Un petit «h» est ajouté au «x» extrait et affecté à la fonction «f».
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index #Changer le numéro d'index de idx
tmp_val = x[idx] #Retirez le x de ce numéro d'index
x[idx] = tmp_val + h #Ajouter un petit h au x extrait
fxh1 = f(x) # f(x+h) #Affecté à la fonction f.
La valeur de retour de la fonction «f» a-t-elle changé en raison de l'ajout d'un petit «h» à «x»?
Cependant, le fait que la valeur de retour de la fonction f
ne change pas en raison de changements dans les arguments est montré au point 1 de" Pourquoi vous êtes-vous demandé? "
En fait, il y a une partie qui a changé en ajoutant un petit «h» à «x».
Le x
ici est le net.W
assigné au deuxième argument de la fonction numerical_gradient
.
Après avoir ajouté un petit «h» à «net.W», il est passé à l'argument de la fonction «f».
La partie suivante de la fonction numerical_gradient
montrée précédemment.
x[idx] = tmp_val + h #Ajouter un petit h au x extrait
fxh1 = f(x) #Affecté à la fonction f.
L'important ici est l'ordre dans lequel la fonction f
est appelée après que le net.W
a changé.
Comment le changement de «net.W» affecte-t-il la fonction «f»?
f
plus en détailVoyons comment changer net.W
affecte la fonction f
.
La fonction «f» est illustrée ci-dessous.
def f(W):
return net.loss(x, t)
La fonction loss
qui apparaît dans la fonction f
est définie dans la classe simpleNet
définie à la p.110 de ce manuel.
La classe simpleNet
est illustrée ci-dessous.
import sys, os
sys.path.append(os.pardir)
import numpy as np
from common.functions import softmax, cross_entropy_error
from common.gradient import numerical_gradient
class simpleNet:
def __init__(self):
self.W = np.random.randn(2,3)
def predict(self, x):
return np.dot(x, self.W)
def loss(self, x, t):
z = self.predict(x)
y = softmax(z)
loss = cross_entropy_error(y, t)
return loss
Vous verrez la fonction loss
en bas de simpleNet
.
À l'intérieur de la fonction «perte» se trouve la fonction «prédire».
La fonction «prédire» est définie juste au-dessus de la fonction «perte».
Si vous regardez de plus près la fonction predire
, vous verrez le paramètre de poids W
.
À la fin de "En savoir plus sur la fonction numerical_gradient
", quel effet le changement de net.W
a-t-il sur la fonction f
? La réponse est ici.
En changeant «net.W», le paramètre de poids «W» de la fonction «prédire» appelée par la fonction «perte» dans la fonction «f» a changé.
Ensuite, bien sûr, la valeur de retour de la fonction loss
changera.
L'explication est enfin terminée.
Revenons à la fonction numerical_gradient
. La fonction numerical_gradient
est à nouveau représentée ci-dessous.
def numerical_gradient(f, x):
h = 1e-4
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index
print('idx:', idx)
tmp_val = x[idx]
x[idx] = tmp_val + h
fxh1 = f(x) # f(x+h)
x[idx] = tmp_val - h
fxh2 = f(x) # f(x-h)
print('fxh2:', fxh2)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val
it.iternext()
return grad
Comme mentionné ci-dessus, la valeur de retour de la fonction «loss» dans la fonction «f» change en raison du changement de «net.W».
Dans ce code, l'ajout d'un petit «h» à «x» («net.W») a changé la fonction «f», et la valeur de «fxh1» a changé.
La même chose s'applique à la suivante «fxh2».
Puis passée au code suivant, la fonction numerical_gradient
imprime la valeur de retour.
Cela a résolu la première question que j'ai posée.
Le point important est
● Supprimez que le deuxième argument de la fonction numerical_gradient
, x
, soit net.W
.
● La valeur de retour de la fonction f
a changé à mesure que le net.W
a changé.
Continuons à lire "Deep Learning from scratch"!