Convolutional Neural Networks (CNN), die häufig zur Bilderkennung usw. verwendet werden. In letzter Zeit wird es auch im Bereich der Verarbeitung natürlicher Sprache verwendet [Kim, EMNLP2014]. Dieses Mal habe ich mit CNN mit Chainer ein einfaches Netzwerk aufgebaut und es auf die Aufgabe der Dokumentklassifizierung angewendet.
--Quell Code diesmal implementiert - ichiroex@github
--Installation von Chainer, Scikit-Learn, Gensim
Dieses Mal wird das Eingabedokument mit word2vec vektorisiert und das vektorisierte Dokument wird gefaltet. Die Vektorisierung von Dokumenten erfolgt mit "def load_data (fname)", definiert in "uitl.py".
Als Bild eine Eingabewortzeichenfolge (Dokument) $ x_1 $, $ x_2 $, $ x_3 $, ...., $ x_n $ für jedes Wort $ x_i $ Konvertiert in einen festdimensionalen $ N $ -Vektor und erstellt nebeneinander einen zweidimensionalen Dokumentvektor.
[Beispiel]
Da die Satzlänge für jedes Dokument unterschiedlich ist, wird ein Auffüllen durchgeführt, um der maximalen Satzlänge $ maxlen $ im Eingabedokument zu entsprechen. Das heißt, die Dimension des erzeugten zweidimensionalen Dokumentvektors ist $ N * maxlen $.
Übrigens beträgt in dem diesmal von Google veröffentlichten word2vec-Modell die Dimension jedes Wortvektors 300.
util.py
def load_data(fname):
#Laden Sie das trainierte word2vec-Modell
model = word2vec.Word2Vec.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
target = [] #Etikette
source = [] #Dokumentvektor
#Erstellen Sie eine Dokumentliste
document_list = []
for l in open(fname, 'r').readlines():
sample = l.strip().split(' ', 1)
label = sample[0]
target.append(label) #Etikette
document_list.append(sample[1].split()) #Wortliste für jedes Dokument
max_len = 0
rev_document_list = [] #Dokumentenliste nach unbekannter Textverarbeitung
for doc in document_list:
rev_doc = []
for word in doc:
try:
word_vec = np.array(model[word]) #Bei unbekannten Wörtern,KeyError tritt auf
rev_doc.append(word)
except KeyError:
rev_doc.append('<unk>') #Unbekanntes Wort
rev_document_list.append(rev_doc)
#Finden Sie die maximale Länge eines Dokuments(Zum Polstern)
if len(rev_doc) > max_len:
max_len = len(rev_doc)
#Passen Sie die Dokumentlänge durch Auffüllen an
rev_document_list = padding(rev_document_list, max_len)
width = 0 #Anzahl der Dimensionen jedes Wortes
#Vektorisierung von Dokumentmerkmalen
for doc in rev_document_list:
doc_vec = []
for word in doc:
try:
vec = model[word.decode('utf-8')]
except KeyError:
vec = model.seeded_vector(word)
doc_vec.extend(vec)
width = len(vec)
source.append(doc_vec)
dataset = {}
dataset['target'] = np.array(target)
dataset['source'] = np.array(source)
return dataset, max_len, width
Dieses Mal habe ich ein Modell mit einer Struktur aus Faltungsschicht -> Poolschicht -> vollständig verbundener Schicht definiert. Ich habe auch einen Ausfall auf dem Weg.
net.py
class SimpleCNN(Chain):
def __init__(self, input_channel, output_channel, filter_height, filter_width, mid_units, n_units, n_label):
super(SimpleCNN, self).__init__(
conv1 = L.Convolution2D(input_channel, output_channel, (filter_height, filter_width)),
l1 = L.Linear(mid_units, n_units),
l2 = L.Linear(n_units, n_label),
)
#Wird vom Klassifikator aufgerufen
def __call__(self, x):
h1 = F.max_pooling_2d(F.relu(self.conv1(x)), 3)
h2 = F.dropout(F.relu(self.l1(h1)))
y = self.l2(h2)
return y
Beim Lernen werden die richtige Antwortrate und der richtige Verlust für jede Epoche von Trainingsdaten und Testdaten berechnet und angezeigt. Der Code ist fast der gleiche wie bei Dokumentklassifizierung mithilfe eines vorwärtsgerichteten neuronalen Netzwerks.
Im gefalteten Zustand beträgt die Filtergröße 3 x 300 (die Anzahl der Dimensionen jedes Wortvektors).
train_cnn.py
# Prepare dataset
dataset, height, width = util.load_data(args.data)
print 'height:', height
print 'width:', width
dataset['source'] = dataset['source'].astype(np.float32) #Funktionswert
dataset['target'] = dataset['target'].astype(np.int32) #Etikette
x_train, x_test, y_train, y_test = train_test_split(dataset['source'], dataset['target'], test_size=0.15)
N_test = y_test.size # test data size
N = len(x_train) # train data size
in_units = x_train.shape[1] #Anzahl der Einheiten in der Eingabeebene(Anzahl der Vokabeln)
# (nsample, channel, height, width)In einen 4-dimensionalen Tensor umgewandelt
input_channel = 1
x_train = x_train.reshape(len(x_train), input_channel, height, width)
x_test = x_test.reshape(len(x_test), input_channel, height, width)
#Anzahl der versteckten Ebeneneinheiten
n_units = args.nunits
n_label = 2
filter_height = 3
output_channel = 50
#Modelldefinition
model = L.Classifier( SimpleCNN(input_channel, output_channel, filter_height, width, 950, n_units, n_label))
#Gibt an, ob eine GPU verwendet werden soll
if args.gpu > 0:
cuda.check_cuda_available()
cuda.get_device(args.gpu).use()
model.to_gpu()
xp = np if args.gpu <= 0 else cuda.cupy #args.gpu <= 0: use cpu, otherwise: use gpu
batchsize = args.batchsize
n_epoch = args.epoch
# Setup optimizer
optimizer = optimizers.AdaGrad()
optimizer.setup(model)
# Learning loop
for epoch in six.moves.range(1, n_epoch + 1):
print 'epoch', epoch, '/', n_epoch
# training)
perm = np.random.permutation(N) #Holen Sie sich eine zufällige Liste von Ganzzahlspalten
sum_train_loss = 0.0
sum_train_accuracy = 0.0
for i in six.moves.range(0, N, batchsize):
#x mit perm_train, y_Wählen Sie einen Datensatz aus dem Zug(Die Zieldaten sind jedes Mal anders)
x = chainer.Variable(xp.asarray(x_train[perm[i:i + batchsize]])) #source
t = chainer.Variable(xp.asarray(y_train[perm[i:i + batchsize]])) #target
optimizer.update(model, x, t)
sum_train_loss += float(model.loss.data) * len(t.data) #Zur durchschnittlichen Fehlerberechnung
sum_train_accuracy += float(model.accuracy.data ) * len(t.data) #Zur Berechnung der durchschnittlichen Genauigkeitsrate
print('train mean loss={}, accuracy={}'.format(sum_train_loss / N, sum_train_accuracy / N)) #Durchschnittlicher Fehler
# evaluation
sum_test_loss = 0.0
sum_test_accuracy = 0.0
for i in six.moves.range(0, N_test, batchsize):
# all test data
x = chainer.Variable(xp.asarray(x_test[i:i + batchsize]))
t = chainer.Variable(xp.asarray(y_test[i:i + batchsize]))
loss = model(x, t)
sum_test_loss += float(loss.data) * len(t.data)
sum_test_accuracy += float(model.accuracy.data) * len(t.data)
print(' test mean loss={}, accuracy={}'.format(
sum_test_loss / N_test, sum_test_accuracy / N_test)) #Durchschnittlicher Fehler
if epoch > 10:
optimizer.lr *= 0.97
print 'learning rate: ', optimizer.lr
sys.stdout.flush()
Die endgültige richtige Antwortrate war "Genauigkeit = 0,775624996424". Bei Klassifizierung nach einem vorwärtsgerichteten neuronalen Netzwerk betrug "Genauigkeit = 0,716875001788", sodass sich die Genauigkeitsrate erheblich verbesserte. (Im Fall eines neuronalen Feed-Forward-Netzes wurde word2vec nicht verwendet, und der Dokumentvektor wurde unter Verwendung eines heißen Wortvektors erstellt, sodass die experimentellen Bedingungen unterschiedlich sind.)
height: 59
width: 300
epoch 1 / 100
train mean loss=0.68654858897, accuracy=0.584814038988
test mean loss=0.673290403187, accuracy=0.674374999106
epoch 2 / 100
train mean loss=0.653146019086, accuracy=0.678733030628
test mean loss=0.626838338375, accuracy=0.695624998212
epoch 3 / 100
train mean loss=0.604344114544, accuracy=0.717580840894
test mean loss=0.582373640686, accuracy=0.713124997914
...
epoch 98 / 100
train mean loss=0.399981137426, accuracy=0.826288489978
test mean loss=0.460177404433, accuracy=0.775625003874
learning rate: 6.85350312961e-05
epoch 99 / 100
train mean loss=0.400466494895, accuracy=0.822536144887
test mean loss=0.464013618231, accuracy=0.773749999702
learning rate: 6.64789803572e-05
epoch 100 / 100
train mean loss=0.399539747416, accuracy=0.824081227461
test mean loss=0.466326575726, accuracy=0.775624996424
learning rate: 6.44846109465e-05
save the model
save the optimizer
Ich habe versucht, Dokumente (positive / negative Klassifizierung) über ein Faltungsnetzwerk zu klassifizieren. Es war ein einfaches Modell, aber es scheint eine gewisse Genauigkeit zu haben.
Als nächstes habe ich auch das Modell von Yoon Kim mit chainer implementiert Ich werde einen Artikel posten.
References
Recommended Posts