Suite de l'article précédent Notes sur les réseaux de neurones J'ai créé un réseau neuronal à deux couches et j'ai appris MNIST. Reportez-vous au chapitre 4 du Deep Learning à partir de zéro
TwoLayerNet.py
import numpy as np
class TwoLayerNet:
    
    def __init__(self,input_size,hidden_size,output_size,weight_init_std=0.01):
        #Initialisation du poids
        self.params = {}
        #784 *Matrice de 50 poids
        self.params['W1'] = weight_init_std * np.random.randn(input_size,hidden_size)
        #50 *10 matrice de poids
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size,output_size)
        #Biais, autant de couches cachées
        self.params['b1'] = np.zeros(hidden_size)
        #Biais, autant que le nombre de couches de sortie
        self.params['b2'] = np.zeros(output_size)
    
    def sigmoid(self,x):
        return 1 / (1 + np.exp(-x))
    
    def softmax(self,a):
        c = np.max(a)
        exp_a = np.exp(a - c)#Mesures de débordement
        sum_exp_a = np.sum(exp_a)
        y = exp_a / sum_exp_a
        return y
    
    def _numerical_gradient_1d(self,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(self,f, X):
        if X.ndim == 1:
            return self._numerical_gradient_1d(f, X)
        else:
            grad = np.zeros_like(X)
            for idx, x in enumerate(X):
                grad[idx] = self._numerical_gradient_1d(f, x)
            return grad
    def cross_entropy_error(self,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)) / batch_size
    
    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 #a = Wx + b
        z1 = self.sigmoid(a1)
        a2 = np.dot(z1,W2) + b2
        z2 = self.softmax(a2)
        
        return z2
    
    def loss(self, x, t):
        y = self.predict(x)
        
        return self.cross_entropy_error(y,t)
    
    def gradient(self,x,t):
        loss_W = lambda W: self.loss(x,t)
        grads = {}
        grads['W1'] = self.numerical_gradient(loss_W,self.params['W1'])
        grads['W2'] = self.numerical_gradient(loss_W,self.params['W2'])
        grads['b1'] = self.numerical_gradient(loss_W,self.params['b1'])
        grads['b2'] = self.numerical_gradient(loss_W,self.params['b2'])
        
        return grads
D'autre part, l'apprentissage par mini-lots (taille 50) a été effectué 500 fois à partir des données MNIST.
LearningMNIST.py
import numpy as np
from sklearn.datasets import fetch_mldata
from sklearn.preprocessing import OneHotEncoder
mnist = fetch_mldata('MNIST original', data_home=".")
x_train = mnist['data'][:60000]
t_train = mnist['target'][:60000]
train_loss_list = []
#Normalisation des données(0<=x<=1)je fais
x_train = x_train.astype(np.float64)
x_train /= x_train.max()
#one-Convertir en vecteur chaud
t_train = t_train.reshape(1, -1).transpose()
encoder = OneHotEncoder(n_values=max(t_train)+1)
t_train = encoder.fit_transform(t_train).toarray()
#hyper parameter
iters_num = 500
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1
#Puisque les données d'image sont 28x28, la couche d'entrée est 784, la couche cachée est 50, et la couche de sortie est 10 selon le nombre d'étiquettes.
network = TwoLayerNet(input_size=784,hidden_size=50,output_size=10)
for i in range(iters_num):
    batch_mask = np.random.choice(train_size,batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    
    grad = network.gradient(x_batch,t_batch)
    
    for key in ('W1','W2','b1','b2'):
        network.params[key] -= learning_rate * grad[key]
        
    loss = network.loss(x_batch,t_batch)
    train_loss_list.append(loss)
Ce résultat est le graphique ci-dessous, l'axe vertical est l'erreur d'entropie d'intersection et l'axe horizontal est le nombre d'itérations d'apprentissage.

L'erreur d'entropie croisée est réduite. La prochaine fois, nous vérifierons la précision de prédiction de ce réseau de neurones.
Recommended Posts