4.3.3 Différenciation partielle
fournit un exemple de dessin d'un vecteur de gradient de f = x0 ^ 2 + x1 ^ 2
avec du code.
Sur cette base, lorsque j'ai essayé de dessiner le résultat de f = x0 * x1
, je suis resté bloqué, je vais donc décrire la solution.
L'exemple de code d'origine est deep-learning-from-scratch / ch04 / gradient_2d.py )est.
Le résultat de l'exécution est le suivant.
Tout d'abord, le code de résultat de vérification de cette heure est affiché.
# coding: utf-8
# cf.http://d.hatena.ne.jp/white_wheels/20100327/p3
import numpy as np
import matplotlib.pylab as plt
from mpl_toolkits.mplot3d import Axes3D
def _numerical_gradient_no_batch(f, x):
h = 1e-4 # 0.0001
grad = np.zeros_like(x)
for idx in range(x.size):
tmp_val = x[idx]
x[idx] = float(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
return grad
def numerical_gradient(f, X):
if X.ndim == 1:
return _numerical_gradient_no_batch(f, X)
else:
grad = np.zeros_like(X)
for idx, x in enumerate(X):
grad[idx] = _numerical_gradient_no_batch(f, x)
return grad
def function_2(x):
if x.ndim == 1:
return np.sum(x**2)
else:
return np.sum(x**2, axis=1)
# f = x0*x1, df/dx0 = x1, df/dx1 = x0
# can110
def function_xy(x):
if x.ndim == 1:
return x[0]*x[1]
else:
return x[:,0]*x[:,1]
# f = sin(x0*x1), df/dx0 = x1*cos(x0*x1), df/dx1 = x0*cos(x0*x1)
# can110
def function_sin_xy(x):
if x.ndim == 1:
return np.sin(x[0]*x[1])
else:
return np.sin(x[:,0]*x[:,1])
def tangent_line(f, x):
d = numerical_gradient(f, x)
print(d)
y = f(x) - d*x
return lambda t: d*t + y
if __name__ == '__main__':
x0 = np.arange(-2, 2.5, 0.25)
x1 = np.arange(-2, 2.5, 0.25)
X, Y = np.meshgrid(x0, x1)
X = X.flatten()
Y = Y.flatten()
a = np.array([X, Y])
a = a.T #Translocation. 1 ligne=1 vecteur (colonne=x0,x1) devrait être can110
#Vérification
#func = function_2 # df/dx0(=2*x0), df/dx1(=2*x1)Sont x0 respectivement,Puisqu'il n'est calculé qu'à partir de x1, cela fonctionne-t-il?
func = function_xy
#func = function_sin_xy
#grad = numerical_gradient(function_2, np.array([X, Y]) )
grad = numerical_gradient(func, a)
grad = grad.T #Transposé pour carquois (x0 par ligne,Placer les valeurs de coordonnées x1) can110
plt.figure()
plt.quiver(X, Y, -grad[0], -grad[1], angles="xy",color="#666666")#,headwidth=10,scale=40,color="#444444")
plt.xlim([-2, 2])
plt.ylim([-2, 2])
plt.xlabel('x0')
plt.ylabel('x1')
plt.grid()
plt.legend()
plt.draw()
plt.show()
Cette fois, j'ai défini la fonction f = x0 * x1
comme suit. Au fait, dans ce calcul de gradient, seule la partie de x.ndim == 1
est appelée.
def function_xy(x):
if x.ndim == 1:
return x[0]*x[1]
else:
return x[:,0]*x[:,1]
Je l'ai remplacé par l'original function_2
et l'ai exécuté, mais avec des résultats étranges.
J'ai donc suivi le code de calcul du gradient.
La fonction numerical_gradient
est utilisée pour plusieurs vecteurs → La fonction _numerical_gradient_no_batch
est utilisée pour calculer le gradient pour un vecteur.
Donc, si vous regardez x.shape
dans _numerical_gradient_no_batch
, c'est (324,)
. Le nombre de vecteurs (points à dessiner).
Cela devrait être ** (2,)
**. Donc, si vous vérifiez l'appelant
grad = numerical_gradient(function_2, np.array([X, Y]) )
Nous passons une paire de coordonnées X (x0) et Y (x1). Telle est la cause. En traduisant «np.array ([X, Y]» sous la forme «1 ligne = 1 vecteur (point)», il est maintenant dessiné correctement.
--Passez le résultat transposé (1 ligne = 1 vecteur) à la fonction numerical_gradient
.
numerical_gradient
est également transposé pour le dessinquiver
(les valeurs de coordonnées x0, x1 sont disposées pour chaque ligne).Tableau correct / erroné de "Deep Learning from scratch", mais cela ressemble à un bogue ??
Recommended Posts