[PYTHON] Essayez de créer un réseau de neurones / d'apprentissage en profondeur avec scratch

1.Tout d'abord

Cette fois, afin de comprendre la propagation vers l'avant et la propagation des erreurs, je vais essayer d'implémenter un réseau de neurones réellement en mouvement avec scratch. L'ensemble de données utilise MNIST.

2. Spécifications du réseau neuronal

Un réseau neuronal avec 28 x 28 = 784 couches d'entrée, 10 couches intermédiaires et 2 couches de sortie, la fonction d'activation / fonction d'erreur est sigmoïde et la méthode d'optimisation est la méthode de descente de gradient.

Pour l'ensemble de données, "1" et "7" sont extraits de MNIST et une classification binaire est effectuée. スクリーンショット 2020-03-16 09.00.03.png

3. Propagation vers l'avant

Premièrement, lorsque vous calculez $ a ^ 0_0 $, il y a 784 entrées de $ x ^ 0_0 $ à $ x ^ 0_ {783} $, chacune avec des poids $ w ^ 0_ {00} $ à $ w ^ 0_ {783,0} $ est bloqué, donc スクリーンショット 2020-03-16 09.12.07.png

Exprimé sous forme de matrice, tous les calculs de $ a ^ 0_0 $ à $ a ^ 0_9 $ peuvent être facilement représentés. スクリーンショット 2020-03-16 09.19.28.png

Puisque $ x ^ 1_0 $ à $ x ^ 1_9 $ est le résultat du passage de $ a ^ 0_0 $ à $ a ^ 0_9 $ via la fonction d'activation sigmoïde, スクリーンショット 2020-03-16 09.21.38.png

Ensuite, lorsque vous calculez $ a ^ 1_0 $, il y a 10 entrées de $ x ^ 1_0 $ à $ x ^ 1_9 $, chacune avec des poids $ w ^ 1_ {00} $ à $ w ^ 1_ {90. } $ Est bloqué, donc スクリーンショット 2020-03-16 09.25.48.png

Comme précédemment, si $ a ^ 1_0 $ et $ a ^ 1_1 $ sont représentés par une matrice, スクリーンショット 2020-03-16 18.33.38.png

Enfin, $ y ^ 0 $ et $ y ^ 1 $ sont スクリーンショット 2020-03-16 19.29.15.png

De cette manière, la propagation vers l'avant peut être facilement réalisée par le produit interne de la matrice ou de l'addition.

4. Rétro-propagation d'erreur (de la couche intermédiaire à la couche de sortie)

Tout d'abord, mettez à jour les pondérations et les biais de la couche intermédiaire à la couche de sortie.

L'expression de mise à jour pour le poids w peut être représentée par $ w = w- \ eta * \ frac {\ partial E} {\ partial w} $. Où $ \ eta $ est le taux d'apprentissage et $ \ frac {\ partial E} {\ partial w} $ est l'erreur E différenciée par le poids w.

Donnons un exemple concret de $ \ frac {\ partial E} {\ partial w} $ et exprimons-le avec une formule générale pour l'implémenter. Tout d'abord, les pondérations de la couche intermédiaire à la couche de sortie.

スクリーンショット 2020-03-15 19.10.21.png Trouvez $ \ frac {\ partial E ^ 0} {\ partial w ^ 1_ {00}} $ pour mettre à jour le poids $ w ^ 1_ {00} $. Du rapport en chaîne de la différenciation スクリーンショット 2020-03-15 19.14.30.png Exprimé sous forme de formule générale, k = 0 à 9, j = 0 à 1, スクリーンショット 2020-03-16 08.44.27.png Cela permet de mettre à jour le poids $ w ^ 1_ {kj} $. En ce qui concerne le biais, $ b ^ 1 $ vaut 1, donc $ x ^ 1_k $ dans la formule ci-dessus remplace juste 1. スクリーンショット 2020-03-16 10.02.58.png Cela permet de mettre à jour le biais $ b ^ 1_j $.

