[PYTHON] [Mémo d'apprentissage] Deep Learning fait de zéro [~ Chapitre 4]

Mémo d'apprentissage Deep Learning fait de zéro

https://www.amazon.co.jp/dp/4873117585/

Mémo de fonction qui semble être utilisé

Fonction sigmoïde: sigmoïde

Propriétés importantes: renvoie entre 0 et 1, lisse, monotone (bien que non mentionné dans le livre)

Fonction Sigmaid


h(x) = \frac{1}{1+\exp(-x)} 
def sigmoid(x):
    return 1/(1+np.exp(-x))

sigmoid.png

Fonction Softmax

Après tout, la valeur maximale est recherchée indépendamment du fait qu'elle soit appliquée ou non, il est donc courant d'omettre la fonction softmax de la couche de sortie.

python


y_k = \frac{\exp(a_k)}{\sum_{i=1}^{n}\exp(a_i)} = \frac{\exp(a_k + C')}{\sum_{i=1}^{n}\exp(a_i + C')} 
def softmax(a) :
    c = np.max(a)
    exp_a = np.exp(a - c)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    return y

Fonction de perte

Raisons de définir la fonction de perte Lorsque la précision de la reconnaissance est indexée, le différentiel du paramètre devient 0 (bloqué) dans la plupart des endroits.

Erreur de somme des carrés: erreur quadratique moyenne

E = \frac{1}{2}\sum_{k=1} (y_k - t_k)^2

python


def mean_squared_error(y,t):
    return 0.5 * np.sum((y-t)**2)

Erreur d'entropie croisée: erreur d'entropie croisée

Point: Expression One-hot: Seule l'étiquette de réponse correcte est 1, les autres sont 0 (l'étiquette est t)

E=\sum_{k=1} - t_k \log y_k 

python


def cross_entropy_error(y, t) :
    delta = le-7
    return -np.sum(t*np.log(y+delta))

Version compatible mini-batch: erreur d'entropie croisée

