[PYTHON] Bestätigt den Unterschied im Vorhandensein oder Fehlen einer zufälligen Verarbeitung während des Mini-Batch-Lernens mit Chainer

Einführung

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.

Umgebung

Inhalt des Studiums

Ü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]

Implementierung

Fest oder zufällig

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]]

Lernparameter

Alle Parameter sind wie im Beispiel geeignet.

Ganzer Code

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()

Ausführungsergebnis

Error

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.

sin_diff_order.png

Wenn Sie die gesamten Daten mischen

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

sin_diff_order2.png

Zusammenfassung

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.

Referenz

Neuronales Netzwerk beginnend mit Chainer

Grundlagen und Praxis der Implementierung von Deep Learning

Recommended Posts

Bestätigt den Unterschied im Vorhandensein oder Fehlen einer zufälligen Verarbeitung während des Mini-Batch-Lernens mit Chainer
Vorhersage des Vorhandenseins oder Nichtvorhandenseins von Untreue durch maschinelles Lernen
Ich habe versucht, das Vorhandensein oder Nichtvorhandensein von Schnee durch maschinelles Lernen vorherzusagen.
rsync Das Verhalten ändert sich abhängig vom Vorhandensein oder Fehlen des Schrägstrichs der Kopierquelle
Erhalten Sie eine Liste der Ergebnisse der Parallelverarbeitung in Python mit Starmap
Wie sich die Referenz des Python-Arrays ändert, hängt vom Vorhandensein oder Fehlen von Indizes ab
Die Geschichte des tiefen Lernens mit TPU
Zeigen Sie das Ergebnis der Geometrieverarbeitung in Python an
Informationen zum Verhalten der Warteschlange während der Parallelverarbeitung