5. Rétro-propagation d'erreur (couche d'entrée vers couche intermédiaire)

Vient ensuite la mise à jour des poids et biais de la couche d'entrée à la couche intermédiaire.

スクリーンショット 2020-03-16 10.15.30.png

Pour mettre à jour le poids $ w ^ 0_ {00} $, $ \ frac {\ partial E ^ 0} {\ partial w ^ 0_ {00}} $ et $ \ frac {\ partial E ^ 1} {\ Vous devez trouver un w ^ 0_ {00}} $ partiel. Du rapport en chaîne de la différenciation スクリーンショット 2020-03-16 08.32.17.png Exprimé sous forme de formule générale, k = 0 à 783, j = 0 à 9, スクリーンショット 2020-03-16 08.33.56.png Cela permet de mettre à jour le poids $ w ^ 0_ {kj} $. En ce qui concerne le biais, $ b ^ 0 $ vaut 1, donc $ x ^ 0_k $ dans la formule ci-dessus remplace simplement 1. スクリーンショット 2020-03-16 10.11.34.png Cela permet de mettre à jour le biais $ b ^ 0_j $.

6. Mise en œuvre de la partie propagation directe et propagation arrière d'erreur

En vous basant sur la formule générale obtenue précédemment, implémentez les parties propagation directe et propagation arrière d'erreur.

#Fonction Sigmaid
def sigmoid(a):
    return 1 / (1 + np.exp(-a))

#Différenciation de la fonction sigmoïde
def sigmoid_d(a):
    return (1 - sigmoid(a)) * sigmoid(a)

#Erreur de propagation de retour
def back(l, j):
    if l == max_layer - 1:
        return (y[j] - t[j]) * sigmoid_d(A[l][j])
    else:
        output = 0
        m = A[l+1].shape[0]   
        for i in range(m):
            output += back(l+1, i) * W[l+1][i,j] * sigmoid_d(A[l][j])
        return output

Le mouvement spécifique de def back (l, j): est

Lorsque «l = 1», (y [j] -t [j]) * sigmoid_d (A [1] [j]) est retourné.

Lorsque l = 0,  (y[0]-t[0])*sigmoid_d(A[1][0])*W[1][0,j]*sigmoid_d(A[0][j])  +(y[1]-t[1])*sigmoid_d(A[1][1])*W[1][1,j]*sigmoid_d(A[0][j]) Est retourné.

#Réglage poids W
np.random.seed(seed=7)
w0 = np.random.normal(0.0, 1.0, (10, 784))
w1 = np.random.normal(0.0, 1.0, (2, 10))
W = [w0, w1]

#Réglage du biais b
b0 = np.ones((10, 1))
b1 = np.ones((2, 1))
B = [b0, b1]

#Autres réglages
max_layer = 2 #Définition du nombre de couches
n = 0.5  #Réglage du taux d'apprentissage

Définissez le poids W, la polarisation b et d'autres paramètres.

