[PYTHON] [Classification de texte] J'ai essayé d'utiliser le mécanisme d'attention pour les réseaux de neurones convolutifs.

introduction

Les réseaux de neurones convolutifs (CNN) sont également utilisés pour le traitement d'image et le traitement du langage naturel, mais pourquoi ne pas le combiner avec un mécanisme d'attention? Alors j'ai essayé.

Mécanisme d'attention

En termes simples, c'est une fonctionnalité qui vous permet de vous concentrer davantage sur les parties importantes de votre saisie (ici la phrase).

Elle est belle et a un bon style, mais elle a la pire personnalité.

Par exemple, lorsque vous voulez décider de la polarité d'évaluation (positive ou négative) de cette phrase, les êtres humains la jugent négative en regardant la section suivante contenant le pire ''. De même, le mécanisme Attention peut mettre davantage l'accent sur la partie pire '' que sur beauté '', `` (style) bien ''.

Il a été initialement publié en traduction automatique. Traduction automatique neuronale par l'apprentissage conjoint de l'alignement et de la traduction [Bahdanau et al., ICLR2015] Pour ceux qui veulent en savoir plus, l'article ici est facile à comprendre.

Mécanisme d'attention dans CNN

Le mécanisme Attention a été utilisé dans diverses tâches de traitement du langage naturel depuis son annonce dans la traduction automatique. Cependant, la plupart d'entre eux sont des méthodes RNN qui appliquent LSTM et GRU. Donc, cette fois, j'ai essayé d'utiliser le mécanisme Attention pour CNN dans la tâche de classification de la polarité d'évaluation. L'évaluation de la classification de la polarité consiste à prédire si une phrase d'entrée a une signification positive ou négative lorsqu'elle est donnée, comme dans l'exemple ci-dessus.

Modèle de réseau

Il est basé sur Convolutional Neural Networks for Sentence Classification [Kim, EMNLP2014]. スクリーンショット 2016-12-20 13.20.27(2).jpg

Calcul de l'attention

