Un débutant en apprentissage profond a essayé d'apprendre la fonction de péché avec un chainer. En tant que niveau débutant, je me suis senti un peu compris après avoir lu l'apprentissage profond, mais lorsque j'ai décidé d'écrire cet article, je me suis senti désespéré face à mon faible niveau de compréhension. L'apprentissage de la fonction sin a été fait par yuukiclass et bien d'autres, mais ce n'est pas mal.
Apprendre le sin (thêta) à partir d'angles (thêta) de 0 à 2π
[training data]
C'est la partie implémentation de l'apprentissage par mini-lots. Ce code est familier des exemples MNIST (certains changements tels que la plage). Cet apprentissage par mini-lots semble être populaire.
Extrait de l'apprentissage mini-batch
perm = np.random.permutation(N)
sum_loss = 0
for i in range(0, N, batchsize):
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()
Le nombre de données est modifié de sorte que l'angle utilisé pendant le test soit différent de celui pendant l'entraînement. L'angle est modifié en divisant 0 à 2π en 1000 pendant l'apprentissage et en divisant 0 à 2π en 900 pendant le test.
Données d'entraînement&Extrait de la confirmation des résultats
#Données d'entraînement
N = 1000
x_train, y_train = get_dataset(N)
#données de test
N_test = 900
x_test, y_test = get_dataset(N_test)
'''
réduction
'''
# test
loss = model(x_test,y_test)
test_losses.append(loss.data)
Mini taille de lot: 10
Époque (n_epoch): 500
Nombre de couches cachées: 2
Nombre d'unités de couche cachées (n_units): 100
Fonction d'activation: fonction linéaire normalisée (relu)
Abandon: Aucun (0%)
Optimisation: Adam
Fonction d'erreur de perte: fonction d'erreur quadratique moyenne (mean_squared_error)
Tous les paramètres sont appropriés.
L'ensemble
# -*- coding: utf-8 -*-
#Importer depuis une extrémité pour le moment
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
#Les données
def get_dataset(N):
x = np.linspace(0, 2 * np.pi, N)
y = np.sin(x)
return x, y
#réseau neuronal
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)) #Convertir en objet variable
y = Variable(y_data.astype(np.float32).reshape(len(y_data),1)) #Convertir en objet variable
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__":
#Données d'entraînement
N = 1000
x_train, y_train = get_dataset(N)
#données de test
N_test = 900
x_test, y_test = get_dataset(N_test)
#Paramètres d'apprentissage
batchsize = 10
n_epoch = 500
n_units = 100
#La modélisation
model = MyChain(n_units)
optimizer = optimizers.Adam()
optimizer.setup(model)
#Boucle d'apprentissage
train_losses =[]
test_losses =[]
print "start..."
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):
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
train_losses.append(average_loss)
# test
loss = model(x_test,y_test)
test_losses.append(loss.data)
#Processus d'apprentissage des extrants
if epoch % 10 == 0:
print "epoch: {}/{} train loss: {} test loss: {}".format(epoch, n_epoch, average_loss, loss.data)
#Créer un graphique des résultats d'apprentissage
if epoch in [10, 500]:
theta = np.linspace(0, 2 * np.pi, N_test)
sin = np.sin(theta)
test = model.get_predata(theta)
plt.plot(theta, sin, label = "sin")
plt.plot(theta, test, label = "test")
plt.legend()
plt.grid(True)
plt.xlim(0, 2 * np.pi)
plt.ylim(-1.2, 1.2)
plt.title("sin")
plt.xlabel("theta")
plt.ylabel("amp")
plt.savefig("fig/fig_sin_epoch{}.png ".format(epoch)) #En supposant que le dossier fig existe
plt.clf()
print "end"
interval = int(time.time() - start_time)
print "Temps d'exécution: {}sec".format(interval)
#Graphique d'erreur
plt.plot(train_losses, label = "train_loss")
plt.plot(test_losses, label = "test_loss")
plt.yscale('log')
plt.legend()
plt.grid(True)
plt.title("loss")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.savefig("fig/fig_loss.png ") #En supposant que le dossier fig existe
plt.clf()
L'erreur a tendance à diminuer à mesure que l'époque (nombre d'apprentissage) augmente. Il n'y avait pas de différence significative entre les erreurs d'apprentissage et de test. Je pense que l'erreur lors des tests est légèrement meilleure que celle lors de l'apprentissage car la méthode de calcul de l'erreur est différente.
Lorsque l'époque est de 10, il est difficile de dire que c'est une fonction péché, mais lorsque l'apprentissage progresse vers 500, elle est assez proche de la fonction péché.
epoch: 10
epoch: 500
Pour le moment, j'ai pu entraîner la fonction péché avec chainer.
Cependant, pour une raison quelconque, plus l'angle est grand, plus l'erreur est grande. Je pensais que si l'ordre des angles à apprendre était aléatoire, la variation de l'erreur pour chaque angle pourrait être supprimée, mais elle semble être différente. Ce n'est pas bien compris.
J'ai essayé d'approcher la fonction sin en utilisant chainer (re-challenge)
Chainer et apprentissage en profondeur appris par approximation de fonction
Réseau neuronal de type à propagation directe régressive avec chaînage
Recommended Posts