Es gibt bereits eine Person, die Zundokokiyoshi mithilfe von LSTM implementiert, aber ich denke, dass Sie auf dieser Ebene nur mit einem einfachen RNN lernen können sollten. Ich habe versucht, es mit Chainer zu implementieren, um RNN zu verstehen.
Gemäß 7.5 des Buches "Deep Learning (Machine Learning Professional Series)" (ISBN-13: 978-4061529021) erinnert sich RNN Sie können es für die letzten 10 Stunden tun. Sie müssen sich nur an das Muster erinnern, in dem "Zun" viermal und "Doko" einmal vorkommt, daher sollte es innerhalb dieses Bereichs liegen.
Ich dachte an eine möglichst einfache Struktur. Geben Sie zwei ein ($ x_1, x_2
Mist → x_0 = 0, x_1 = 1 \\
Doco → x_0 = 1, x_1 = 0
Die Ausgabe ist wie folgt definiert: Angenommen, es ist ein einfaches Klassifizierungsproblem.
Kiyoshi ist fehlgeschlagen → y_0 = 1, y_1 = 0 \\
Kiyoshi gründete → y_0 = 0, y_1 = 1
Die Code-Definition lautet wie folgt.
import numpy as np
import chainer
from chainer import cuda, Function, gradient_check, Variable, optimizers, serializers, utils
from chainer import Link, Chain, ChainList
import chainer.functions as F
import chainer.links as L
class RNN(chainer.Chain):
def __init__(self):
super(RNN, self).__init__(
w1 = L.Linear(2, 10),
h1 = L.Linear(10, 10),
o = L.Linear(10, 2)
)
def reset_state(self):
self.last_z = chainer.Variable(np.zeros((1,10), dtype=np.float32))
def __call__(self, x):
z = F.relu(self.w1(x) + self.h1(self.last_z))
self.last_z = z
y = F.relu(self.o(z))
return y
rnn = RNN()
rnn.reset_state()
model = L.Classifier(rnn)
optimizer = optimizers.Adam() #Benutze Adam
optimizer.setup(model)
optimizer.add_hook(chainer.optimizer.GradientClipping(10.0)) #Stellen Sie die Obergrenze des Verlaufs ein
Unter der Annahme einer Mini-Charge mit einer festen Größe von 1 ist der Anfangswert (last_z) Null. Während der in self.last_z berechnete Wert der verborgenen Ebene beibehalten wird, wird das Ergebnis an die Ausgabeebene übergeben.
Generieren Sie mäßig zufällige Seriendaten und trainieren Sie diese.
ans_zundoko = [0, 0, 0, 0, 1] #Richtige Antwortreihenfolge
src_x_ary = [0, 0, 0, 1] #Stellen Sie die Erscheinungsrate des Zufallszahlengenerierungsarrays 0 höher als 1 ein
def zd_gen(): #Generator
x_ary = [0, 0, 0, 0, 1]
y_ary = [0, 0, 0, 0, 1]
while True:
x = x_ary.pop(0)
y = y_ary.pop(0)
x = [0, 1] if x == 0 else [1, 0]
yield x, y
new_x = src_x_ary[np.random.randint(0, 4)] #0 wenn 0 bis 2,Wenn es 3 ist, ist es 1.
x_ary.append(new_x)
y_ary.append(1 if x_ary == ans_zundoko else 0) # x_ary ist[0, 0, 0, 0, 1]Nur wenn
bprop_len = 40 #BPPT-Abschaltzeit
iter = 300 * 100 * 2 #Anzahl des Lernens
loss = 0
i = 0
for xx, yy in zd_gen():
x = chainer.Variable(np.asarray([xx], dtype=np.float32))
t = chainer.Variable(np.asarray([yy], dtype=np.int32))
loss += model(x, t)
i += 1
if i % bprop_len == 0:
model.zerograds()
loss.backward()
loss.unchain_backward()
optimizer.update()
print("iter %d, loss %f, x %d, y %d" % (i, loss.data, xx[0], yy))
loss = 0
if i > iter:
break
Das Lernen ist zeitaufwändig und kann abhängig von den Anfangswerten funktionieren oder auch nicht. Es wird nicht richtig funktionieren, es sei denn, der Verlust fällt schließlich unter 0,1.
Versuchen Sie, den Optimierer in SGD oder bprop_len zu ändern, und die Ergebnisse ändern sich. Der hier eingestellte Wert verwendet den Fall, der irgendwie gut zur Hand ging.
Bewerten Sie das trainierte Modell. Sie können die Eingabespalten zufällig generieren, aber der Einfachheit halber habe ich statische Auswertungsdaten vorbereitet.
#Mist Mist Mist Mist Mist Doko Doko Mist
x_data = [[0,1], [0,1], [0,1], [0,1], [1,0], [1,0], [1,0], [0,1]]
rnn.reset_state()
for xx in x_data:
print('Dung' if xx[1] == 1 else 'Doco')
x = chainer.Variable(np.asarray([xx], dtype=np.float32))
y = model.predictor(x)
z = F.softmax(y, use_cudnn=False)
if z.data[0].argmax() == 1: #Kiyoshi wird eingerichtet, wenn der Array-Index mit dem größeren Wert 1 ist.
print('Kiyoshi')
Die Ausgabe, wenn sie gut läuft, wird als Referenz angezeigt.
iter 59520, loss 0.037670, x 1, y 0
iter 59560, loss 0.051628, x 0, y 0
iter 59600, loss 0.037519, x 0, y 0
iter 59640, loss 0.041894, x 0, y 0
iter 59680, loss 0.059143, x 0, y 0
iter 59720, loss 0.062305, x 0, y 0
iter 59760, loss 0.055293, x 0, y 0
iter 59800, loss 0.060964, x 1, y 1
iter 59840, loss 0.057446, x 1, y 0
iter 59880, loss 0.034730, x 1, y 0
iter 59920, loss 0.054435, x 0, y 0
iter 59960, loss 0.039648, x 0, y 0
iter 60000, loss 0.036578, x 0, y 0
Dung
Dung
Dung
Dung
Doco
Kiyoshi
Doco
Doco
Dung
Ich habe das Gefühl, dass ich endlich RNN verstehen kann, das ich nicht vollständig verdaut hatte. Anfangs war die Anzahl der Einheiten in der mittleren Schicht gering und die BPTT-Grenzzeit war zu kurz eingestellt, sodass sie überhaupt nicht funktionierte, aber nach verschiedenen Anpassungen begann sie schließlich zu funktionieren. Es gibt viele Beispiele für die Verwendung von LSTM- und Worteinbettungsausdrücken in der Welt, aber ich habe beschlossen, es mit einem minimierten Problem zu versuchen, und ich bin froh, dass ich es endlich erkannt habe.
Es ist jedoch ein Problem, dass es immer noch einen Teil gibt, der vom Glück abhängt.
Recommended Posts