[PYTHON] Untersuchung des wiederkehrenden neuronalen Netzes (RNN) durch Chainer ~ Überprüfung der Genauigkeit von Zufallszahlen in Excel und R ~

Überblick

Ich möchte das Recurrent Neural Network (RNN) studieren, das ich mir nicht leisten konnte. Grundsätzlich handelt es sich um eine Form der Vorhersage mithilfe der rekursiven Verarbeitung mit LSTM. Einige Dinge stehen jedoch noch kurz vor dem Kopieren. Daher verstehe ich sie nicht vollständig. Bitte weisen Sie auf Fehler usw. hin. Ich möchte, dass.

Referenziertes Ziel

Ein Beispiel für die Implementierung von RNN + LSTM in Chainer habe ich auf Chainers Beispiel verwiesen. Da es jedoch so ist, passt es nicht in das Framework, das ich bisher erstellt habe, also habe ich einige Verarbeitungen durchgeführt. Die Erklärung des obigen Codes wurde in hier detailliert beschrieben. Ich habe auch ein grobes Verständnis von RNN und LSTM in dem kürzlich erschienenen Buch.

Problemstellung

Es ist nicht interessant, das Sample so zu verschieben, wie es ist. Stellen wir also das Problem ein.

Wie in der Praxis gesagt wurde, beträgt die Periode der Zufallszahlen, die mit der Rand () - Funktion von Excel erstellt wurden, $ 2 ^ {24} $, und es ist bekannt, dass die Periode kürzer ist als bei anderen Zufallszahlen. Wenn Sie in Monte Carlo Excel-Zufallszahlen verwenden, sind die Ergebnisse daher verzerrt. (Nun, es kann gut sein, wenn die Anzahl der Proben gering ist)

