** 2016/7/18: corrigé car une erreur s'est produite dans la formule de calcul de la taille après le filtrage. ** **
Ces dernières années, l'IA, le deep learning, etc. ont fait du bruit à divers endroits. Je pense que le nombre de bibliothèques a augmenté et que l'atmosphère est devenue plus facile à essayer. Par conséquent, je vais essayer d'analyser les émotions de Tweet en utilisant Chainer. Faisons quelque chose de similaire avec Chainer en faisant référence à Article sur Theano.
Cependant, si vous êtes habitué aux bibliothèques d'apprentissage automatique telles que sklearn, c'est un peu difficile à utiliser, donc si vous pouvez résoudre cela également.
Il peut y avoir des erreurs parce qu'il contient ma propre compréhension, mais je vous serais reconnaissant de bien vouloir le signaler.
Mac OSX Yosemite 10.10.15 Python 2.7 CPU Intel Core i5 2.6GHz Mémoire 8 Go
(Est-ce que ça va avec un tel équipement? → Je ne sais pas)
pip install chainer
Dans sklearn
model = (SVM ou forêt aléatoire)
model.fit(x_train,y_train)
y_p = model.predict(x_test)
C'était facile à faire.
Où x_train est une matrice de grandeur $ N x M $ et y_train est un vecteur enseignant de longueur $ N $ (tel que 0,1). $ N $ est la taille de l'échantillon et $ M $ est le nombre d'entités. x_test est les données de test avec le même nombre de colonnes (c'est-à-dire la même taille d'entités) que x_train.
D'autre part, Chainer n'a pas de méthodes comme "fit" et "prédire" comme ça, vous devez le faire vous-même.
Par exemple, dans Perceptron multicouche (MLP), il semble implémenter comme suit.
Classe de base comme suit
# -*- coding: utf-8 -*-
from chainer import FunctionSet, Variable, optimizers
from chainer import functions as F
from sklearn import base
from abc import ABCMeta, abstractmethod
import numpy as np
import six
class BaseChainerEstimator(base.BaseEstimator):
__metaclass__= ABCMeta # python 2.x
def __init__(self, optimizer=optimizers.SGD(), n_iter=10000, eps=1e-5, report=100,
**params):
self.network = self._setup_network(**params)
self.optimizer = optimizer
self.optimizer.setup(self.network.collect_parameters())
self.n_iter = n_iter
self.eps = eps
self.report = report
@abstractmethod
def _setup_network(self, **params):
return FunctionSet(l1=F.Linear(1, 1))
@abstractmethod
def forward(self, x, train=True):
y = self.network.l1(x)
return y
@abstractmethod
def loss_func(self, y, t):
return F.mean_squared_error(y, t)
@abstractmethod
def output_func(self, h):
return F.identity(h)
def fit(self, x_data, y_data):
batchsize = 100
N = len(y_data)
for loop in range(self.n_iter):
perm = np.random.permutation(N)
sum_accuracy = 0
sum_loss = 0
for i in six.moves.range(0, N, batchsize):
x_batch = x_data[perm[i:i + batchsize]]
y_batch = y_data[perm[i:i + batchsize]]
x = Variable(x_batch)
y = Variable(y_batch)
self.optimizer.zero_grads()
yp = self.forward(x)
loss = self.loss_func(yp,y)
loss.backward()
self.optimizer.update()
sum_loss += loss.data * len(y_batch)
sum_accuracy += F.accuracy(yp,y).data * len(y_batch)
if self.report > 0 and loop % self.report == 0:
print('loop={}, train mean loss={} , train mean accuracy={}'.format(loop, sum_loss / N,sum_accuracy / N))
return self
def predict(self, x_data):
x = Variable(x_data)
y = self.forward(x,train=False)
return self.output_func(y).data
class ChainerClassifier(BaseChainerEstimator, base.ClassifierMixin):
def predict(self, x_data):
return BaseChainerEstimator.predict(self, x_data).argmax(1) #argmax renvoie le plus grand index de la ligne de la matrice. Autrement dit, la classe est de 0 à 1,Doit être 2
def predict_proba(self,x_data):
return BaseChainerEstimator.predict(self, x_data)
En plus de cela, les classes MLP sont héritées de ChainerClassifier.
class MLP3L(ChainerClassifier):
"""
3-Layer Perceptron
"""
def _setup_network(self, **params):
network = FunctionSet(
l1=F.Linear(params["input_dim"], params["hidden_dim"]),
l2=F.Linear(params["hidden_dim"], params["hidden_dim"]),
l3=F.Linear(params["hidden_dim"], params["n_classes"]),
)
return network
def forward(self, x, train=True):
h1 = F.dropout(F.relu(self.network.l1(x)),train=train)
h2 = F.dropout(F.relu(self.network.l2(h1)),train=train)
y = self.network.l3(h2)
return y
def loss_func(self, y, t):
return F.softmax_cross_entropy(y, t)
def output_func(self, h):
return F.softmax(h)
Implémenter.
Vous pouvez maintenant utiliser "fit" et "predict (predict_proba)" tout comme sklearn.
Il semble que x_data doit être de type numpy.float32 et y_data doit être de type numpy.int32. (Moulé sur l'ajustement intérieur variable de Chainer)
Maintenant, dans le cas du MLP ci-dessus, les x_data ci-dessus peuvent être une matrice de taille $ N × M $ comme sklearn. Cependant, si vous essayez d'étendre cela à, par exemple, un réseau neuronal convolutif (CNN), des problèmes surviennent soudainement.
Étant donné que CNN est principalement utilisé dans le traitement d'image, l'entrée est bidimensionnelle, et si vous ajoutez la taille du lot (taille de l'échantillon) à cela, vous devez le rendre x_data en trois dimensions. (Il y a un concept de canal?, Et c'est en fait un tenseur à 4 dimensions)
J'ai utilisé le code de here comme exemple.
L'image MNIST que j'utilise est de 28 $ x 28 $.
model = chainer.FunctionSet(conv1=F.Convolution2D(1, 20, 5),
conv2=F.Convolution2D(20, 50, 5),
l1=F.Linear(800, 500),
l2=F.Linear(500, 10))
def forward(x_data, y_data, train=True):
x, t = chainer.Variable(x_data), chainer.Variable(y_data)
h = F.max_pooling_2d(F.relu(model.conv1(x)), 2)
h = F.max_pooling_2d(F.relu(model.conv2(h)), 2)
h = F.dropout(F.relu(model.l1(h)), train=train)
y = model.l2(h)
if train:
return F.softmax_cross_entropy(y, t)
else:
return F.accuracy(y, t)
En regardant la référence de F.Convolution2D,
Le premier argument est in_channels, le deuxième argument est out_channels et le troisième argument est ksize (taille du filtre). Il semble que in_channels est réglé sur 3 avec RVB, mais j'essaie avec 1, et out_channels est le nombre de canaux de sortie, mais peut-être que 20 types d'images sont créés avec différents filtres? Je le comprends sans permission. Puisque ksize vaut 5, cela signifie que le filtre est un filtre de 5 $ x 5 $.
(Corrigé le 18 juillet 2016 à partir d'ici)
~~ Dans le processus de convolution, si la taille du filtre est $ F $ et la taille de l'image est $ S × S $, la taille de l'image après le filtrage sera $ S_f × S_f $ si aucun remplissage n'est inclus. Selon article ~~
S_f = S - 2 × [F/2]
Cela devient ~~. $ [] $ Est tronqué après la virgule décimale. ~~
** Apparemment, cela semble différent quand je l'essaye, ou plutôt il a été écrit dans le document de Chainer. ** **
S_f = S - F + 1
Ça va. C'est la même chose que la moyenne mobile, n'est-ce pas? La formule précédente fonctionne bien pour les tailles de filtre impaires, mais pas pour les paires.
De plus, dans le processus de mise en commun, le traitement de périphérie diffère selon que le regroupement Max est utilisé ou le regroupement moyen est utilisé. Comme j'ai essayé, la mise en commun moyenne ne peut pas calculer s'il y a un reste après avoir divisé la taille cible par la taille de la mise en commun, mais la mise en commun Max le fait. Par conséquent, vous devez faire attention à ce domaine.
(Correction 2016/7/18 jusqu'à présent)
En d'autres termes, dans cet exemple,
Dans le premier pli
S_{f1} = 28 - 2 × [5/2] = 24
Ainsi, puisque la mise en pool Max est effectuée dans la fonction avant, la taille après la mise en commun est fixée à $ S_ {p1} x S_ {p1} $.
S_{p1} = 24 / 2 = 12
Donc, dans le deuxième pliage
S_{f2} = 12 - 2 × [5/2] = 8
Ainsi, dans la fonction avant, la mise en commun Max est effectuée, donc la taille après la mise en commun est $ S_ {p2} × S_ {p2} $.
S_{p2} = 8 / 2 = 4
Ce sera.
En d'autres termes, la dimension de la quantité de caractéristiques qui devient l'entrée finale est que le nombre de sorties est de 50, donc
M = 50 × 4 × 4 = 800
Et la première couche
l1=F.Linear(800, 500)
Correspond au premier argument de. (Chainer semble vous dire la bonne réponse si vous faites une erreur)
Eh bien, après avoir défini le modèle, je lance x_data à la fonction forward, mais il y a toujours un problème, et lors de la Convolution, je dois lancer un tenseur 4D à partir de la référence suivante. (Voir x dans les paramètres)
$ n $ est la taille du lot (taille de l'échantillon), $ c_I $ est le nombre de canaux, et $ h $ et $ w $ sont les tailles verticale et horizontale de l'image.
En regardant l'exemple de code ci-dessus, il est converti en un tenseur à 4 dimensions à l'aide de remodeler, comme illustré ci-dessous.
X_train = X_train.reshape((len(X_train), 1, 28, 28))
Cette fois, je voulais remodeler à partir de l'état de type Variable, et quand je l'ai recherché, la même chose a été définie comme une fonction Chainer.
Utilisez ceci.
Recommended Posts