[PYTHON] Analysons les émotions de Tweet en utilisant Chainer (1er)

Historique des corrections

** 2016/7/18: corrigé car une erreur s'est produite dans la formule de calcul de la taille après le filtrage. ** **

Aperçu

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.

Contenu du premier

environnement

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)

Préparation

Installation de chaînes

pip install chainer

sklearn et 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)

Décodez les échantillons CNN dans Chainer.

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,

Kobito.SCEMO4.png

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 $.

Taille de l'élément après pliage et mise en commun

(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)

Préparation avant de lancer

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)

Kobito.sKeAcV.png

$ 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.

Kobito.StweJ1.png

Utilisez ceci.

la prochaine fois

Recommended Posts

Analysons les émotions de Tweet en utilisant Chainer (1er)
Analysons les émotions de Tweet en utilisant Chainer (2ème)
Obtenez le titre de Yahoo News et analysez les sentiments
Analysons les données de l'enquête par questionnaire [4e: Analyse des émotions]
Décidons le gagnant du bingo
A propos du comportement de enable_backprop de Chainer v2
Implémentation d'un système de dialogue utilisant Chainer [seq2seq]
Tweet à l'aide de l'API Twitter en Python
[Bash] Analysons maintenant la bombe Fork
Implémentation de réseaux neuronaux "flous" avec Chainer
Examinons le mécanisme de la chinchirorine de Kaiji
Raccourcir le temps d'analyse d'Openpose à l'aide du son
Estimation de l'effet des mesures à l'aide des scores de propension
Vérifiez le type de variable que vous utilisez
[Python] Exécutons le module régulièrement en utilisant schedule
Sortie exclusive de l'application Django utilisant ngrok
Signate_ Revue du 1er Concours Limité Débutant
Essayez d'utiliser le module de collections (ChainMap) de python3
Analyse émotionnelle des données de tweet à grande échelle par NLTK
Déterminez le nombre de classes à l'aide de la formule Starges
Vérifiez l'état des données à l'aide de pandas_profiling
Gratter les données gagnantes de Numbers à l'aide de Docker
Expliquer Chat Bot annoncé à PyCon 2016 à partir de la base de code (réponse de chat à l'aide de Chainer)