Beim Deep Learning scheint es üblich zu sein, die Trainingsdaten des Mini-Batch für jede Epoche zufällig zu mischen, daher habe ich den Effekt überprüft.
Überprüfen Sie den Unterschied zwischen festen Mini-Batch-Trainingsdaten und zufälligen Mini-Batch-Trainingsdaten für jede Epoche. Das Training ist die gleiche Sündenfunktion wie in Ich habe versucht, die Sündenfunktion mit Chainer zu lernen.
[training data]
Die Trainingsdaten des Mini-Batch werden zwischen fest und zufällig umgeschaltet. Der feste Code entspricht der beim Testen häufig verwendeten Technik.
Fest oder zufällig
perm = np.random.permutation(N)
sum_loss = 0
for i in range(0, N, batchsize):
if order == "fixed": #Die Reihenfolge des Lernens ist festgelegt
x_batch = x_train[i:i + batchsize]
y_batch = y_train[i:i + batchsize]
elif order == "random": #Zufällige Reihenfolge des Lernens
x_batch = x_train[perm[i:i + batchsize]]
y_batch = y_train[perm[i:i + batchsize]]
Alle Parameter sind wie im Beispiel geeignet.
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):
x = np.linspace(0, 2 * np.pi, N)
y = np.sin(x)
return x, y
#neurales Netzwerk
class MyChain(Chain):
def __init__(self, n_units=10):
super(MyChain, self).__init__(
l1=L.Linear(1, n_units),
l2=L.Linear(n_units, n_units),
l3=L.Linear(n_units, 1))
def __call__(self, x_data, y_data):
x = Variable(x_data.astype(np.float32).reshape(len(x_data),1)) #In variables Objekt konvertieren
y = Variable(y_data.astype(np.float32).reshape(len(y_data),1)) #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),1))).data
# main
if __name__ == "__main__":
#Trainingsdaten
N = 1000
x_train, y_train = get_dataset(N)
#Lernparameter
batchsize = 10
n_epoch = 500
n_units = 100
#Lernschleife
fixed_losses =[]
random_losses =[]
print "start..."
for order in ["fixed", "random"]:
#Modellieren
model = MyChain(n_units)
optimizer = optimizers.Adam()
optimizer.setup(model)
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):
if order == "fixed": #Die Reihenfolge des Lernens ist festgelegt
x_batch = x_train[i:i + batchsize]
y_batch = y_train[i:i + batchsize]
elif order == "random": #Zufällige Reihenfolge des Lernens
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
if order == "fixed":
fixed_losses.append(average_loss)
elif order == "random":
random_losses.append(average_loss)
#Lernprozess ausgeben
if epoch % 10 == 0:
print "({}) epoch: {}/{} loss: {}".format(order, epoch, n_epoch, average_loss)
interval = int(time.time() - start_time)
print "Ausführungszeit({}): {}sec".format(order, interval)
print "end"
#Fehlergrafik
plt.plot(fixed_losses, label = "fixed_loss")
plt.plot(random_losses, label = "random_loss")
plt.yscale('log')
plt.legend()
plt.grid(True)
plt.title("loss")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.show()
Es gab einen etwa 10-fachen Unterschied im Fehler zwischen fester Zeit und zufälliger Zeit. Es ist besser, es nach dem vorherigen Ruf zufällig zu machen.
Wir haben auch den Fall bestätigt, in dem die gesamten Trainingsdaten zufällig gemischt wurden. Wenn die gesamten Trainingsdaten nach dem Zufallsprinzip gemischt wurden, war das Ergebnis mit dem nach dem Zufallsprinzip vergleichbaren Ergebnis vergleichbar. Vielmehr ist die Variation für jede Epoche besser, wenn sie festgelegt ist.
Zufällige gesamte Daten
def get_dataset(N):
x = 2 * np.pi * np.random.random(N)
y = np.sin(x)
return x, y
Beim Training der Sin-Funktion ist der Fehler etwa zehnmal besser als wenn die Trainingsdaten des Mini-Batches nicht für jede Epoche zufällig gemischt werden. Die Randomisierung der gesamten Trainingsdaten ergab jedoch in beiden Fällen gute Ergebnisse.
Es kann auf bestimmte Bedingungen wie die Sündenfunktion beschränkt sein, aber es lohnt sich auch, eine Methode auszuprobieren, bei der die gesamten Daten zufällig gemischt und die Trainingsdaten des Mini-Batches festgelegt werden.
Neuronales Netzwerk beginnend mit Chainer
Grundlagen und Praxis der Implementierung von Deep Learning
Recommended Posts