Il existe de nombreux documents sur Internet sur les bases et le mécanisme de l'apprentissage automatique, mais écrivons le code! Je pense qu'il est difficile de comprendre. Surtout le chainer et le tensorflow sont utiles, mais je ne comprends pas du tout même si je les installe, et certaines personnes essaient de déplacer l'exemple et de quitter sans bouger. De plus, l'ensemble d'images fourni avec le chaîneur dans l'exemple de reconnaissance d'image peut ne pas comprendre ce que c'est lorsque vous essayez de lire le code. Donc, tout d'abord, j'ai décidé d'écrire cet article dans le but de ** implémenter l'exemple le plus simple de mnist de reconnaissance de caractères manuscrits à partir de zéro en utilisant le chainer et comprendre le mécanisme et comment écrire du code **. J'ai récemment commencé à étudier le chainer comme passe-temps, mais je suis un amateur, donc mon but est de vérifier ma compréhension en écrivant des articles. De plus, je pense que ici sera utile pour le mécanisme et l'étude du réseau neuronal lui-même.
Jusqu'à ce que je touche au chainer, je faisais souvent des rayures complètes en utilisant le langage de base C, et j'étais toujours conscient que le programme que j'écrivais était "input ○, output ×". En conséquence, j'ai souffert d'un exemple de code où le code d'entrée des données, l'ordre et le stockage des données étaient masqués, et la sortie n'était que les informations du modèle après l'entraînement (rires). Depuis que je l'ai appris, j'ai pensé que ce serait comme s'il y avait des entrées et des sorties. C'est une punition qui a hésité à lire la bibliothèque.
Créez un environnement dans lequel python peut être exécuté. Dans mon environnement, j'ai installé python3.5 en utilisant pyenv. Essayez d'installer le chainer avec pip ou quelque chose comme ça. Pour référence
chainer==1.13.0
J'utilise. Vous devez d'abord obtenir les données d'entrée et les lire comme un vecteur. chainer/example/mnist/ Vous pouvez trouver le code dans data.py ci-dessous, alors copiez-le dans votre répertoire de développement. Comme une magie à nouveau
chainer_test.py
import numpy as np
import chainer
from chainer import cuda, Function, gradient_check, report, training, utils, Variable
from chainer import datasets, iterators, optimizers, serializers
from chainer import Link, Chain, ChainList
import chainer.functions as F
import chainer.links as L
from chainer.training import extensions
import data
Veuillez écrire le code source. Je vais l'ajouter à ce fichier source ci-dessous.
Il existe quatre configurations de réseau (entrée, couche cachée 1, couche cachée 2, sortie). Les dimensions respectives sont 784, 100, 100, 10. Pour l'entrée, c'est 28 * 28 px. Comme pour la sortie, 10 dimensions sont utilisées pour exprimer 0-9.
chainer_test.py
class MLP(Chain):
def __init__(self):
super(MLP, self).__init__(
l1=L.Linear(784, 100),
l2=L.Linear(100, 100),
l3=L.Linear(100, 10),
)
def __call__(self, x):
h1 = F.relu(self.l1(x))
h2 = F.relu(self.l2(h1))
y = self.l3(h2)
return y
Il est décrit comme. Tout d'abord, à propos de init, qui définit la structure des couches. On a l'impression que la dimension vectorielle change comme 784-> 100, 100-> 100, 100-> 10. Ensuite, l'appel est l'état de propagation dans chaque couche, c'est-à-dire le calcul de l'avant. La fonction de tir est systématiquement propagée à la sortie de la couche cornée dans le réseau neuronal, mais cela est préparé à l'avance par le chaîneur, et F.relu () est utilisé ici. Bien sûr, il devrait y avoir tanh et ainsi de suite.
De plus, nous allons créer une fonction appelée Predict, qui est personnellement importante. La raison en est qu'il est agréable de s'entraîner et de voir le taux de perte, mais lorsque vous utilisez vous-même le réseau neuronal formé, il est difficile de comprendre ce qu'est l'API après tout. Il y a peut-être d'autres bons moyens, mais je vais mettre en œuvre la prédiction moi-même.
chainer_test.py
def predict(model, x_data):
x = Variable(x_data.astype(np.float32))
y = model.predictor(x)
return np.argmax(y.data, axis = 1)
Cela signifie que le modèle entraîné (décrit plus loin) et le vecteur d'entrée (784 dimensions * N (nombre de vecteurs)) sont utilisés comme arguments, le vecteur d'entrée est défini sur float32, l'entrée est entrée dans le prédicteur, la sortie est sortie (dimension 10) et le maximum est Renvoie un index contenant un nombre. Etc. Cela vous donnera une sortie facile à comprendre.
Préparez les données.
chainer_test.py
batchsize = 100
datasize = 60000
N = 10000
mnist = data.load_mnist_data()
x_all = mnist['data'].astype(np.float32) / 255
y_all = mnist['target'].astype(np.int32)
x_train, x_test = np.split(x_all, [datasize])
y_train, y_test = np.split(y_all, [datasize])
la taille du lot et N seront décrits plus loin. Stockez les données avec data.load_mnist_data (). Ensuite, mnist ['data'], ['target'] récupère l'entrée et sa classification. Habituellement, au lieu d'utiliser toutes les données préparées pour l'entraînement, il est courant d'en former certaines et de tester le reste. Cette fois aussi, nous en avons préparé deux, x_traint et x_test.
Créez un modèle en vue de l'apprentissage.
chainer_test.py
model = L.Classifier(MLP())
optimizer = optimizers.Adam()
optimizer.setup(model)
Dans un problème de classification comme celui-ci, L.Classifier (), qui implémente le calcul de la fonction de perte et le rapport d'erreur, est préparé à l'avance, donnez-lui donc la classe définie ci-dessus et affichez-la sous forme de modèle. L'optimiseur est un excellent outil qui définit automatiquement de bons paramètres basés sur des méthodes mathématiques.
Je vais réellement commencer à apprendre.
chainer_test.py
for epoch in range(20):
print('epoch % d' % epoch)
indexes = np.random.permutation(datasize)
sum_loss, sum_accuracy = 0, 0
for i in range(0, datasize, batchsize):
x = Variable(np.asarray(x_train[indexes[i : i + batchsize]]))
t = Variable(np.asarray(y_train[indexes[i : i + batchsize]]))
optimizer.update(model, x, t)
sum_loss += float(model.loss.data) * batchsize
sum_accuracy += float(model.accuracy.data) * batchsize
print('train mean loss={}, accuracy={}'.format(sum_loss / datasize, sum_accuracy / datasize))
sum_loss, sum_accuracy = 0, 0
for i in range(0, N, batchsize):
x = Variable(np.asarray(x_test[i : i + batchsize]),volatile='on')
t = Variable(np.asarray(y_test[i : i + batchsize]),volatile='on')
loss = model(x, t)
sum_loss += float(loss.data) * batchsize
sum_accuracy += float(model.accuracy.data) * batchsize
print('test mean loss={}, accuracy={}'.format(sum_loss / N, sum_accuracy / N))
l'époque est le nombre de fois où l'apprentissage est répété. Cette fois, nous allons nous entraîner et tester à chaque époque. Au moment de l'apprentissage, le tableau est réorganisé de manière appropriée et 0 ~ batchsize est répété fois data / batchsize. Le test réel est créé à partir de i avec un index de i + batchsize (entrée, données de réponse correctes) = (x, t), et entraîné par l'optimiseur (modèle, x, t). Après cela, répétez cette opération et sortez le taux de perte moyen et la précision. Le test est presque le même.
Donnez au modèle formé un vecteur et voyez si la réponse est correcte.
chainer_test.py
p_test = np.empty((0, 784), float)
p_test = np.append(p_test, np.array([x_test[0]]), axis=0)
p_test = np.append(p_test, np.array([x_test[1]]), axis=0)
print(p_test)
print(predict(model, p_test))
print(y_test)
serializers.save_hdf5('myMLP.model',model)
p_test est le vecteur de l'entrée que vous voulez essayer. Cette fois, il était difficile de se préparer moi-même, j'ai donc utilisé les 0e et 1er vecteurs utilisés dans le test comme données vectorielles. Vous voudrez peut-être jouer avec certaines des valeurs. En fait, lorsque j'essaie de l'utiliser, les deux premiers de y_test apparaissent comme la valeur de retour de prédire, cela signifie donc que l'apprentissage est réussi (je pense).
La dernière ligne écrit le modèle sous forme de fichier. Vous pouvez maintenant le réutiliser.
Mise en œuvre de la mnist chainer à partir de zéro Le site de traduction en japonais a été très utile pour ce test. Personnellement, je suis surpris de la facilité d'écriture du cours de chainer. À l'avenir, j'aimerais utiliser mon temps libre pour écrire sur le code source de la bibliothèque elle-même et sur l'implémentation d'imagenet à partir de zéro.