Convolutional Neural Networks (CNN) werden auch für die Bildverarbeitung und die Verarbeitung natürlicher Sprache verwendet. Warum jedoch nicht mit einem Aufmerksamkeitsmechanismus kombinieren? Also habe ich es versucht.
Einfach ausgedrückt, ist es eine Funktion, mit der Sie sich mehr auf die wichtigen Teile Ihrer Eingabe konzentrieren können (hier der Satz).
Sie ist schön und hat einen guten Stil, aber sie hat die schlechteste Persönlichkeit.
Wenn Sie beispielsweise die Bewertungspolarität (positiv oder negativ) dieses Satzes bestimmen möchten, beurteilen Menschen ihn als negativ, indem sie sich den folgenden Abschnitt ansehen, der "das Schlimmste" enthält. In ähnlicher Weise kann der Aufmerksamkeitsmechanismus den "schlimmsten" Teil mehr betonen als die "Schönheit", "(Stil) gut".
Ursprünglich in maschineller Übersetzung veröffentlicht. Neuronale maschinelle Übersetzung durch gemeinsames Lernen des Ausrichtens und Übersetzens [Bahdanau et al., ICLR2015] Für diejenigen, die mehr Details wissen möchten, ist der Artikel hier leicht zu verstehen.
Der Aufmerksamkeitsmechanismus wurde bei verschiedenen Aufgaben der Verarbeitung natürlicher Sprache verwendet, seit er in der maschinellen Übersetzung angekündigt wurde. Bei den meisten handelt es sich jedoch um RNN-Methoden, die LSTM und GRU anwenden. Dieses Mal habe ich versucht, den Aufmerksamkeitsmechanismus für CNN in der Aufgabe zur Klassifizierung der Bewertungspolarität zu verwenden. Die Klassifizierung der Bewertungspolarität ist die Aufgabe, vorherzusagen, ob ein Eingabesatz eine positive oder negative Bedeutung hat, wenn er gegeben wird, wie im obigen Beispiel.
Es basiert auf Convolutional Neural Networks for Satzklassifikation [Kim, EMNLP2014].
Einführung des Aufmerksamkeitsmechanismus für RNN unter Verwendung von GRU zur Klassifizierung von Dokumenten [Hierarchical Attention Networks for Document Classification] (https://www.cs.cmu.edu/~diyiy/docs/naacl16.pdf) [Yang et al., NAACL2016] Ich bezog mich auf. Feature-Map $ \ boldsymbol {c} \ in \ mathcal {R} ^ {l-k + 1} $
\boldsymbol{c} = [c_1, c_2,\cdots,c_{l-k+1}]
$ l $ ist die Satzlänge und $ k $ ist die Fenstergröße. Berechnet die Wichtigkeit in dieser Feature-Map $ \ boldsymbol {c} $. Dieser Teil ist der Aufmerksamkeitsmechanismus.
\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 $ ist das Produkt von Elementen. $ W ^ {(C1)} \ in \ mathcal {R} ^ {{d} \ times 1} $, $ W ^ {(C2)} \ in \ mathcal {R} ^ {1 \ times {d}} $ D $ in $ ist ein Hyperparameter. Wie ist dieser Name? .. $ a_i $ hat reelle Werte von 0 bis 1, und je näher $ a_i $ an 1 liegt, desto wichtiger ist das entsprechende $ c_i $. Ein Pooling-Ergebnis $ p $ wird von einer Feature-Map ausgegeben. Ab hier ist es dasselbe wie das oben eingeführte Kim CNN-Modell. Kombinieren Sie mehrere $ p $, komprimieren Sie den resultierenden Vektor $ v $ dimensional und klassifizieren Sie ihn mit einem Softmax-Klassifikator.
v = p^1\oplus p^2\oplus \cdots p^m
$ m $ ist die Anzahl der Feature-Maps. Hier ist es wie bei Kim auf 100 gesetzt.
Es fühlt sich so an, als hätte ich versucht, Attention anstelle von Max Pooling in der Pooling-Schicht von CNN zu verwenden. In der Abbildung sieht es so aus.
Bei Verwendung von Attention in RNN berechnen wir die Wichtigkeit des Vektors der verborgenen Schicht. Dies ist eine Form, die die Wichtigkeit des durch Falten erhaltenen Skalars berechnet (haben Sie Ngram-Informationen?). Ob es also funktioniert oder nicht. .. ..
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 #Nicht-Charakter
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
Wir haben SST verwendet, um die Genauigkeitsrate der Klassifizierung mit dem maximalen Pooling zu vergleichen. Wir haben mit zwei Aufgaben experimentiert: SST-5, das die fünf Werte sehr negativ, negativ, neutral, positiv und sehr positiv klassifiziert, und SST-2, das positiv und negativ ohne neutral klassifiziert.
method | SST-2 | SST-5 |
---|---|---|
max | 86.3 (0.27) | 46.5 (1.13) |
attention | 86.0 (0.20) | 47.2 (0.37) |
Der Wert ist der Durchschnittswert, der fünfmal versucht wurde, und der Wert in Klammern ist die Standardabweichung. Die 5-Wert-Klassifizierung sollte beachtet werden, aber das Ergebnis ist, dass sich der 2-Wert nicht so stark ändert. Übrigens betrug der Maximalwert (SST-5) von 5 mal 48,2% für maximales Pooling und 47,7% für Aufmerksamkeit, was besser für maximales Pooling ist. Es ist einfach zu schütteln. .. ..
Wenn Sie sich die Aufmerksamkeit in der Feature-Map genauer ansehen, Es stellte sich heraus, dass einer von ihnen mit etwa 0,9 stark betont wurde und die anderen fast 0 waren, was dem maximalen Pooling ähnlich war. Im Gegensatz zum maximalen Pooling wird jedoch der Wert der gesamten Feature-Map berücksichtigt, sodass ich mich frage, ob es schwierig ist, einen Fehler zu machen. .. ..
Intuitiv war ich der Meinung, dass Aufmerksamkeit, die die allgemeine Bedeutung betrachtet, besser ist als maximales Pooling, bei dem nur der maximale Wert verwendet wird. Es ist nicht schlecht, weil die Genauigkeit der 5-Wert-Klassifizierung höher ist als die der 2-Wert-Klassifizierung. .. Ich denke, es hängt von der Aufgabe ab, deshalb möchte ich auch andere Aufgaben ausprobieren.
Der Artikel hier führt auch die Textklassifizierung mit CNN auf leicht verständliche Weise ein.
Recommended Posts