Letztes Mal ist die grundlegende Verwendung von Chainer, die Implementierung von MLP (Multilayer Perceptron) und die Anzahl der Knoten der vollständig verbundenen Schicht aus der Faltungsschicht von CNN. Ich habe die dafür notwendige Berechnungsformel eingeführt.
Dieses Mal werde ich die tatsächlichen Twitter-Daten lesen und ein CNN erstellen.
Die Erklärung des Faltungsnetzwerks war [hier] leicht zu verstehen (http://tkengo.github.io/blog/2016/03/11/understanding-convolutional-neural-networks-for-nlp/).
Ein Filter wird auf die zweidimensionalen Bilddaten angewendet, um die Merkmale zu komprimieren. Danach wird ein Pooling durchgeführt, um die Feature-Menge weiter zu extrahieren. Wahrscheinlich gibt es nicht einen Filtertyp, aber für die Anzahl der Blätter, die Sie ausgeben möchten, werden unterschiedliche Filter angewendet.
Dieser Artikel unter Bezugnahme auf [http://qiita.com/hogefugabar/items/93fcb2bc27d7b268cbe6) Ich werde darüber nachdenken, es nachzuahmen.
Der Umriss des Prozesses ist wie folgt.
Die Definition und das Lernen von CNN verwenden die folgende in diesem Artikel beschriebene Methode.
Diese Abbildung zeigt den Faltungs- und Pooling-Prozess für einen einzelnen Satz, wobei $ d $ die Dimension des Wortvektors und $ s $ die Anzahl der Wörter im Satz in der großen Matrix ganz links ist. Und die Filtergröße ist keine symmetrische Matrix, sondern eine asymmetrische Matrix mit $ d × m $ Dimensionen.
Ich habe es jedoch selbst nach dem Lesen der Zeitung nicht verstanden, aber $ s $ ist für jeden Satz anders. Wenn ich mich also gefragt habe, wie das geht, dieser Artikel / items / 93fcb2bc27d7b268cbe6) verwendet die maximale Anzahl von Wörtern für jeden Satz, der in allen Tweets vorkommt. Imitieren Sie dies also.
Holen Sie sich die Tweet-Daten (https://raw.githubusercontent.com/satwantrana/CharSCNN/master/tweets_clean.txt). In den Daten ist die erste Spalte das Flag von [0,1] und die zweite Spalte ist der Tweet in Englisch.
Word Embed
Ich möchte den Satz in einem zweidimensionalen Bildformat halten, daher werde ich ihn in eine verteilte Darstellung ändern. Dieses Mal funktionierte die mit Chainer gelieferte Embed-ID nicht, daher verwende ich Word2Vec aus dem Gensim-Paket.
Weisen Sie Word zunächst eine ID aus den Textdaten zu.
#! -*- coding:utf-8 -*-
def read(inp_file,num_sent=None):
f_in = open(inp_file, 'r')
lines = f_in.readlines()
words_map = {}
word_cnt = 0
k_wrd = 5 #Word-Kontextfenster
y = []
x_wrd = []
if num_sent is None:
num_sent = len(lines)
max_sen_len = 0
else:
max_sen_len, num_sent = 0, num_sent
words_vocab_mat = []
token_list = []
for line in lines[:num_sent]:
words = line[:-1].split()
tokens = words[1:]
y.append(int(float(words[0])))
max_sen_len = max(max_sen_len,len(tokens))
for token in tokens:
if token not in words_map:
words_map[token] = word_cnt
token_list.append(token)
word_cnt += 1
words_vocab_mat.append(tokens)
cnt = 0
for line in lines[:num_sent]:
words = line[:-1].split()
cnt += 1
tokens = words[1:]
word_mat = [-1] * (max_sen_len+k_wrd-1)
for i in xrange(len(tokens)):
word_mat[(k_wrd/2)+i] = words_map[tokens[i]]
x_wrd.append(word_mat)
max_sen_len += k_wrd-1
# num_sent:Anzahl der Dokumente
# word_cnt:Anzahl der Worttypen
# max_sen_len:Maximale Länge des Dokuments
# x_wrd:Anzahl der Zeilen in der ID-Spalte des Eingabeworts:Anzahl der Sätze(num_sent)Anzahl der Spalten:Maximale Länge des Dokuments(max_sen_len)
# k_wrd: window size
# words_map : key = word,value = id
# y: 1 or 0 (i.e., positive or negative)
# words_vocab_mat :Zerlegter Satz, Anzahl der Zeilen ist Anzahl der Sätze, Anzahl der Spalten ist variabel und Anzahl der Wörter
# token_list :Token-Liste, Index entspricht ID
data = (num_sent, word_cnt, max_sen_len, k_wrd, x_wrd, y,words_map,words_vocab_mat,token_list)
return data
(num_sent, word_cnt, max_sen_len, k_wrd, x_wrd, y,words_map,sentences,token_list) = load.read("data/tweets_clean.txt",10000)
x_wrd ist eine Matrix aus der Anzahl der Sätze x der maximalen Dokumentlänge, und jedes Element ist die ID des angezeigten Wortes. Bereiten Sie words_map, token_list und words_vocab_mat so vor, wie Sie sie später benötigen.
Verwenden Sie als Nächstes Word2Vec, um eine Vektordarstellung für jedes Wort zu erhalten, und erstellen Sie dann eine "Satzbildmatrix" (willkürlich angehängt).
"""Erstellen Sie mit Word2Vec einen Wortvektorraum"""
word_dimension = 200
from gensim.models import Word2Vec
model_w2v = Word2Vec(sentences,seed=123,size=word_dimension,min_count=0,window=5)
sentence_image_matrix = np.zeros((len(sentences),1,word_dimension,max_sen_len)) #Initialisierung der Satzbildmatrix für die Faltung
"""x_Generieren Sie einen Vektor für wrd"""
for i in range(0,len(x_wrd)):
tmp_id_list = x_wrd[i,:]
for j in range(0,len(tmp_id_list)):
"""Biegen Sie für eine Linie"""
id = tmp_id_list[j]
if id == -1:
"""Keine Information"""
sentence_image_matrix[i,0,:,j] = [0.] * word_dimension #0 Vektor einfügen
else:
target_word = token_list[id]
sentence_image_matrix[i,0,:,j] = model_w2v[target_word]
Satz_Bildmatrix ist definiert als ein 4-dimensionaler Tensor mit der Größe (Anzahl der Sätze, 1, Vektordimension = 200, maximale Satzlänge).
Wie ich zum ersten Mal erfahren habe, kann sklearns train_test_split auch für 4-dimensionale Tensoren verwendet werden. Wahrscheinlich, weil ich nur die erste Dimension betrachte.
"""Teilen Sie in Trainingsdaten und Testdaten"""
sentence_image_matrix = np.array(sentence_image_matrix,dtype=np.float32)
N = len(sentence_image_matrix)
t_n = 0.33
x_train,x_test,y_train,y_test = train_test_split(sentence_image_matrix,y,test_size=t_n,random_state=123)
Das Problem ist die Definition von CNN. In diesem Artikel verwenden wir einen asymmetrischen Filter, und das Pooling ist ebenfalls asymmetrisch, daher müssen wir dies berücksichtigen.
Dann sieht es so aus.
class CNNFiltRow(ChainerClassifier):
"""
Ein Muster, das alle Zeilenrichtungen von CNN in Spaltenrichtung als Filter verschiebt
"""
def _setup_network(self, **params):
self.input_dim = params["input_dim"] #Spaltenweise Abmessungen eines einzelnen Bildes
self.in_channels = params["in_channels"] #input channels : default = 1
self.out_channels = params["out_channels"] #out_channels :Irgendein
self.row_dim = params["row_dim"] #Zeilenrichtungsdimension eines Bildes=Es wird die Anzahl der Filterzeilen
self.filt_clm = params["filt_clm"] #Anzahl der Filterspalten
self.pooling_row = params["pooling_row"] if params.has_key("pooling_row") else 1 #Anzahl der Poollinien: default = 1
self.pooling_clm = params["pooling_clm"] if params.has_key("pooling_clm") else int(self.input_dim - 2 * math.floor(self.filt_clm/2.)) #Anzahl der Pooling-Spalten: default = math.floor((self.input_dim - 2 * math.floor(self.filt_clm/2.))
self.batch_size = params["batch_size"] if params.has_key("batch_size") else 100
self.hidden_dim = params["hidden_dim"]
self.n_classes = params["n_classes"]
self.conv1_out_dim = math.floor((self.input_dim - 2 * math.floor(self.filt_clm/2.))/self.pooling_clm)
network = FunctionSet(
conv1 = F.Convolution2D(self.in_channels,self.out_channels,(self.row_dim,self.filt_clm)), #Filter asymmetrisch gemacht
l1=F.Linear(self.conv1_out_dim*self.out_channels, self.hidden_dim),
l2=F.Linear(self.hidden_dim, self.hidden_dim),
l3=F.Linear(self.hidden_dim, self.n_classes),
)
return network
def forward(self, x, train=True):
h = F.max_pooling_2d(F.relu(self.network.conv1(x)), (self.pooling_row,self.pooling_clm))
h1 = F.dropout(F.relu(self.network.l1(h)),train=train)
h2 = F.dropout(F.relu(self.network.l2(h1)),train=train)
y = self.network.l3(h2)
return y
def output_func(self, h):
return F.softmax(h)
def loss_func(self, y, t):
return F.softmax_cross_entropy(y, t)
def fit(self, x_data, y_data):
batchsize = self.batch_size
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 fit_test(self, x_data, y_data,x_test,y_test):
batchsize = self.batch_size
N = len(y_data)
Nt = len(y_test)
train_ac = []
test_ac = []
for loop in range(self.n_iter):
perm = np.random.permutation(N)
permt = np.random.permutation(Nt)
sum_accuracy = 0
sum_loss = 0
sum_accuracy_t = 0
"""Lernphase"""
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)
"""Testphase"""
for i in six.moves.range(0,Nt,batchsize):
x_batch = x_test[permt[i:i + batchsize]]
y_batch = y_test[permt[i:i + batchsize]]
x = Variable(x_batch)
y = Variable(y_batch)
yp = self.forward(x,False)
sum_accuracy_t += 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={} , test mean accuracy={}'.format(loop, sum_loss / N,sum_accuracy / N,sum_accuracy_t / Nt))
train_ac.append(sum_accuracy / N)
test_ac.append(sum_accuracy_t / Nt)
return self,train_ac,test_ac
Weitere Informationen zum Chainer Classifier finden Sie in Vorheriger Artikel.
Ich wollte auch die Genauigkeit der Testdaten sehen, also habe ich die Methode fit_test hinzugefügt.
"""CNN-Filterzeile lernen"""
n_iter = 200
report = 5
params = {"input_dim":max_sen_len,"in_channels":1,"out_channels":20,"row_dim":word_dimension,"filt_clm":3,"batch_size":100,"hidden_dim":300,"n_classes":2}
cnn = CNNFiltRow(n_iter=n_iter,report=report,**params)
cnn,train_ac,test_ac = cnn.fit_test(x_train,y_train,x_test,y_test)
Unten sehen Sie eine grafische Darstellung der Genauigkeit während des Trainings und der Genauigkeit der Testdaten. Es scheint, dass das Überlernen bei etwa 100 beginnt. Dennoch ist der Eindruck, dass die Generalisierungsleistung hoch ist.
Wenn Sie Testdaten in das endgültige Modell einfügen und jeden Index ausgeben, sieht dies wie folgt aus.
[CNN]P AUC: 0.80 Pres: 0.66 Recl: 0.89 Fscr: 0.76
Der F-Wert betrug 0,76 und die AUC 0,8, was ziemlich gut war.
Machen Sie dasselbe mit Random Forest und MLP (Multilayer Perceptron) als Benchmark. Da die Eingabedaten in diesem Fall nicht zweidimensional sind, werden sie wie MNIST eindimensional korrigiert.
Infolgedessen sind verschiedene Indikatoren für ähnliche Testdaten wie folgt.
[RF ]P AUC: 0.71 Pres: 0.65 Recl: 0.60 Fscr: 0.62
[MLP]P AUC: 0.71 Pres: 0.64 Recl: 0.69 Fscr: 0.67
[CNN]P AUC: 0.80 Pres: 0.66 Recl: 0.89 Fscr: 0.76
Dieser überwältigende Leistungsunterschied von CNN ...
Recommended Posts