Bis vorher habe ich nur 1 Eingabe und 1 Ausgabe von sin like angle (theta) gelernt, aber diesmal habe ich nur 1 Eingabe und 1 Ausgabe von sin und cos gelernt. Ich möchte 2 Eingänge und 1 Ausgang lernen.
Lerne den Winkel (Theta) aus sin und cos (0-2π).
[training data]
Trainingsdaten
def get_dataset(N):
theta = np.linspace(0, 2 * np.pi, N)
sin = np.sin(theta)
cos = np.cos(theta)
x = np.c_[sin, cos]
y = theta
return x, y
Da die Anzahl der Einheiten in der Eingabeebene (in_units) und der Ausgabeebene (out_units) festgelegt ist, ist die Vielseitigkeit im Vergleich zum vorherigen Code geringfügig erhöht.
Batch-Lernen
class MyChain(Chain):
def __init__(self, in_units=1, n_units=10, out_units=1):
super(MyChain, self).__init__(
l1=L.Linear(in_units, n_units),
l2=L.Linear(n_units, n_units),
l3=L.Linear(n_units, out_units))
self.in_units = in_units
self.out_units = out_units
Alle Parameter sind angemessen.
Das ganze
# -*- coding: utf-8 -*-
#Vorerst von einem Ende importieren
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
import time
from matplotlib import pyplot as plt
#Daten
def get_dataset(N):
theta = np.linspace(0, 2 * np.pi, N)
sin = np.sin(theta)
cos = np.cos(theta)
x = np.c_[sin, cos]
y = theta
return x, y
#neurales Netzwerk
class MyChain(Chain):
def __init__(self, in_units=1, n_units=10, out_units=1):
super(MyChain, self).__init__(
l1=L.Linear(in_units, n_units),
l2=L.Linear(n_units, n_units),
l3=L.Linear(n_units, out_units))
self.in_units = in_units
self.out_units = out_units
def __call__(self, x_data, y_data):
x = Variable(x_data.astype(np.float32).reshape(len(x_data),self.in_units)) #In variables Objekt konvertieren
y = Variable(y_data.astype(np.float32).reshape(len(y_data),self.out_units)) #In variables Objekt konvertieren
return F.mean_squared_error(self.predict(x), y)
def predict(self, x):
h1 = F.relu(self.l1(x))
h2 = F.relu(self.l2(h1))
h3 = self.l3(h2)
return h3
def get_predata(self, x):
return self.predict(Variable(x.astype(np.float32).reshape(len(x),self.in_units))).data
# main
if __name__ == "__main__":
#Trainingsdaten
N = 1000
x_train, y_train = get_dataset(N)
#Testdaten
N_test = 900
x_test, y_test = get_dataset(N_test)
#Lernparameter
batchsize = 10
n_epoch = 500
in_units = 2
n_units = 100
out_units = 1
#Modellieren
model = MyChain(in_units, n_units, out_units)
optimizer = optimizers.Adam()
optimizer.setup(model)
#Lernschleife
print "start..."
train_losses =[]
test_losses =[]
start_time = time.time()
for epoch in range(1, n_epoch + 1):
# training
perm = np.random.permutation(N)
sum_loss = 0
for i in range(0, N, batchsize):
x_batch = x_train[perm[i:i + batchsize]]
y_batch = y_train[perm[i:i + batchsize]]
model.zerograds()
loss = model(x_batch,y_batch)
sum_loss += loss.data * batchsize
loss.backward()
optimizer.update()
average_loss = sum_loss / N
train_losses.append(average_loss)
# test
loss = model(x_test, y_test)
test_losses.append(loss.data)
#Lernprozess ausgeben
if epoch % 10 == 0:
print "epoch: {}/{} train loss: {} test loss: {}".format(epoch, n_epoch, average_loss, loss.data)
interval = int(time.time() - start_time)
print "Ausführungszeit(normal): {}sec".format(interval)
print "end"
#Fehlergrafik
plt.plot(train_losses, label = "train_loss")
plt.plot(test_losses, label = "test_loss")
plt.yscale('log')
plt.legend()
plt.grid(True)
plt.title("loss")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.show()
#Erstellen eines Diagramms der Lernergebnisse
sin, cos = np.hsplit(x_test ,in_units)
theta = y_test
test = model.get_predata(x_test)
plt.subplot(3, 1, 1)
plt.plot(theta, sin, "b", label = "sin")
plt.legend(loc = "upper left")
plt.grid(True)
plt.xlim(0, 2 * np.pi)
plt.ylim(-1.2, 1.2)
plt.subplot(3, 1, 2)
plt.plot(theta, cos, "g", label = "cos")
plt.legend(loc = "upper left")
plt.grid(True)
plt.xlim(0, 2 * np.pi)
plt.ylim(-1.2, 1.2)
plt.subplot(3, 1, 3)
plt.plot(theta, theta, "r", label = "theta")
plt.plot(theta, test, "c", label = "test")
plt.legend(loc = "upper left")
plt.grid(True)
plt.xlim(0, 2 * np.pi)
plt.ylim(-0.5, 7)
plt.tight_layout()
plt.show()
Wenn die Anzahl der Epochen 500 beträgt, ist der Fehler groß. Da der Grad der Fehlerabnahme gesättigt wird, ist es außerdem unwahrscheinlich, dass eine weitere Verringerung erwartet werden kann, wenn die Anzahl der Epochen nicht signifikant erhöht wird.
Da die Ausgabe linear ist, scheint der Fehler nicht so groß zu sein.
Ich bestätigte auch den Fall, in dem die Eingabe sin und cos mit dem Träger multipliziert wurden. (3 Eingänge und 1 Ausgang inklusive Träger) Dies ist das gleiche Prinzip wie der Resolver, der den Winkel des Motors erfasst.
Trainingsdaten mit Träger
def get_dataset(N):
theta = np.linspace(0, 2 * np.pi, N)
ref = np.sin(40 * theta) #Träger
sin = np.sin(theta) * ref
cos = np.cos(theta) * ref
x = np.c_[sin, cos, ref]
y = theta
return x, y
# in_Ändern Sie die Einheiten auf 3
Es kann bestätigt werden, dass der Fehler auch im Erscheinungsbild groß ist, da die Eingabe kompliziert ist. Harmonische Komponenten bleiben erhalten.
Obwohl der Fehler groß war, konnte ich den Winkel von sin und cos lernen. (2 Eingänge und 1 Ausgang) Wir konnten auch den Winkel aus der Resolver-Wellenform lernen, die mit dem Träger multipliziert wurde. Es wurde jedoch eine harmonische Komponente erzeugt. Es war keine große Sache, also dachte ich, ich könnte genauer lernen, aber ich war überrascht, dass der Fehler groß war. In Zukunft möchte ich kompliziertere Inhalte lernen, damit ich an die Zukunft denken kann ...
Recommended Posts