読者です 読者をやめる 読者になる 読者になる

俺とプログラミング

某IT企業でエンジニアをしてます。このブログではプログラミングに関わることを幅広く発信します。

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]]


深層学習 (機械学習プロフェッショナルシリーズ)

深層学習: Deep Learning

Copyright © 2016 ttlg All Rights Reserved.