Mini-lot (petit morceau): sélectionnez une partie des données et utilisez la partie des données comme une "approximation" de l'ensemble Point: Dans one-hot, l'étiquette incorrecte est 0 (= l'erreur est 0), vous pouvez donc l'ignorer. Divisez par N pour obtenir un index unifié quel que soit le nombre de données d'entraînement

E=-\frac{1}{N}\sum_{n}\sum_{k=1} t_{nk} \log y_{nk} 

python


def cross_entropy_error(y, t) :
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
        
    batch_size = y.shape[0]
    return -np.sum(t*np.log(y[np.arange(bathch_size), t])) / bathc_size

différentiel

Différenciation numérique

Point: mis à environ 1e-4 pour ne pas provoquer d'erreur d'arrondi

python


def numerical_diff(f, x) :
    h = 1e-4
    return (f(x+h)-f(x-h))/(2*h)

Différenciation partielle

python


# x1=4 heures

def function_tmp1(x0):
    return x0*x0 + 4.0*2.0

numerical_diff(function_tmp1, 3.0)

Pente

Gradient: un vecteur qui résume la différenciation partielle de toutes les variables

python


def numerical_gradient(f, x):
    h = 1e-4 # 0.0001
    grad = np.zeros_like(x) #Générez un tableau de la même forme que x et remplissez-le de valeurs

    #Le fait est que les variables sont différenciées une par une dans l'ordre.
    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

Méthode de gradient

Méthode du dégradé: répétez le mouvement dans le sens du dégradé et réduisez progressivement la valeur de la fonction. Point: la méthode du dégradé atteint la valeur minimale et non la valeur minimale. L'image est facile à comprendre par le Dr Andrew Ng de Coursera Machine Learning Semaine 5 Conférence 9 p.31

x_0=x_0-\eta\frac{\partial f}{\partial x_0} \\
x_1=x_1-\eta\frac{\partial f}{\partial x_1} \\
\\
\eta :Taux d'apprentissage (combien vous apprenez en un seul apprentissage, ni trop grand ni trop petit)

python


def gradient_descent(f, init_x, lr=0.01, step_num=100):
    x = init_x
    
    for i in range(step_num):
        grad = numerical_gradient(f, x)
        x -= lr * grad
        
    return x

def function_2(x):
    return x[0]**2 + x[1]**2

init_x = np.array([-3.0, 4.0])
gradient_descent(function_2, init_x=init_x, lr=0.1, step_num=100)

Les paramètres définis par les humains tels que le taux d'apprentissage ci-dessus sont appelés hyper paramètres.

Gradient par rapport au réseau neuronal

W = \biggl(\begin{matrix}
w_{11} & w_{21} & w_{31} \\
w_{12} & w_{22} & w_{32} 
\end{matrix}\biggr)\\


\frac{\partial L}{\partial W} = \Biggl(\begin{matrix}
\frac{\partial L}{\partial w_{11}} & \frac{\partial L}{\partial w_{21}} & \frac{\partial L}{\partial w_{31}}\\
\frac{\partial L}{\partial w_{12}} & \frac{\partial L}{\partial w_{22}} & \frac{\partial L}{\partial w_{32}} 
\end{matrix}\Biggr)\\

\frac{\partial L}{\partial w_{11}} : w_{11}Représente à quel point la fonction de perte L change lorsque

python


# coding: utf-8
import sys, os
sys.path.append(os.pardir)  #Paramètres d'importation des fichiers dans le répertoire parent
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

python


#Essayez d'utiliser
#Paramètres
x = np.array([0.6, 0.9])
#étiquette
t = np.array([0, 0, 1])

net = simpleNet()

f = lambda w: net.loss(x, t)
#En bref, nous exécutons une méthode de gradient qui recherche celle avec la fonction de perte minimale.
dW = numerical_gradient(f, net.W)

print(dW)

[[ 0.10181684 0.35488728 -0.45670412] [ 0.15272526 0.53233092 -0.68505618]] Le résultat ci-dessus montre que l'augmentation de w_11 de h augmente de 0,10181684. En termes de contribution, w_23 est le plus grand

python


#Style Lambda
myfunc = lambda x: x ** 2 

myfunc(5)  # 25
myfunc(6)  # 36

#C'est la même chose que ci-dessous
def myfunc(x):
    return x ** 2

Implémentation d'algorithme d'apprentissage

Aperçu de l'apprentissage

Formation en réseau neuronal: ajustement des poids et des biais pour s'adapter aux données d'entraînement

procédure

Étape 1: Mini lot </ b> Sélectionnez au hasard certaines données parmi les données d'entraînement. (Mini lot) Le but est de réduire la valeur de la fonction de perte de ce mini-lot

Étape 2: Calculez le gradient </ b> Trouvez la pente de chaque paramètre de poids pour réduire la fonction de perte du mini-lot. Le gradient indique la direction dans laquelle la valeur de la fonction de perte est la plus réduite

Étape 3: Mettre à jour les paramètres </ b> Mettez à jour légèrement le paramètre de pondération dans la direction du dégradé.

Étape 4: Répétez </ b> Répétez les étapes 1 à 3

le terme

Descente de gradient probabiliste (descente de gradient stochastique SGD): Probabiliste: "Sélection aléatoire probabiliste" Méthode de descente de gradient *: "Trouver la valeur minimale"

  • Il existe également une méthode d'augmentation de gradient, et c'est essentiellement le même problème si le signe est inversé, il ne s'agit donc pas essentiellement de demande.

Epoque: époque 1 Epoch correspond au nombre de fois où toutes les données d'entraînement sont utilisées dans l'apprentissage Exemple: données d'entraînement avec 10000 données, répétition de la méthode de descente de gradient stochastique 100 fois pour 100 mini-lots

Mise en œuvre et description

python


# coding: utf-8
import sys, os
sys.path.append(os.pardir)  #Paramètres d'importation des fichiers dans le répertoire parent
from common.functions import *
from common.gradient import numerical_gradient


class TwoLayerNet:

    #Initialisation
    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        #Initialisation du poids
        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)

    #Effectuer la reconnaissance (inférence). L'argument x est des données d'image
    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
    
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        
        return y

    #Trouvez la fonction de perte
    # x:Des données d'entrée, t:Données des enseignants
    def loss(self, x, t):
        y = self.predict(x)
        
        return cross_entropy_error(y, t)
    
    #Trouver la précision de la reconnaissance
    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)
        
        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy
        
    #Trouvez le dégradé du paramètre de poids
    # x:Des données d'entrée, t:Données des enseignants
    def numerical_gradient(self, x, t):
        loss_W = lambda W: self.loss(x, t)
        
        grads = {}
        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
        
        return grads

Illustration difficile à comprendre Faire juste ce calcul semblable à une image à la fois avec le calcul matriciel L'image est plus facile à comprendre dans Dr. Andrew Ng de Coursera, Semaine 5 de l'apprentissage automatique, Conférence 9 p.13. memo.png

Apprentissage par mini-lots, évaluation avec données de test

Omis car il améliore uniquement la précision en répétant la méthode du gradient L'évaluation avec les données de test est également omise car elle illustre uniquement l'exactitude des données de test afin de juger s'il s'agit d'un surentraînement.

Recommended Posts