スクリーンショット 2020-03-16 19.48.21.png Chaque terme de la matrice de poids w0 et w1 est un nombre aléatoire qui suit une distribution normale de 0 à 1 afin que l'apprentissage puisse commencer en douceur. Au fait, si vous changez la graine = nombre de np.random.seed (graine = 7), la condition de départ de l'apprentissage (qu'elle démarre en douceur ou soit un peu lente) changera. Chaque terme des matrices de biais b0 et b1 vaut 1.

#Boucle d'apprentissage
count = 0 
acc = []

for x, t in zip(xs, ts):
    
    #Propagation vers l'avant
    x0 = x.flatten().reshape(784, 1)
    a0 = W[0].dot(x0) + B[0]
    x1 = sigmoid(a0)
    a1 = W[1].dot(x1) + B[1]
    y = sigmoid(a1)

    #X pour la mise à jour des paramètres,Lister un
    X = [x0, x1]
    A = [a0, a1]

    #Mise à jour des paramètres
    for l in range(len(X)):
        for j in range(W[l].shape[0]):
            for k in range(W[l].shape[1]):
                W[l][j, k] = W[l][j, k] - n * back(l, j) * X[l][k]  
            B[l][j] = B[l][j] - n * back(l, j) 

C'est une boucle d'apprentissage. La propagation vers l'avant peut être facilement réalisée par le produit interne de la matrice, l'addition, etc. Dans la mise à jour des paramètres,

Lorsque «l = 0», dans la plage de «j = 0 à 9, k = 0 à 783»  W[0][j,k] = W[0][j,k] - n * back(0,j) * X[0][k]  B[0][j] = B[0][j] - n * back(0,j) Sera mis à jour.

Lorsque «l = 1», dans la plage de «j = 0 à 1, k = 0 à 9»  W[1][j,k] = W[1][j,k] - n * back(0,j) * X[0][k]  B[1][j] = B[1][j] - n * back(0,j) Sera mis à jour.

7. Préparation de l'ensemble de données

Lisez l'ensemble de données MNIST avec Keras et extrayez uniquement "1" et "7".

import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
import matplotlib.pyplot as plt

#Affichage numérique
def show_mnist(x):
    fig = plt.figure(figsize=(7, 7))   
    for i in range(100):
        ax = fig.add_subplot(10, 10, i+1, xticks=[], yticks=[])
        ax.imshow(x[i].reshape((28, 28)), cmap='gray')
    plt.show()

#Lecture de l'ensemble de données
(x_train, y_train), (x_test, y_test) = mnist.load_data()
show_mnist(x_train)

# 1,7 extraits
x_data, y_data = [], []
for i in range(len(x_train)):  
    if y_train[i] == 1 or y_train[i] == 7:
       x_data.append(x_train[i])
       if y_train[i] == 1:
          y_data.append(0)
       if y_train[i] == 7:
          y_data.append(1)

show_mnist(x_data)

#Convertir du format de liste au format numpy
x_data = np.array(x_data)
y_data = np.array(y_data)

# x_normalisation des données, y_Représentation unique des données
x_data = x_data.astype('float32')/255
y_data = np_utils.to_categorical(y_data)

#Apprenez, obtenez des données de test
xs = x_data[0:200]
ts = y_data[0:200]  
xt = x_data[2000:3000]  
tt = y_data[2000:3000] 

スクリーンショット 2020-03-16 14.42.10.png スクリーンショット 2020-03-16 14.42.25.png Les données de 0 à 9 et les données dont 1 et 7 sont extraites sont affichées depuis le début.

Préparez 200 éléments de données d'entraînement xs et ts, et 1 000 éléments de données de test xt et tt.

8. Mise en œuvre complète

C'est l'ensemble de la mise en œuvre avec l'ajout de la confirmation de la précision par les données de test et l'affichage du graphique de transition de précision pour chaque apprentissage.

import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils

#Lecture de l'ensemble de données
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 1,Extraire seulement 7 numéros
x_data, y_data = [], []
for i in range(len(x_train)):  
    if y_train[i] == 1 or y_train[i] == 7:
       x_data.append(x_train[i])
       if y_train[i] == 1:
          y_data.append(0)
       if y_train[i] == 7:
          y_data.append(1)

#Convertir du format de liste au format numpy
x_data = np.array(x_data)
y_data = np.array(y_data)

# x_normalisation des données, y_Une donnée chaude
x_data = x_data.astype('float32')/255
y_data = np_utils.to_categorical(y_data)

#Acquisition de données d'entraînement et de données de test
xs = x_data[0:200]  
ts = y_data[0:200]  
xt = x_data[2000:3000]  
tt = y_data[2000:3000]  


#Fonction Sigmaid
def sigmoid(a):
    return 1 / (1 + np.exp(-a))

#Différenciation de la fonction sigmoïde
def sigmoid_d(a):
    return (1 - sigmoid(a)) * sigmoid(a)

#Erreur de propagation de retour
def back(l, j):
    if l == max_layer - 1:
        return (y[j] - t[j]) * sigmoid_d(A[l][j])
    else:
        output = 0
        m = A[l+1].shape[0]   
        for i in range(m):
            output += back(l + 1, i) * W[l + 1][i, j] * sigmoid_d(A[l][j])
        return output

#Réglage poids W
np.random.seed(seed=7)
w0 = np.random.normal(0.0, 1.0, (10, 784))
w1 = np.random.normal(0.0, 1.0, (2, 10))
W = [w0, w1]

#Réglage du biais b
b0 = np.ones((10, 1))
b1 = np.ones((2, 1))
B = [b0, b1]

#Autres réglages
max_layer = 2 #Définition du nombre de couches
n = 0.5  #Réglage du taux d'apprentissage

#Boucle d'apprentissage
count = 0 
acc = []

for x, t in zip(xs, ts):
    
    #Propagation vers l'avant
    x0 = x.flatten().reshape(784, 1)
    a0 = W[0].dot(x0) + B[0]
    x1 = sigmoid(a0)
    a1 = W[1].dot(x1) + B[1]
    y = sigmoid(a1)

    #X pour la mise à jour des paramètres,Lister un
    X = [x0, x1]
    A = [a0, a1]

    #Mise à jour des paramètres
    for l in range(len(X)):
        for j in range(W[l].shape[0]):
            for k in range(W[l].shape[1]):
                W[l][j, k] = W[l][j, k] - n * back(l, j) * X[l][k]  
            B[l][j] = B[l][j] - n * back(l, j) 
            
    #Contrôle de l'exactitude par les données de test
    correct, error = 0, 0

    for i in range(1000):

        #Inférence avec les paramètres appris
        x0 = xt[i].flatten().reshape(784, 1)
        a0 = W[0].dot(x0) + B[0]
        x1 = sigmoid(a0)
        a1 = W[1].dot(x1) + B[1]
        y = sigmoid(a1)
    
        if np.argmax(y) == np.argmax(tt[i]):
           correct += 1
        else:
           error += 1
    calc = correct/(correct+error)
    acc.append(calc)
    count +=1
    print("\r[%s] acc: %s"%(count, calc))
   
#Affichage du graphique de transition de précision
import matplotlib.pyplot as plt
plt.plot(acc, label='acc')
plt.legend()
plt.show()   

スクリーンショット 2020-03-16 17.21.46.png En 200 étapes, la précision de la classification était de 97,8%. Ce serait formidable si le réseau de neurones que j'ai implémenté en grattant fonctionne correctement.

Recommended Posts

Essayez de créer un réseau de neurones / d'apprentissage en profondeur avec scratch
Apprentissage par renforcement 10 Essayez d'utiliser un réseau neuronal formé.
[Deep Learning from scratch] À propos des couches requises pour implémenter le traitement de rétropropagation dans un réseau neuronal
Essayez l'apprentissage en profondeur avec TensorFlow
Essayez le Deep Learning avec FPGA
Essayez le Deep Learning avec les concombres FPGA-Select
[Evangelion] Essayez de générer automatiquement des lignes de type Asuka avec Deep Learning
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 16) J'ai essayé de créer SimpleConvNet avec Keras
Essayez l'apprentissage en profondeur avec TensorFlow Partie 2
(Maintenant) Construisez un environnement GPU Deep Learning avec GeForce GTX 960
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 17) J'ai essayé de créer DeepConvNet avec Keras
[Apprentissage en profondeur] Classification d'images avec un réseau neuronal convolutif [DW jour 4]
J'ai essayé d'écrire dans un modèle de langage profondément appris
Version Lua Apprentissage profond à partir de zéro Partie 6 [Traitement d'inférence de réseau neuronal]
Introduction au Deep Learning (2) - Essayez votre propre régression non linéaire avec Chainer-
Composez avec un réseau neuronal! Run Magenta
Apprentissage profond / Apprentissage profond à partir de zéro 2-Essayez de déplacer GRU
Essayez les prévisions de prix Bitcoin avec Deep Learning
Essayez avec Chainer Deep Q Learning - Lancement
Essayez l'apprentissage profond de la génomique avec Kipoi
Créez un classificateur avec un taux de reconnaissance de l'écriture manuscrite de 99,2% à l'aide du réseau neuronal convolutif TensorFlow
PPLM: Une technique simple de Deep Learning pour générer des phrases avec des attributs spécifiés
Créez un environnement d'apprentissage pour le «Deep learning from scratch» avec Cloud9 (jupyter miniconda python3)
Expérimentez avec divers algorithmes d'optimisation sur le réseau neuronal
Deep Learning from scratch ① Chapitre 6 "Techniques liées à l'apprentissage"
Essayez de dessiner une courbe de vie avec python
Essayez de créer un code de "décryptage" en Python
Essayez de créer un groupe de dièdre avec Python
Créer un environnement d'apprentissage automatique Python avec des conteneurs
Python vs Ruby "Deep Learning from scratch" Chapitre 3 Implémentation d'un réseau neuronal à 3 couches
Créez un environnement python pour apprendre la théorie et la mise en œuvre de l'apprentissage profond
J'ai essayé d'extraire le dessin au trait de l'image avec Deep Learning
[Deep Learning from scratch] Valeur initiale du poids du réseau neuronal utilisant la fonction sigmoïde
Apprentissage profond à partir de zéro
Une histoire de prédiction du taux de change avec Deep Learning
Entraînez les données MNIST avec PyTorch en utilisant un réseau neuronal
Faisons un outil de veille de commande avec python
Essayez de créer un Checkbutton dynamiquement avec Tkinter en Python
Je veux escalader une montagne avec l'apprentissage par renforcement
Essayez de prédire le taux de change (FX) avec un apprentissage automatique non approfondi
Créer un environnement de développement d'applications d'apprentissage automatique avec Python
Un échantillon pour essayer rapidement les machines de factorisation avec fastFM
Les débutants en apprentissage automatique essaient de créer un arbre de décision
[Deep Learning] Exécuter la console de réseau neuronal SONY à partir de CUI
Bases de PyTorch (2) -Comment créer un réseau de neurones-
Learning Deep Forest, un nouveau dispositif d'apprentissage comparable à DNN
[Deep Learning from scratch] J'ai essayé d'expliquer le décrochage
Créez un environnement d'apprentissage automatique à partir de zéro avec Winsows 10
Osez apprendre avec Ruby "Deep Learning from scratch" Importation de fichiers pickle depuis PyCall interdit
Créez un "bot qui vous informe des actrices audiovisuelles aux visages similaires" grâce à l'apprentissage en profondeur
Étapes pour créer rapidement un environnement d'apprentissage en profondeur sur Mac avec TensorFlow et OpenCV
[Deep Learning from scratch] Poids initial du réseau neuronal lors de l'utilisation de la fonction Relu
J'ai essayé de mettre en œuvre le modèle de base du réseau neuronal récurrent
Implémenter un réseau neuronal à 3 couches
Créez une application Web qui reconnaît les nombres avec un réseau neuronal
Essayez de défier le sol par récursif
Apprentissage profond à partir de zéro 1 à 3 chapitres
Un exemple de python pour apprendre XOR avec un algorithme génétique sur un réseau neuronal
Créez un environnement d'apprentissage automatique scikit-learn avec VirtualBox et Ubuntu
[Apprentissage en profondeur] Découvrez comment utiliser chaque fonction du réseau neuronal convolutif [DW jour 3]