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