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