Chainerチュートリアルの勉強ノート【バージョン1.4】
巷ではTensorflowが話題ですが、気にせずChainerを使います。 ChainerのAPIは綺麗で読みやすいのがいいですね。 この記事ではChainerのチュートリアルのまとめを公開します。 一部、実験も含んでいます。
import文
# -*- coding: utf-8 -*- import numpy as np from chainer import FunctionSet, Variable, optimizers import chainer.functions as F
Forward/Backward Computation
基本となる演算(順伝搬計算と逆誤差伝搬法)を行う。 Variable型に計算過程が記録されている。
# numpy arrayを5で初期化 x_data = np.array([5], dtype=np.float32) # numpy arrayをVariable型に変換 x = Variable(x_data) # Variable型で算術演算を行う y = x**2 - 2 * x + 1 print y.data # out: [ 16.] # 誤差逆伝播法(back propagation)を実行 y.backward() # xの勾配が計算される print x.grad # out: [ 8.] # 中間の勾配を保持しておくにはretain_gradにTrueを指定する(普通は必要ない) z = 2*x y = x**2 - z + 1 y.backward(retain_grad=True) print z.grad # out: [ -1.] # 多次元に拡張 x = Variable(np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32)) y = x**2 - 2*x + 1 # 多次元の場合、backwardの前に勾配を初期化する必要がある y.grad = np.ones((2, 3), dtype=np.float32) y.backward() print x.grad # out: [[ 0. 2. 4.] # [ 6. 8. 10.]]
Parameterized Function
パラメータ(Wやbなど)を持った関数のこと。Optimizerを使わない場合、勾配を自分で初期化する必要がある。
# 関数 入力: 3D --> 出力: 2D f = F.Linear(3, 2) # 関数のパラメータ(W)はランダムに初期化される print f.W # out: [[ 0.20126812 0.13777408 0.95926213] # [ 0.90332973 0.17615487 -0.75226796]] print f.b # out:[ 0. 0.] # listの要素数は3Dの必要がある(listの個数がバッチ数) x = Variable(np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32)) # 普通の関数としてつかえる y = f(x) print y.data # out: [[ 3.35460281 -1.00116456] # [ 7.24951553 -0.01951456]] # 関数パラメータの勾配を0で初期化する f.gW.fill(0) f.gb.fill(0) y.grad = np.ones((2, 2), dtype=np.float32) y.backward() print f.gW # out: [[ 5. 7. 9.] # [ 5. 7. 9.]] print f.gb # out: [ 2. 2.]
Function Set
関数のまとまりのこと。 これで、Deep Neural Netの構造を定義する。
# 4D --> 3D -- > 2D --> 2D model = FunctionSet( l1=F.Linear(4, 3), l2=F.Linear(3, 2), l3=F.Linear(2, 2) ) # 順伝搬計算(Forward Computation) x = Variable(np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=np.float32)) h1 = model.l1(x) h2 = model.l2(h1) y = model.l3(h2) print y.data # out:[[-3.48857141 2.62073851] # [-6.72572136 5.48979092]] # 勾配の初期化と計算 y.grad = np.ones((2, 2), dtype=np.float32) model.l1.gW.fill(0) model.l1.gb.fill(0) model.l2.gW.fill(0) model.l2.gb.fill(0) model.l3.gW.fill(0) model.l3.gb.fill(0) y.backward() print model.l3.gW # out: [[ 11.3967514 -11.04709435] # [ 11.3967514 -11.04709435]] print model.l3.gb # out: [ 2. 2.]
Optimizer
関数最適化や勾配の初期化などを行える。
# modelを定義 model = FunctionSet( l1=F.Linear(4, 3), l2=F.Linear(3, 2), l3=F.Linear(2, 2) ) # 確率的勾配降下法(Stochastic Gradient Descent)を使う optimizer = optimizers.SGD() # modelをセッティング optimizer.setup(model) # 先ほどの冗長な部分(0での初期化)をやってくれる optimizer.zero_grads() # 勾配は0に初期化される print model.l1.gW # out:[[ 0. 0. 0. 0.] # [ 0. 0. 0. 0.] # [ 0. 0. 0. 0.]] # 初期パラメータWはランダムに決まる print model.l1.W # out: [[-0.32616782 -0.30050409 0.465808 0.53529584] # [-0.19208315 0.03425147 -0.04532254 -1.01169217] # [ 0.7444182 0.1564717 -0.05203951 0.04011982]] # 順伝搬計算(Forward Computation) x = Variable(np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=np.float32)) h1 = model.l1(x) h2 = model.l2(h1) y = model.l3(h2) # 誤差逆伝播(Backward Computation) y.grad = np.ones((2, 2), dtype=np.float32) y.backward() # 勾配を見て関数のパラメータ(W,b)を更新 optimizer.update() # 最適化後の関数パラメータ print model.l1.W # out: [[-0.33830398 -0.31668565 0.44558105 0.51102352] # [-0.18072271 0.04939871 -0.02638848 -0.98897129] # [ 0.710751 0.11158206 -0.10815156 -0.02721464]]