[PYTHON] Théorie et implémentation simples des réseaux neuronaux

J'avais besoin d'expliquer le code du réseau de neurones (ci-après, NN), j'ai donc décidé de profiter de l'occasion pour le résumer brièvement. Ci-dessous, nous procéderons en supposant que les connaissances de base sur NN sont connues.

Matériel de référence

[Learning and Neural Network (Electronic Information and Communication Engineering Series)](http://www.amazon.co.jp/gp/product/4627702914/ref=as_li_tf_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4627702914&linkCode=as2&tagao-shimash 22) <img src = "http://ir-jp.amazon-adsystem.com/e/ir?t=shimashimao06-22&l=as2&o=9&a=4627702914" width = "1" height = "1" border = " 0 "alt =" "style =" border: none! Important; margin: 0px! Important; "/>

Ce que j'ai fait

Théorie BP

symbole

Entrée sur le réseau: $ (x_ {1}, x_ {2}, ..., x_ {N}) $ Sortie du réseau: $ (y_ {1}, y_ {2}, ..., y_ {M}) $ Relation réseau entrée / sortie: $ (y_ {1}, y_ {2}, ..., y_ {M}) = F (x_ {1}, x_ {2}, ..., x_ {N}) $ Poids de jointure: {$ w_ {ij} } Seuil: { {\ theta_ {i}} $}

Présentation de BP

Avantages de BP

Le livre de référence ci-dessus a la description suivante des raisons pour lesquelles BP est devenu largement utilisé.

  • Le calcul de la différenciation partielle de la fonction d'évaluation pour chaque paramètre a tendance à être compliqué dans un système non linéaire général, mais il existe une méthode de calcul systématique et systématique dans BP. De plus, les informations requises pour déterminer la quantité de correction de chaque paramètre peuvent être transmises à l'emplacement requis en utilisant la structure de connexion connue par le réseau. Cela signifie qu'il n'est pas nécessaire de fournir une ligne de communication spéciale pour l'apprentissage, ce qui est pratique pour simplifier l'algorithme et le matériel.
  • La capacité d'approximation fonctionnelle du réseau est théoriquement garantie. Si un nombre suffisant d'éléments de couche intermédiaire est utilisé, toute fonction peut être arbitrairement approximée avec une grande précision en déterminant de manière appropriée les valeurs de paramètres (poids de connexion, valeur de seuil). Il n'est pas toujours possible de trouver une valeur de paramètre qui donne l'approximation optimale par BP, mais la preuve d'une sorte de théorème d'existence donne un sentiment de sécurité.

Approximation des fonctions

Effectuez les opérations suivantes.

Approximation de fonction dans un seul neurone

Puisque la méthode d'apprentissage de mise à jour séquentielle est dérivée, la méthode de gradient est appliquée dans le but de réduire l'échelle d'évaluation de l'équation suivante pour chaque donnée d'entraînement ($ x ^ {(l)}, y ^ {(l)} $). E(w_0, w_1, ..., w_N)=|y^{(l)}-\hat{y}^{(l)}|^2 s=\sum_{n=0}^{N}w_nx_n^{(l)} \hat{y}^{(l)}=sigmoid(s)

L'équation suivante est obtenue en différenciant l'échelle d'évaluation d'erreur $ E (w_0, w_1, ..., w_N) $ par $ w_n $. \frac{\partial E(w_0, w_1, ..., w_N)}{\partial w_n}=-2(y^{(l)}-\hat{y}^{(l)})sigmoid'(s)x_n^{(l)} ici, sigmoid(s)=\frac{1}{1+e^{-\alpha s}}

Lorsque cela est différencié, sigmoid'(s)=\frac{\alpha e^{-\alpha s}}{(1+e^{-\alpha s})^2}

Pour résumer cela davantage, \frac{\alpha e^{-\alpha s}}{(1+e^{-\alpha s})^2} =\alpha \frac{1}{1+e^{-\alpha s}}(1-\frac{1}{1+e^{-\alpha s}}) =\alpha sigmoid(s)(1-sigmoid(s)) =\alpha \hat{y}^{(l)}(1-\hat{y}^{(l)})

En utilisant la valeur de $ \ partial E (w_0, w_1, ..., w_N) / \ partial w_n $ obtenue à partir de ce qui précède, le poids de connexion est corrigé à plusieurs reprises par l'équation suivante. w_n=w_n-\epsilon \frac{\partial E(w_0, w_1, ..., w_N)}{\partial w_n}

Dérivation

Règles de chaîne

image Le petit changement de x se propage au changement d'autres valeurs de variable dans une chaîne en fonction de la dépendance des variables dans la figure ci-dessus. Selon la règle de la chaîne, l'expression relationnelle suivante est valable entre les changements infimes de ces variables $ \ Delta x, \ Delta z_1, \ Delta x_2, \ Delta y $. \Delta z_1=\frac{\partial z_1}{\partial x}\Delta x \Delta z_2=\frac{\partial z_2}{\partial x}\Delta x \Delta y=\frac{\partial y}{\partial z_1}\Delta z_1 + \frac{\partial y}{\partial z_2}\Delta z_2

Pour résumer la formule ci-dessus, \frac{\partial y}{\partial x}=\frac{\partial y}{\partial z_1}\frac{\partial z_1}{\partial x} + \frac{\partial y}{\partial z_2}\frac{\partial z_2}{\partial x}

3 couches NN

Sur la base de la règle de chaîne ci-dessus, nous dériverons le BP de NN constitué de la couche d'entrée, de la couche intermédiaire et de la couche de sortie. Le nombre d'unités pour les trois couches est de 3 (4 unités pour la couche d'entrée et la couche intermédiaire, compte tenu du terme de polarisation). À partir de l'unité de la couche de sortie, numérotez la couche de sortie: {1,2,3}, la couche intermédiaire: {4,5,6} et la couche d'entrée: {7,8,9}. Et

  1. Lorsque le poids $ w_2 $ de la 4ème unité de la couche intermédiaire à la 2ème unité de la couche de sortie change légèrement
  2. Lorsque le poids $ w_4 $ de la 5ème unité de la couche d'entrée à la 4ème unité de la couche intermédiaire change légèrement

BP est dérivée en utilisant ces deux cas comme exemples. Une image de chaque propagation est présentée ci-dessous.

image

image

Dans le cas de 1 ci-dessus

La relation entre le montant de la variation dans $ w_2 $ $ \ Delta w_2 $ et le montant de la variation dans $ s_2 $ $ \ Delta s_2 $ est illustrée par l'équation suivante. \Delta s_2=\Delta w_2y_4 Aussi, y_2=sigmoid(s_2) Que \Delta y_2=sigmoid'(s_2)\Delta s_2

Cette modification de $ y_2 $ modifie la valeur de l'échelle d'évaluation des erreurs, et l'expression relationnelle suivante est valable. \Delta E=2(y_2-t_2)\Delta y_2 Ici, $ t_2 $ fait référence aux données de réponse correctes de $ y_2 $. Si vous organisez la formule, \Delta E=2(y_2-t_2)sigmoid'(s_2)y_4\Delta w_2 \frac{\partial E}{\partial w_2}=2(y_2-t_2)sigmoid'(s_2)y_4

A partir de l'équation ci-dessus, le coefficient différentiel partiel $ \ partial E / \ partial w_2 $ requis pour corriger $ w_2 $ par la méthode du gradient a été obtenu.

Aussi, à partir de $ \ Delta s_2 = y_4 \ Delta w_2 $ \frac{\partial E}{\partial s_2}=2(y_2-t_2)sigmoid'(s_2) Est également recherché en même temps. Ces valeurs peuvent être utilisées telles quelles lors du calcul du coefficient différentiel partiel lorsque le poids une couche au-dessus change.

Dans le cas de 2 ci-dessus

La relation entre le montant du changement lorsque $ w_4 $ est modifié est calculée par la formule suivante. \Delta s_4=\Delta w_4 y_5 \Delta y_4=sigmoid'(s_4) \Delta s_4

Le changement de $ y_4 $ qui se produit de cette manière affecte $ s_1, s_2, s_3 $ à la destination de la connexion. Par conséquent, l'expression relationnelle suivante s'applique entre les quantités de changement. \Delta s_1=w_1 \Delta y_4 \Delta s_2=w_2 \Delta y_4 \Delta s_3=w_3 \Delta y_4

Le changement ci-dessus modifie également l'échelle d'évaluation des erreurs, comme indiqué dans l'équation suivante. \Delta E=\frac{\partial E}{\partial s_1} \Delta s_1+\frac{\partial E}{\partial s_2} \Delta s_2+\frac{\partial E}{\partial s_3} \Delta s_3

Organisez ceci et divisez les deux côtés par $ \ Delta s_4 $ en \frac{\partial E}{\partial s_4}=(\frac{\partial E}{\partial s_1}w_1+\frac{\partial E}{\partial w_2}s_2+\frac{\partial E}{\partial s_3}w_3)sigmoid'(s_4)

Est recherché. On peut voir que la formule ci-dessus est une sorte de formule graduelle dans laquelle $ \ partial E / \ partial s_i $ dans la couche intermédiaire est obtenu par $ \ partial E / \ partial s_j $ dans la couche de sortie. De même, on peut voir que l'erreur peut être propagée aux couches inférieures en trouvant $ \ partial E / \ partial s $ de la couche finale pour n'importe quel nombre de NN.

Finalement, \frac{\partial s_4}{\partial w_4}=y_5 À \frac{\partial E}{\partial w_4}=\frac{\partial E}{\partial s_4}\frac{\partial s_4}{\partial w_4} Remplacer dans \frac{\partial E}{\partial w_4}=\frac{\partial E}{\partial s_4}y_5 Obtenir. $ sigmoid '(s) $ simplifie le calcul en utilisant $ y = sigmoid (s) $ indiqué dans la partie neurone unique.

Code de référence

Désolé pour le code assez sale, mais je vais le coller ci-dessous. Le seuil (biais) est fixé pour tous les neurones par souci de simplicité. Lors de la création du code, ajoutez un élément avec une valeur de 1 au début du vecteur d'entrée, ajoutez un élément de biais au vecteur de pondération et ajustez les paramètres dans le cadre du poids.

python


# coding: utf-8

import numpy as np
Afrom numpy.random import randint
import sys


class NN:
    def __init__(self):
        self.alph = 0.04
        self.mu = 0.01
        self.theta = 0.1
        self.w = []
        self.output = []
        self.output_sigm = []
        self.T = 0

    def create_data(self, input_n_row, input_n_col, layer_sizes):
        self.x = randint(2, size=(input_n_row, input_n_col))
        self.y = randint(2, size=(input_n_row, layer_sizes[-1]))
        for i_layer, size in enumerate(layer_sizes):
            if i_layer == 0:
                self.w.append(np.random.randn(input_n_col, size))
                self.output.append(np.zeros((input_n_row, size)))
                self.output_sigm.append(np.zeros((input_n_row ,size)))
            else:
                self.w.append(np.random.randn(layer_sizes[i_layer-1], size))
                self.output.append(np.zeros((input_n_row, size)))
                self.output_sigm.append(np.zeros((input_n_row ,size)))

    def fit(self, eps=10e-6):
        error = sys.maxint
        self.forward()
        while error>eps:
            self.update( self.backword() )
            self.forward()
            error = self.calculate_error()
            self.T += 1
            print "T=", self.T
            print "error", error

    def calculate_error(self):
        return np.sum( np.power(self.y - self.output_sigm[-1], 2) )

    def forward(self):
        for i_layer in xrange(len(self.output)):
            if i_layer == 0:
                self.output[i_layer] = self.x.dot(self.w[i_layer])
                self.output_sigm[i_layer] = self.sigmoid(self.output[i_layer])
            else:
                self.output[i_layer] = self.output_sigm[i_layer-1].dot(self.w[i_layer])
                self.output_sigm[i_layer] = self.sigmoid(self.output[i_layer])

    def backword(self):
        result = []
        for i_layer in range(len(self.w))[::-1]:
            if i_layer==len(self.w)-1:
                result.insert(0, self.diff(self.output_sigm[i_layer], self.y) )
            else:
                result.insert(0, self.diff_mult( self.output_sigm[i_layer], result[0].dot(self.w[i_layer+1].T)) )
        return result

    def update(self, diff):
        for i_layer in range(len(self.w))[::-1]:
            if i_layer==0:
                for i_row in xrange(len(diff[i_layer])):
                    self.w[i_layer] -= self.get_incremental_update_value(
                                              self.x[i_row].reshape(len(self.w[i_layer]),1),
                                              diff[i_layer][i_row,:].reshape(1,self.w[i_layer].shape[1])
                                          )
            else:
                for i_row in xrange(len(diff[i_layer])):
                    self.w[i_layer] -= self.get_incremental_update_value(
                                              self.output_sigm[i_layer-1][i_row,:].reshape(len(self.w[i_layer]),1),
                                              diff[i_layer][i_row,:].reshape(1,self.w[i_layer].shape[1])
                                          )

    def get_incremental_update_value(self, input_data, diff):
        return np.kron(input_data, self.mu*diff)

    def diff(self, y, t):
        return self.alph * 2*(y - t) * self.dsigmoid(y)

    def diff_mult(self, y, prp_value):
        return self.alph * self.dsigmoid(y) * prp_value

    def sigmoid(self, s, alph=0.01):
        return 1/(1+np.exp(-self.alph*(s-self.theta)))

    def dsigmoid(self, y):
        return y * (1 - y)

if __name__=='__main__':
    layer_sizes = (4,3)
    input_layer_size = 3 
    input_data_size = 1000

    nn = NN()
    nn.create_data(input_data_size, input_layer_size, layer_sizes)
    nn.fit()

Nous vous prions de nous excuser pour la gêne occasionnée, mais nous vous serions reconnaissants de bien vouloir signaler toute erreur.

Recommended Posts

Théorie et implémentation simples des réseaux neuronaux
Implémentation de réseau neuronal simple à l'aide de la préparation Chainer-Data-
Implémentation de réseau neuronal simple à l'aide de la description du modèle Chainer-
Normalisation de la théorie et de la mise en œuvre des flux
Implémentation de réseau neuronal en python
Implémentation de réseau neuronal (NumPy uniquement)
Réseau neuronal avec OpenCV 3 et Python 3
Implémentation d'un réseau de neurones à deux couches 2
PRML Chapitre 5 Implémentation Python du réseau neuronal
Modèle de classification simple avec réseau neuronal
Explication et mise en œuvre du perceptron simple
Implémentation d'un réseau neuronal à 3 couches (pas d'apprentissage)
Implémentation de réseaux neuronaux "flous" avec Chainer
2. Écart moyen et standard avec le réseau neuronal!
Réseau neuronal paramétrique
Estimation de l'auteur à l'aide du réseau neuronal et de Doc2Vec (Aozora Bunko)
Implémenter un réseau neuronal convolutif
Mise en œuvre de l'optimisation bayésienne des hyper paramètres du réseau de neurones (Chainer + GPyOpt)
Implémenter le réseau neuronal à partir de zéro
Expérience de réseau de neurones pliable
Principes de base et mise en œuvre de Perceptron
Implémentation d'un réseau de neurones convolutifs utilisant uniquement Numpy
Le modèle linéaire généralisé (GLM) et le réseau neuronal sont les mêmes (1)
Apprentissage des classements à l'aide d'un réseau neuronal (implémentation RankNet par Chainer)
Classification d'images avec un réseau de neurones auto-fabriqué par Keras et PyTorch
Réseau de neurones pour comprendre et mettre en œuvre en mathématiques au secondaire
Le modèle linéaire généralisé (GLM) et le réseau neuronal sont les mêmes (2)
Théorie et mise en œuvre de modèles de régression multiple - pourquoi une régularisation est nécessaire -
Implémenter un réseau neuronal à 3 couches
Réseau de neurones avec Python (scikit-learn)
3. Distribution normale avec un réseau neuronal!
Explication et mise en œuvre de SocialFoceModel
Théorie de la prophétie et sa simulation (2)
Réseau de neurones commençant par Chainer
Tutoriel sur le réseau neuronal (CNN) de Pytorch 1.3.1.
4. Entourez les paramètres avec un réseau neuronal!
Description et implémentation de Maxout (Python)
Tutoriel TensorFlow - Réseau neuronal à convolution (traduction)
J'ai créé une caméra réseau simple en combinant ESP32-CAM et RTSP.
Fonctionnement simple du réseau en reliant Cisco DNA Center et le commutateur tactile
[Python] J'ai expliqué en détail la théorie et la mise en œuvre de la régression logistique
[Python] J'ai expliqué en détail la théorie et la mise en œuvre de l'arbre de décision