J'aimerais commencer à étudier le réseau neuronal récurrent (RNN), que je ne pouvais pas me permettre. Fondamentalement, il s'agit d'une forme de prédiction utilisant un traitement récursif utilisant LSTM, mais il y a des choses qui sont encore proches de la copie, donc je ne le comprends pas complètement, alors veuillez signaler toute erreur, etc. Je te veux.
Pour un exemple d'implémentation de RNN + LSTM dans Chainer, j'ai fait référence à [Sample] de Chainer (https://github.com/yusuketomoto/chainer-char-rnn). Cependant, tel quel, il ne rentre pas dans le cadre que j'ai créé jusqu'à présent, alors j'ai fait un peu de traitement. L'explication du code ci-dessus a été détaillée dans ici. J'ai également une compréhension approximative de RNN et LSTM dans le récent livre.
Ce n'est pas intéressant de déplacer l'échantillon tel quel, alors posons le problème.
Comme cela a été dit dans la pratique, la période des nombres aléatoires créée par la fonction Rand () d'Excel est de 2 $ ^ {24} $, et on sait que la période est plus courte que les autres nombres aléatoires. Par conséquent, si vous utilisez des nombres aléatoires Excel à Monte Carlo, les résultats seront biaisés. (Eh bien, cela peut être bon si le nombre d'échantillons est petit)
D'autre part, le nombre aléatoire de R est un nombre aléatoire avec une très longue période ($ 2 ^ {19937} $) créé par un algorithme appelé [Mersenne Twister](https://ja.wikipedia.org/wiki/Mersenne Twister). Je suis.
En d'autres termes, s'il y a périodicité, il peut être possible de prédire la valeur de nombre aléatoire suivante en effectuant un apprentissage séquentiel en utilisant RNN. Telle est la conscience du problème.
Je ne suis pas un expert des nombres aléatoires, donc je ne suis pas sûr que la méthode d'évaluation soit correcte.
Tout d'abord, les nombres aléatoires Excel sont calculés à l'aide de la fonction Rand.
=ROUNDDOWN(RAND()*10,0)
Préparez 1001 pièces. Ensuite, vous obtiendrez 10 valeurs entières de 0 à 9.
Ensuite, le nombre aléatoire de R génère un nombre aléatoire uniforme comme suit.
x <- floor(runif(1001)*10);
(1001 est une valeur supplémentaire pour faire des données de réponse la valeur suivante.)
La variable explicative est la valeur aléatoire actuelle (0-9) et les données de l'enseignant sont la valeur aléatoire suivante (0-9).
RNN a été implémenté en utilisant Chainer comme suit. Puisqu'il s'agit d'un processus séquentiel, nous définissons intentionnellement la taille du lot sur 1 et traitons chacun dans l'ordre depuis le début.
Tout d'abord, la classe de base est la suivante.
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)
L'implémentation RNN suivante ressemble à ceci:
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) #Génération de l'état initial
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 =Supporte seulement 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)
Le code qui est presque référencé est adopté.
Si vous écrivez jusqu'à présent, vous pouvez simplement écrire le processus principal,
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=""):
"""
Apprenez et prédisez des nombres aléatoires Excel avec 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)
Fondamentalement, c'est un problème de classification en 10 classes.
L'évaluation des résultats est difficile. On considère qu'une évaluation correcte ne peut pas être effectuée avec des données d'essai avec un petit nombre d'échantillons.
L'apprentissage RNN se déroule essentiellement quelle que soit la séquence de nombres aléatoires utilisée. Par conséquent, j'ai décidé de voir en quoi la vitesse d'apprentissage diffère avec le même nombre d'époques.
En d'autres termes, à la même époque, ceux qui sont plus précis interprètent qu'il y a un certain modèle dans les données et qu'il a été "appris".
En tant que nombre aléatoire, il vaut mieux qu'il n'y ait pas de modèle, il est donc naturellement préférable que cette vitesse d'apprentissage soit lente.
Le résultat est ci-dessous
Vous pouvez voir que la vitesse d'apprentissage est plus rapide côté Excel que sur R. En d'autres termes, je me demande si R est meilleur en termes de qualité des nombres aléatoires. En fait, c'est mieux si l'apprentissage ne progresse pas.
Cette fois, pour la pratique de RNN, j'ai essayé l'implémentation et appris les nombres aléatoires d'Excel et de R. Indépendamment du fait que la méthode d'évaluation des résultats soit correcte ou non, il a été constaté que l'apprentissage du côté Excel progressait plus rapidement avec cette méthode d'évaluation et que R était meilleur en tant que nombre aléatoire.
Probablement, d'innombrables séquences de nombres aléatoires sont nécessaires pour vérifier plus correctement, mais en raison de la puissance de l'ordinateur, je l'ai gardé à ce niveau.
Mais comment accélérer le calcul avec RNN?
Recommended Posts