2017-10-09 9 views
1

J'ai étudié les réseaux de neurones depuis un moment et fait une implémentation avec python et numpy. J'ai fait un exemple très simple avec XOR et ça a bien marché. J'ai donc pensé aller plus loin et essayer la base de données MNIST.Neural Network MNIST

Il y a mon problème. J'utilise un NN avec 784 entrées, 30 neurones cachés et 10 neurones de sortie. La fonction d'activation du calque caché ne crache que les uns, de sorte que le réseau arrête essentiellement d'apprendre. Le calcul que je fais est correct et la même implémentation fonctionne bien avec l'exemple XOR et je lis le MNIST correctement. Donc je ne vois pas d'où vient le problème.

import pickle 
import gzip 

import numpy as np 

def load_data(): 
    f = gzip.open('mnist.pkl.gz', 'rb') 
    training_data, validation_data, test_data = pickle.load(f, encoding="latin1") 
    f.close() 
    return (training_data, validation_data, test_data) 

def transform_output(num): 
    arr = np.zeros(10) 
    arr[num] = 1.0 
    return arr 

def out2(arr): 
    return arr.argmax() 


data = load_data() 
training_data = data[0] 
training_input = np.array(training_data[0]) 
training_output = [transform_output(y) for y in training_data[1]] 

batch_size = 10 

batch_count = int(np.ceil(len(training_input)/batch_size)) 

input_batches = np.array_split(training_input, batch_count) 
output_batches = np.array_split(training_output, batch_count) 

#Sigmoid Function 
def sigmoid (x): 
    return 1.0/(1.0 + np.exp(-x)) 

#Derivative of Sigmoid Function 
def derivatives_sigmoid(x): 
    return x * (1.0 - x) 

#Variable initialization 
epoch=1 #Setting training iterations 
lr=2.0 #Setting learning rate 
inputlayer_neurons = len(training_input[0]) #number of features in data set 
hiddenlayer_neurons = 30 #number of hidden layers neurons 

output_neurons = len(training_output[0]) #number of neurons at output layer 

#weight and bias initialization 
wh=np.random.uniform(size=(inputlayer_neurons,hiddenlayer_neurons)) 
bh=np.random.uniform(size=(1,hiddenlayer_neurons)) 
wout=np.random.uniform(size=(hiddenlayer_neurons,output_neurons)) 
bout=np.random.uniform(size=(1,output_neurons)) 

for i in range(epoch): 
    for batch in range(batch_count): 

     X = input_batches[batch] 
     y = output_batches[batch] 

     zh1 = np.dot(X, wh) 
     zh = zh1 + bh 

     # data -> hidden neurons -> activations 
     ah = sigmoid(zh) 

     zo1 = np.dot(ah, wout) 
     zo = zo1 + bout 

     output = sigmoid(zo) 

     # data -> output neurons -> error 
     E = y - output 

     print("debugging") 
     print("X") 
     print(X) 
     print("WH") 
     print(wh) 
     print("zh1") 
     print(zh1) 
     print("bh") 
     print(bh) 
     print("zh") 
     print(zh) 
     print("ah") 
     print(ah) 
     print("wout") 
     print(wout) 
     print("zo1") 
     print(zo1) 
     print("bout") 
     print(bout) 
     print("zo") 
     print(zo) 
     print("out") 
     print(output) 
     print("y") 
     print(y) 
     print("error") 
     print(E) 
     # data -> output neurons -> slope 
     slope_out = derivatives_sigmoid(output) 

     # data -> output neurons -> change of error 
     d_out = E * slope_out 

     # data -> hidden neurons -> error = data -> output neurons -> change of error DOT output neurons -> output inputs (equal to hidden neurons) -> weights 
     error_hidden = d_out.dot(wout.T) 

     # data -> hidden neurons -> slope 
     slope_h = derivatives_sigmoid(ah) 

     # data -> hidden neurons -> change of error 
     d_hidden = error_hidden * slope_h 

     # hidden neurons -> output neurons -> weights = "" + hidden neurons -> data -> activations DOT data -> output neurons -> change of error 
     wout = wout + ah.T.dot(d_out) * lr 
     bout = bout + np.sum(d_out, axis=0, keepdims=True) * lr 

     wh = wh + X.T.dot(d_hidden) * lr 
     bh = bh + np.sum(d_hidden, axis=0, keepdims=True) * lr 
    # testing results 
    X = np.array(data[1][0][0:10]) 
    zh1 = np.dot(X, wh) 
    zh = zh1 + bh 

    # data -> hidden neurons -> activations 
    ah = sigmoid(zh) 

    zo1 = np.dot(ah, wout) 
    zo = zo1 + bout 

    output = sigmoid(zo) 
    print([out2(y) for y in output]) 
    print(data[1][1][0:10]) 

donc globalement la sortie du réseau de neurones est pour chaque entrée et la même formation avec des tailles de lots différents, les taux d'apprentissage et 100 époques n'a pas aidé.

Répondre

1

La différence entre les problèmes XOR et MNIST est le nombre de classes: XOR est une classification binaire et dans MNIST il y a 10 classes. Ce que vous calculez en tant qu'erreur E fonctionne pour XOR, car la fonction sigmoïde peut être utilisée dans le cas binaire. Quand il y a plus de 2 classes, vous devez utiliser un softmax function, qui est une version étendue de sigmoid, et cross entropy loss. Jetez un oeil à this question pour voir la différence. Vous avez correctement traduit y en un codage à chaud, mais output ne contient pas de distribution de probabilité prédite, en fait contient un vecteur de 10 valeurs, chacune très proche de 1.0. C'est pourquoi le réseau n'apprend pas.

+0

Merci pour la réponse rapide. J'ai utilisé le tutoriel suivant http://neuralnetworksanddeeplearning.com/chap1.html Il utilise un réseau similaire à moi, avec 10 neurones de sortie simples et sigmoïde comme moi et obtient environ 95% de taux de réussite après la première époque. Je vais passer en revue son code et le mien et comparer. Le diable est dans les détails. Mais oui, dès que j'ai ce travail, je vais certainement aller dans softmax, l'abandon, et relus etc. – Johannes

+0

Je suis en fait un peu sceptique que le réseau décrit peut faire une précision de 95%. Son exemple suivant utilise la régression logistique (ce que j'ai suggéré) puis le réseau neuronal convolutif (qui est beaucoup plus susceptible de montrer un tel résultat), peut-être était-ce ce modèle en action. Mais si vous pouviez me prouver que vous aviez tort et que vous arriviez à une précision de 90%, faites le moi savoir, je suis curieux d'essayer moi-même ce réseau. – Maxim

+0

J'ai couru son code et j'ai obtenu 90% après la première époque à plusieurs reprises. Les différences que j'ai vues jusqu'ici, c'est qu'il divise le taux d'apprentissage en fonction de la taille du lot et randomise les lots, ce que je n'ai pas fait. Mais cela ne tient pas compte de mon problème. Je n'obtiens rien, toutes les activations de neurones sont toutes 1 dans la couche cachée et de sortie – Johannes