Andererseits ist die Zufallszahl von R eine Zufallszahl mit einer sehr langen Periode ($ 2 ^ {19937} $), die von einem Algorithmus namens [Mersenne Twister](https://ja.wikipedia.org/wiki/Mersenne Twister) erstellt wurde. Ich bin.

Mit anderen Worten, wenn es Periodizität gibt, kann es möglich sein, den nächsten Zufallszahlenwert vorherzusagen, indem sequentielles Lernen unter Verwendung von RNN durchgeführt wird. Das ist das Bewusstsein für das Problem.

Ich bin kein Experte für Zufallszahlen, daher bin ich mir nicht sicher, ob die Bewertungsmethode korrekt ist.

Vorbereitung der Daten

Zunächst werden Excel-Zufallszahlen mit der Rand-Funktion berechnet.

=ROUNDDOWN(RAND()*10,0)

Bereiten Sie 1001 Stück vor. Dann erhalten Sie 10 ganzzahlige Werte von 0-9.

Als nächstes erzeugt die Zufallszahl von R eine einheitliche Zufallszahl wie folgt.

x <- floor(runif(1001)*10);

(Der Wert 1001 ist ein Extra, um die Antwortdaten zum nächsten Wert zu machen.)

Die erklärende Variable ist der aktuelle Zufallswert (0-9) und die Lehrerdaten sind der nächste Zufallswert (0-9).

RNN-Implementierung

RNN wurde unter Verwendung von Chainer wie folgt implementiert. Da es sich um einen sequentiellen Prozess handelt, setzen wir die Chargengröße absichtlich auf 1 und verarbeiten sie von Anfang an in der richtigen Reihenfolge.

Erstens ist die Basisklasse wie folgt.

DL_chainer.py


# -*- coding: utf-8 -*-
from chainer import FunctionSet, Variable, optimizers,serializers
from chainer import functions as F
from chainer import links as L
from sklearn import base
from sklearn.cross_validation import train_test_split
from abc import ABCMeta, abstractmethod
import numpy as np
import six
import math
import cPickle as pickle

class BaseChainerEstimator(base.BaseEstimator):
    __metaclass__= ABCMeta  # python 2.x
    def __init__(self, optimizer=optimizers.MomentumSGD(lr=0.01), n_iter=10000, eps=1e-5, report=100,
                 **params):
        self.report = report
        self.n_iter = n_iter
        self.batch_size = params["batch_size"] if params.has_key("batch_size") else 100
        self.network = self._setup_network(**params)
        self.decay = 1.
        self.optimizer = optimizer
        self.optimizer.setup(self.network.collect_parameters())
        self.eps = eps
        np.random.seed(123)

    @abstractmethod
    def _setup_network(self, **params):
        return FunctionSet(l1=F.Linear(1, 1))

    @abstractmethod
    def forward(self, x,train=True,state=None):
        y = self.network.l1(x)
        return y

    @abstractmethod
    def loss_func(self, y, t):
        return F.mean_squared_error(y, t)

    @abstractmethod
    def output_func(self, h):
        return F.identity(h)
	
	@abstractmethod
    def fit(self, x_data, y_data):
        batchsize = self.batch_size
        N = len(y_data)
        for loop in range(self.n_iter):
            perm = np.random.permutation(N)
            sum_accuracy = 0
            sum_loss = 0
            for i in six.moves.range(0, N, batchsize):
                x_batch = x_data[perm[i:i + batchsize]]
                y_batch = y_data[perm[i:i + batchsize]]
                x = Variable(x_batch)
                y = Variable(y_batch)
                self.optimizer.zero_grads()
                yp = self.forward(x)
                loss = self.loss_func(yp,y)
                loss.backward()
                self.optimizer.update()
                sum_loss += loss.data * len(y_batch)
                sum_accuracy += F.accuracy(yp,y).data * len(y_batch)
            if self.report > 0 and (loop + 1) % self.report == 0:
                print('loop={:d}, train mean loss={:.6f} , train mean accuracy={:.6f}'.format(loop + 1, sum_loss / N,sum_accuracy / N))
            self.optimizer.lr *= self.decay

        return self

    def predict(self, x_data):
        x = Variable(x_data,volatile=True)
        y = self.forward(x,train=False)
        return self.output_func(y).data

    def predict_proba(self, x_data):
        x = Variable(x_data,volatile=True)
        y = self.forward(x,train=False)
        return self.output_func(y).data

    def save_model(self,name):
        with open(name,"wb") as o:
            pickle.dump(self,o)

class ChainerClassifier(BaseChainerEstimator, base.ClassifierMixin):
    def predict(self, x_data):
        return BaseChainerEstimator.predict(self, x_data).argmax(1) 

    def predict_proba(self,x_data):
        return BaseChainerEstimator.predict_proba(self, x_data)

Die folgende RNN-Implementierung sieht folgendermaßen aus:

DL_chainer.py


class RNNTS(ChainerClassifier):
    """
    Recurrent Neurarl Network with LSTM by 1 step
    """
    def _setup_network(self, **params):

        self.input_dim = params["input_dim"]
        self.hidden_dim = params["hidden_dim"]
        self.n_classes = params["n_classes"]
        self.optsize = params["optsize"] if params.has_key("optsize") else 30
        self.batch_size = 1 
        self.dropout_ratio = params["dropout_ratio"] if params.has_key("dropout_ratio") else 0.5

        network = FunctionSet(
            l0 = L.Linear(self.input_dim, self.hidden_dim),
            l1_x = L.Linear(self.hidden_dim, 4*self.hidden_dim),
            l1_h = L.Linear(self.hidden_dim, 4*self.hidden_dim),
            l2_h = L.Linear(self.hidden_dim, 4*self.hidden_dim),
            l2_x = L.Linear(self.hidden_dim, 4*self.hidden_dim),
            l3   = L.Linear(self.hidden_dim, self.n_classes),
        )
        return network

    def forward(self, x, train=True,state=None):
        if state is None:
            state = self.make_initial_state(train)
        h0 = self.network.l0(x)
        h1_in = self.network.l1_x(F.dropout(h0, ratio=self.dropout_ratio, train=train)) + self.network.l1_h(state['h1'])
        c1, h1 = F.lstm(state['c1'], h1_in)
        h2_in = self.network.l2_x(F.dropout(h1, ratio=self.dropout_ratio, train=train)) + self.network.l2_h(state['h2'])
        c2, h2 = F.lstm(state['c2'], h2_in)
        y = self.network.l3(F.dropout(h2, ratio=self.dropout_ratio, train=train))
        state = {'c1': c1, 'h1': h1, 'c2': c2, 'h2': h2}

        return y,state

    def make_initial_state(self,train=True):
        return {name: Variable(np.zeros((self.batch_size, self.hidden_dim), dtype=np.float32),
                volatile=not train)
                for name in ('c1', 'h1', 'c2', 'h2')}

    def fit(self, x_data, y_data):
        batchsize = self.batch_size
        N = len(y_data)
        for loop in range(self.n_iter):
            sum_accuracy = Variable(np.zeros((), dtype=np.float32))
            sum_loss = Variable(np.zeros((), dtype=np.float32))
            state = self.make_initial_state(train=True) #Erzeugung des Ausgangszustands
            for i in six.moves.range(0, N, batchsize):
                x_batch = x_data[i:i + batchsize]
                y_batch = y_data[i:i + batchsize]

                x = Variable(x_batch,volatile=False)
                y = Variable(y_batch,volatile=False)
                yp,state = self.forward(x,train=True,state=state)
                loss = self.loss_func(yp,y)
                accuracy = F.accuracy(yp,y)
                sum_loss += loss
                sum_accuracy += accuracy

                if (i + 1) % self.optsize == 0:
                    self.optimizer.zero_grads()
                    sum_loss.backward()
                    sum_loss.unchain_backward()
                    self.optimizer.clip_grads(5)
                    self.optimizer.update()

            if self.report > 0 and (loop + 1) % self.report == 0:
                print('loop={:d}, train mean loss={:.6f} , train mean accuracy={:.6f}'.format(loop + 1, sum_loss.data / N,sum_accuracy.data / N))
            self.optimizer.lr *= self.decay

        return self

    def output_func(self, h):
        return F.softmax(h)

    def loss_func(self, y, t):
        return F.softmax_cross_entropy(y, t)

    def predict_proba(self, x_data):
        N = len(x_data)
        state = self.make_initial_state(train=False)
        y_list = []
        for i in six.moves.range(0, N, self.batch_size):
            x = Variable(x_data[i:i+self.batch_size],volatile=True)
            y,state = self.forward(x,train=False,state=state)
            y_list.append(y.data[0]) #batch size =Unterstützt nur 1
        y = Variable(np.array(y_list),volatile=False)
        return self.output_func(y).data

    def predict(self, x_data):
        return self.predict_proba(x_data).argmax(1)

Der Code, auf den fast verwiesen wird, wird übernommen.

Wenn Sie bisher schreiben, können Sie einfach den Hauptprozess schreiben,

main.py


# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
from DL_chainer import *
import warnings
from sklearn.metrics import classification_report
warnings.filterwarnings("ignore")

I_FILE_EXCEL="excelrand.csv"
I_FILE_R="RRandom.csv"

def main(file=""):
    """
Lernen und prognostizieren Sie Excel-Zufallszahlen mit RNN
    :return:
    """
    df0 = pd.read_csv(file)
    N = len(df0)
    x_all = df0.iloc[:,0]
    y_all = []
    y_all.extend(x_all)
    y_all.extend([np.nan])
    y_all = y_all[1:(N+1)]

    x_all_array = np.reshape(np.array(x_all[0:(N-1)],dtype=np.float32),(len(x_all)-1,1))/10
    y_all_array = np.reshape(np.array(y_all[0:(N-1)],dtype=np.int32),(len(x_all)-1))

    train_n = 2 * N/3

    x_train = x_all_array[0:train_n]
    y_train = y_all_array[0:train_n]

    x_test = x_all_array[train_n:]
    y_test = y_all_array[train_n:]

    params = {"input_dim":1,"hidden_dim":100,"n_classes":10,"dropout_ratio":0.5,"optsize":30}
    print params
    print len(x_train),len(x_test)
    rnn = RNNTS(n_iter=200,report=1,**params)
    rnn.fit(x_train,y_train)
    pred = rnn.predict(x_train)
    print classification_report(y_train,pred)

    pred = rnn.predict(x_test)
    print classification_report(y_test,pred)

if __name__ == '__main__':
    main(I_FILE_R)
    main(I_FILE_EXCEL)

Grundsätzlich handelt es sich um ein 10-Klassen-Klassifizierungsproblem.

Auswertung der Ergebnisse

Die Auswertung der Ergebnisse ist schwierig. Es wird davon ausgegangen, dass mit Testdaten mit einer kleinen Anzahl von Proben keine korrekte Bewertung erfolgen kann.

Das RNN-Lernen läuft grundsätzlich unabhängig davon ab, welche Zufallszahlenfolge verwendet wird. Daher habe ich mich entschlossen zu sehen, wie sich die Lerngeschwindigkeit bei gleicher Anzahl von Epochen unterscheidet.

Mit anderen Worten, in derselben Epoche interpretieren diejenigen, die genauer sind, dass die Daten ein Muster enthalten und dass sie "gelernt" wurden.

Als Zufallszahl ist es besser, dass es kein Muster gibt, daher ist es natürlich besser, dass diese Lerngeschwindigkeit langsam ist.

Das Ergebnis ist unten

精度.png

Sie können sehen, dass die Lerngeschwindigkeit auf der Excel-Seite schneller ist als auf R. Mit anderen Worten, ich frage mich, ob R in Bezug auf die Qualität von Zufallszahlen besser ist. Eigentlich ist es besser, wenn das Lernen nicht voranschreitet.

Zusammenfassung

Dieses Mal habe ich für das Üben von RNN die Implementierung ausprobiert und die Zufallszahlen von Excel und R gelernt. Unabhängig davon, ob die Ergebnisbewertungsmethode korrekt ist oder nicht, wurde festgestellt, dass das Lernen auf der Excel-Seite mit dieser Bewertungsmethode schneller voranschreitet und R als Zufallszahl besser ist.

Wahrscheinlich sind unzählige Zufallszahlenfolgen erforderlich, um eine genauere Überprüfung zu ermöglichen, aber aufgrund der Leistung des Computers habe ich ihn auf diesem Niveau gehalten.

Aber wie kann ich die Berechnung mit RNN beschleunigen?

Recommended Posts

Untersuchung des wiederkehrenden neuronalen Netzes (RNN) durch Chainer ~ Überprüfung der Genauigkeit von Zufallszahlen in Excel und R ~
Erkennung handgeschriebener Zahlen durch ein mehrschichtiges neuronales Netzwerk
Rank Learning über ein neuronales Netzwerk (RankNet-Implementierung von Chainer)
Generierung von Zeitreihen durch wiederkehrende neuronale Netze (Magenta-Übersetzung, bei der künstliche Intelligenz Kunst und Musik macht)
Implementierung von "verschwommenen" neuronalen Netzen mit Chainer
[Chainer] Dokumentklassifizierung nach Faltungsnetzwerk