chainerのサンプルコードを理解する。
pc.atsuhiro-me.net
このサイトをコピペしたら動かしたら動いたのだが、何をしているのかを調べていきたいと思います
import json, sys, glob, datetime, math import numpy as np import matplotlib.pyplot as plt import chainer from chainer import computational_graph as c from chainer import cuda import chainer.functions as F from chainer import optimizers class RegressionFNN: def __init__(self, n_units=64, batchsize=100): self.n_units = n_units self.batchsize = batchsize self.plotcount=0 def load(self, train_x, train_y): if len(train_x)!=len(train_y): raise ValueError self.N = len(train_y) self.I = 1 self.x_train = np.array(train_x, np.float32).reshape(len(train_x),1) self.y_train = np.array(train_y, np.float32).reshape(len(train_y),) # self.model = chainer.FunctionSet(l1=F.Linear(self.I, self.n_units), l2=F.Linear(self.n_units, self.n_units), l3=F.Linear(self.n_units, self.n_units), l4=F.Linear(self.n_units, 1)) # self.optimizer = optimizers.Adam() self.optimizer.setup(self.model.collect_parameters()) def forward(self, x_data, y_data, train=True): x = chainer.Variable(x_data) t = chainer.Variable(y_data) h1 = F.relu(self.model.l1(x)) h2 = F.relu(self.model.l2(h1)) h3 = F.relu(self.model.l3(h2)) y = F.reshape(self.model.l4(h3), (len(y_data), )) return F.mean_squared_error(y, t), y def calc(self, n_epoch): for epoch in range(n_epoch): perm = np.random.permutation(self.N) sum_loss = 0 # for i in range(0, self.N, self.batchsize): x_batch = self.x_train[perm[i:i + self.batchsize]] y_batch = self.y_train[perm[i:i + self.batchsize]] # self.optimizer.zero_grads() loss, y = self.forward(x_batch, y_batch) loss.backward() self.optimizer.update() # sum_loss += float(loss.data) * len(y_batch) # print('epoch = {}, train mean loss={}\r'.format(epoch, sum_loss / self.N), end="") def getY(self, test_x, test_y): if len(test_x)!=len(test_y): raise ValueError x_test = np.array(test_x, np.float32).reshape(len(test_x),1) y_test = np.array(test_y, np.float32).reshape(len(test_y),) loss, y = self.forward(x_test, y_test, train=False) # with open("output/{}.csv".format(self.plotcount), "w") as f: f.write("\n".join(["{},{}".format(ux,uy) for ux,uy in zip(y.data, y_test)])) # plt.clf() plt.plot(x_test, y_test, color="b", label="original") plt.plot(x_test, y.data, color="g", label="RegFNN") plt.legend(loc = 'lower left') plt.ylim(-1.2,1.2) plt.grid(True) plt.savefig("output/{}.png".format(self.plotcount)) self.plotcount+=1 def f(d): return [math.sin(u) for u in d] if __name__=="__main__": rf = RegressionFNN(n_units=64, batchsize=314) d = [u*0.02 for u in range(314)] rf.load(d,f(d)) rf.calc(1000) # epoch rf.getY(d,f(d)) print("\ndone.")
ここの部分を見る。
self.x_train = np.array(train_x, np.float32).reshape(len(train_x),1) self.y_train = np.array(train_y, np.float32).reshape(len(train_y),)
NumPy 配列の基礎 — 機械学習の Python との出会い
ここを参考にした。
arrayは配列を作れる。pythonの普通の配列と違うけど、そこは割愛する。
array(配列もしくはタプル, 型)
でざっくり言うと行列が作れる。たとえば
array([[1,2,3], [2,4,6]], float32)
とすると
[[1.0, 2.0, 3.0], [2.0, 4.0, 6.0]]
という具合らしい。
二重にネストしている点に注意する。
また第二引数はfloat32とかint64とかcomplex128(複素数)とかが入る。
配列の次元数や大きさの操作 — 機械学習の Python との出会い
reshapeは配列を望んだ形に変える。
reshape([1,2,3,2,4,6], (2, 3))
だと
[[1, 2, 3], [2, 4, 6]]
となる。1×6の行列を2×3にした。積が一緒でないとエラーが出る。
また-1をしていすると、うまいぐあいに調節してくれる。
(2, -1)と書いた場合2×3行列にしてくれる。
では
np.array(train_x, np.float32).reshape(len(train_x),1)
はなにをしているのかというと、train_xの長さ×1、つまり縦ベクトルに変換していることになる。(らしい)
numpyの1d-arrayを2d-arrayに変換 - keisukeのブログ
np.array(train_y, np.float32).reshape(len(train_y),)
は、横のまま?わからぬ。
Linear(変換前の行列の次元, 変換後の行列の次元)
> Linearは全ての入力と出力がつながっているようなニューラルネットワークを表します。 Linearはニューラルネットワークの文脈では総結合層,数学の用語では線形変換,アフィン変換とよびます。 たとえば,次の例では5個のユニットから,2個のユニットへの変換を表します。
ただし、これはlinks.Linearの場合なので違うかも。