Introduction d'un mécanisme d'attention à RNN utilisant GRU pour la classification des documents [Hierarchical Attention Networks for Document Classification] (https://www.cs.cmu.edu/~diyiy/docs/naacl16.pdf) [Yang et al., NAACL2016] Je l'ai mentionné. Carte des caractéristiques $ \ boldsymbol {c} \ in \ mathcal {R} ^ {l-k + 1} $

\boldsymbol{c} = [c_1, c_2,\cdots,c_{l-k+1}]

$ l $ est la longueur de la phrase et $ k $ est la taille de la fenêtre. Calcule l'importance dans cette carte de caractéristiques $ \ boldsymbol {c} $. Cette partie est le mécanisme Attention.

\begin{align}
p & = \sum_{i} a_i \odot c_i \\
a_i & = \frac{\exp(W^{(C2)} \tanh(W^{(C1)} c_i))} {\sum_{j} \exp(W^{(C2)} \tanh(W^{(C1)} c_j))}
\end{align}

$ \ Odot $ est le produit d'éléments. $ W ^ {(C1)} \ in \ mathcal {R} ^ {{d} \ times 1} $, $ W ^ {(C2)} \ in \ mathcal {R} ^ {1 \ times {d}} $ D $ dans $ est un hyper paramètre. Quel est ce nom? .. $ a_i $ est calculé pour avoir des nombres réels de 0 à 1, et plus $ a_i $ est proche de 1, plus le $ c_i $ correspondant est important. Un résultat de mise en commun $ p $ est généré par une carte d'entités. À partir de maintenant, c'est le même que le modèle Kim CNN présenté ci-dessus. Combinez plusieurs $ p $, compressez dimensionnellement le vecteur résultant $ v $ et classifiez-le avec un classificateur softmax.

v = p^1\oplus p^2\oplus \cdots p^m

$ m $ est le nombre de cartes de caractéristiques. Ici, il est réglé à 100 comme Kim.

J'ai l'impression d'avoir essayé d'utiliser Attention au lieu de pooling maximum dans la couche de pooling de CNN. Cela ressemble à ceci sur la figure.

スクリーンショット 2017-02-03 15.07.49.jpg

Lors de l'utilisation de Attention dans RNN, il calcule l'importance du vecteur de calque caché, C'est un formulaire qui calcule l'importance du scalaire obtenu par pliage (avez-vous des informations ngram?), Donc si cela fonctionnera ou non. .. ..

Les données

Code (partie réseau)

cnn_attention.py


class CNN_attention(Chain):
    def __init__(self, vocab_size, embedding_size, input_channel, output_channel_1, output_channel_2, output_channel_3, k1size, k2size, k3size, pooling_units, atten_size=20, output_size=args.classtype, train=True):
        super(CNN_attention, self).__init__(
            w2e = L.EmbedID(vocab_size, embedding_size),
            conv1 = L.Convolution2D(input_channel, output_channel_1, (k1size, embedding_size)),
            conv2 = L.Convolution2D(input_channel, output_channel_2, (k2size, embedding_size)),
            conv3 = L.Convolution2D(input_channel, output_channel_3, (k3size, embedding_size)),

            l1 = L.Linear(pooling_units, output_size),
            #Attention
            a1 = L.Linear(1, atten_size),
            a2 = L.Linear(atten_size, 1),
        )
        self.output_size = output_size
        self.train = train
        self.embedding_size = embedding_size
        self.ignore_label = 0
        self.w2e.W.data[self.ignore_label] = 0
        self.w2e.W.data[1] = 0  #Non-caractère
        self.input_channel = input_channel

    def initialize_embeddings(self, word2id):
        #w_vector = word2vec.Word2Vec.load_word2vec_format('./vector/glove.840B.300d.txt', binary=False)  # GloVe
        w_vector = word2vec.Word2Vec.load_word2vec_format('./vector/GoogleNews-vectors-negative300.bin', binary=True)  # word2vec
        for word, id in sorted(word2id.items(), key=lambda x:x[1])[1:]:
            if word in w_vector:
                self.w2e.W.data[id] = w_vector[word]
            else:
                self.w2e.W.data[id] = np.reshape(np.random.uniform(-0.25,0.25,self.embedding_size),(self.embedding_size,))
    
    def __call__(self, x):
        h_list = list()
        ox = copy.copy(x)
        if args.gpu != -1:
            ox.to_gpu()
        
        x = xp.array(x.data)
        x = F.tanh(self.w2e(x))
        b, max_len, w = x.shape  # batch_size, max_len, embedding_size
        x = F.reshape(x, (b, self.input_channel, max_len, w))

        c1 = self.conv1(x)
        b, outputC, fixed_len, _ = c1.shape
        tf = self.set_tfs(ox, b, outputC, fixed_len)  # true&flase
        h1 = self.attention_pooling(F.relu(c1), b, outputC, fixed_len, tf)
        h1 = F.reshape(h1, (b, outputC))
        h_list.append(h1)

        c2 = self.conv2(x)
        b, outputC, fixed_len, _ = c2.shape
        tf = self.set_tfs(ox, b, outputC, fixed_len)  # true&flase
        h2 = self.attention_pooling(F.relu(c2), b, outputC, fixed_len, tf)
        h2 = F.reshape(h2, (b, outputC))
        h_list.append(h2)

        c3 = self.conv3(x)
        b, outputC, fixed_len, _ = c3.shape
        tf = self.set_tfs(ox, b, outputC, fixed_len)  # true&flase
        h3 = self.attention_pooling(F.relu(c3), b, outputC, fixed_len, tf)
        h3 = F.reshape(h3, (b, outputC))
        h_list.append(h3)

        h4 = F.concat(h_list)
        y = self.l1(F.dropout(h4, train=self.train))
        return y

    def set_tfs(self, x, b, outputC, fixed_len):
        TF = Variable(x[:,:fixed_len].data != 0, volatile='auto')
        TF = F.reshape(TF, (b, 1, fixed_len, 1))
        TF = F.broadcast_to(TF, (b, outputC, fixed_len, 1))
        return TF

    def attention_pooling(self, c, b, outputC, fixed_len, tf):
        reshaped_c = F.reshape(c, (b*outputC*fixed_len, 1))
        scala = self.a2(F.tanh(self.a1(reshaped_c)))
        reshaped_scala = F.reshape(scala, (b, outputC, fixed_len, 1)) 
        reshaped_scala = F.where(tf, reshaped_scala, Variable(-10*xp.ones((b, outputC, fixed_len, 1)).astype(xp.float32), volatile='auto'))  
        rereshaped_scala = F.reshape(reshaped_scala, (b*outputC, fixed_len))  # reshape for F.softmax
        softmax_scala = F.softmax(rereshaped_scala)
        atten = F.reshape(softmax_scala, (b*outputC*fixed_len, 1))
        a_h = F.scale(reshaped_c, atten, axis=0)
        reshaped_a_h = F.reshape(a_h, (b, outputC, fixed_len, 1))
        p = F.sum(reshaped_a_h, axis=2)
        return p

Contenu de l'expérience

Nous avons utilisé SST pour comparer le taux de précision de la classification avec la mise en commun maximale. Nous avons expérimenté deux tâches: SST-5, qui classe les cinq valeurs de très négatif, négatif, neutre, positif et très positif, et SST-2, qui classe le positif et le négatif sans neutre.

Résultat expérimental

method SST-2 SST-5
max 86.3 (0.27) 46.5 (1.13)
attention 86.0 (0.20) 47.2 (0.37)

La valeur est la valeur moyenne essayée 5 fois et la valeur entre parenthèses est l'écart type. Il faut faire attention pour la classification à 5 valeurs, mais le résultat est que la valeur 2 ne change pas beaucoup. À propos, la valeur maximale (SST-5) sur 5 était de 48,2% pour la mise en commun maximale et de 47,7% pour Attention, ce qui est mieux pour la mise en commun maximale. C'est juste facile à secouer. .. ..

Considération

Si vous examinez de plus près comment se trouve Attention dans la carte des caractéristiques, Il s'est avéré que l'un d'entre eux était fortement accentué par environ 0,9, et les autres étaient presque 0, ce qui était similaire à la mise en commun maximale. Cependant, contrairement à la mise en commun maximale, la valeur de l'ensemble de la carte des caractéristiques est prise en considération, je me demande donc s'il est difficile de faire une erreur. .. ..

en conclusion

Intuitivement, j'ai senti que Attention, qui examine l'importance globale, est meilleur que le pooling max, qui n'utilise que la valeur maximale. Ce n'est pas mal car la précision de la classification à 5 valeurs est supérieure à celle de la classification à 2 valeurs. .. Je pense que cela dépend de la tâche, alors j'aimerais également essayer d'autres tâches.

L'article ici présente également la classification de texte à l'aide de CNN d'une manière facile à comprendre.

Recommended Posts

[Classification de texte] J'ai essayé d'utiliser le mécanisme d'attention pour les réseaux de neurones convolutifs.
[Classification de texte] J'ai essayé d'implémenter des réseaux de neurones convolutifs pour la classification des phrases avec Chainer
[Classification des phrases] J'ai essayé différentes méthodes de mise en commun des réseaux de neurones convolutifs
vprof - J'ai essayé d'utiliser le profileur pour Python
Notes diverses sur l'utilisation de python pour les projets
[Pour les débutants] J'ai essayé d'utiliser l'API Tensorflow Object Detection
J'ai essayé d'utiliser l'API checkio
J'ai essayé d'utiliser Kwant, un module python pour le calcul du transport quantique
J'ai essayé d'utiliser Azure Speech to Text.
J'ai essayé tensorflow pour la première fois
J'ai essayé d'utiliser l'API BigQuery Storage
J'ai recherché dans la bibliothèque l'utilisation de l'API Gracenote
J'ai essayé d'utiliser PyCaret à la vitesse la plus rapide
J'ai essayé d'utiliser l'API Google Cloud Vision
J'ai essayé la programmation python pour la première fois.
J'ai essayé d'utiliser le module Datetime de Python
J'ai essayé Mind Meld pour la première fois
J'ai couru le tutoriel TensorFlow avec des commentaires (classification du texte des critiques de films)
J'ai essayé de comprendre attentivement la fonction d'apprentissage dans le réseau de neurones sans utiliser la bibliothèque d'apprentissage automatique (première moitié)
J'ai essayé d'utiliser Firebase pour le serveur de cache de Django
J'ai essayé d'utiliser le filtre d'image d'OpenCV
J'ai essayé d'utiliser la bibliothèque de programmation fonctionnelle toolz
J'ai essayé d'extraire le texte du fichier image en utilisant Tesseract du moteur OCR
J'ai essayé Python sur Mac pour la première fois.
J'ai essayé python pour la première fois avec heroku
[Linux] J'ai essayé d'utiliser le logiciel de statistiques génétiques PLINK
J'ai essayé de regrouper les données ECG en utilisant la méthode K-Shape
J'ai essayé d'approcher la fonction sin en utilisant le chainer
AI Gaming Je l'ai essayé pour la première fois
J'ai essayé la méthode la plus simple de classification de documents multi-étiquettes
J'ai essayé d'identifier la langue en utilisant CNN + Melspectogram
J'ai essayé de compléter le graphe de connaissances en utilisant OpenKE
J'ai essayé de compresser l'image en utilisant l'apprentissage automatique
J'ai essayé d'utiliser argparse
J'ai essayé d'utiliser anytree
J'ai essayé d'utiliser aiomysql
J'ai essayé d'utiliser Summpy
J'ai essayé d'utiliser coturn
J'ai essayé d'utiliser "Anvil".
J'ai essayé d'utiliser Hubot
J'ai essayé d'utiliser ESPCN
J'ai essayé d'utiliser PyCaret
J'ai essayé d'utiliser cron
J'ai essayé d'utiliser ngrok
J'ai essayé d'utiliser face_recognition
J'ai essayé d'utiliser Jupyter
J'ai essayé d'utiliser doctest
J'ai essayé d'utiliser du folium
J'ai essayé d'utiliser jinja2
J'ai essayé d'utiliser du folium
J'ai essayé d'utiliser la fenêtre de temps
J'ai essayé d'utiliser la méthode Seaborn fréquemment utilisée avec le moins d'arguments possible [pour les débutants]
[Pour ceux qui veulent utiliser TPU] J'ai essayé d'utiliser l'API de détection d'objets Tensorflow 2
J'ai essayé de porter le code écrit pour TensorFlow sur Theano
Classification de texte à l'aide de la convolution (CNN) et du regroupement de pyramides spatiales (SPP-net)
J'ai essayé d'utiliser la bibliothèque Python de Ruby avec PyCall