Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Chainerチュートリアル
- v1.5向け -
2015/12/04 ViEW 2015@パシフィコ横浜
(株)Preferred Networks
奥田 遼介
Chainer(http://chainer.org/)
3
 Chainer の使い方を紹介します
 Deep Learning の簡単な説明から実装へ
 CUDA サポートについても簡単に解説します
 学術的な詳細は既存の文献を参考にしてください
 CUDA の詳細は NVIDIA のドキュメントを参照してください
ニューラルネットの基礎と実装準備
ニューラルネット
 値が伝播していく有向グラフ
 エッジで重みをかけて、ノードに入るところで足し
込み、ノードの中で非線形変換する
 全体としては巨大で複雑な関数を表す
5
ニューラルネット=合成関数
 ベクトルに対して線形・非線形な関数をたくさん適
用する合成関数と捉えるとよい
 各ノードはベクトルを保持する変数
6
一般のニューラルネットは DAG = 計算グラフ
一般にはグラフが分岐したり合流したりする
 分岐:同じ変数を複数の場所でつかう
 合流:二つ以上の変数を受け取る関数を適用する
7
計算グラフの例
z = x ** 2 + 2 * x * y + y
8
x
y
_ ** 2
2 * _ _ * _ _ + _ z
_ + _
z x x y y
機械学習のおさらい
多くの機械学習手法は、
1. 目的関数の設計
2. 勾配の計算
3. 最小化のための反復計算
からなる
9
先ほどの計算は
ここに使う
機械学習の例:分類学習の目的関数
10
argminw ∑(x, y) l(x, y; w)
 xは入力ベクトル、yは予測ラベル
 l(x, y)は予測が正しければ小さく、間違えれば大
きくなる値(損失関数)
 上記関数を最小化するパラメータwを求めたい
機械学習の例:分類学習のアルゴリズム
 目的関数をパラメータwで微分した値(勾配)を
計算する方法を用意する
 wを勾配の方向に少しだけ動かす、を繰り返す
 実際は更新方向の取り方に工夫が他数ある
11
initialize w
until converge:
w := w - η d/dw L(x, y; w)
最急降下法
誤差逆伝播(後退型自動微分)
合成関数の微分を計算するには連鎖律 (chain rule)
をつかう
12
各関数の微分がわかれば機械的に計算できる
誤差逆伝播は、計算グラフを逆向きにたどる
計算グラフと順伝播時の各変数の値があれば計算可能
13
ニューラルネットの学習方法
1. 目的関数の設計
 計算グラフを自分で設計する
2. 勾配の計算
 誤差逆伝播で機械的に計算できる
3. 最小化のための反復計算
 勾配を使って反復更新する
14
1は設計が必要
2、3は自動化されている
Recurrent Net
 ループがあるニューラルネット
 時刻の概念があり、t=T の状態は t=T-1 の状態と t=T の入力
を使って求める
15
T
T-1
T
Recurrent Net は時間展開して考える
 時間展開すれば、DAG の計算グラフになる
 DAG の計算グラフは誤差逆伝播できる(Backprop Through
Time) 16
t=1
t=2
t=3
t=4
Chainer の使い方
Chainer はニューラルネットのフレームワーク
 機能
 ニューラルネットを順伝播を記述する
 ニューラルネットの順伝播・逆伝播を実行する
 勾配法を実行してパラメータを最適化する
 Chainer の特徴
 順伝播は単純に Python のスクリプトとして書ける
 そのスクリプトで実行した計算手順を記録されて、
逆伝播を内部で自動生成する
18
ニューラルネットワークフレームワークの構成要素
構成要素 Chainerの場合
変数 chainer.Variable
関数
(損失関数/活性化関数)
chainer.Functionを継承
パラメーター付き関数 chainer.Linkを継承
パラメーター付き関数集合 chainer.Chainを継承
最適化 chainer.Optimizer
19
 大きく分けて三要素
 変数・関数・最適化
Chainer のインストール
 環境は Linux(特に Ubuntu)がおすすめ
 インストール方法
 新しめの Python 環境を用意(CPython 2.7+, 3.4+, 3.5+)
 pip も用意
 コマンドを実行
 pip install -U cython
 pip install chainer
 chainer パッケージが import できれば完了です
 Python 環境は、Anaconda がおすすめ
 Python のバージョン管理は pyenv がおすすめ
 pyenv からコマンド一つで Anaconda もインストールできます
20
順伝播
 今まで「変数」と呼んでいたものは、Chainer で
は Variable オブジェクト
 Variable を Function に入れると、順伝播後の
Variable が返ってくる
 Variable が計算グラフを保持している
 Function は、四則演算以外に
chainer.functions に用意されている
21
順伝播とコード例
22
x = Varaible(...)
y = Variable(...)
z = x ** 2 + 2 * x * y + y
x
y
_ ** 2
2 * _ _ * _ _ + _ z
_ + _
Variable オブジェクト
 計算グラフの(データ)ノード
 NumPy または CuPy(後述)の配列を保持する
 初期化時に配列を渡す
 data 属性に保存される
 多くの Function は配列の最初の軸をミニバッチとして使
うので注意
 下の x は、20 次元ベクトルが 10 個入ったミニバッチとみなす
 現状、Chainer は多くの場所で float32 配列を要求するの
で注意
23
x = Variable(np.zeros((10, 20),
dtype=np.float32))
x.data
Function オブジェクト
 計算グラフの「演算」ノード
 chainer.functions (以降 F) にいろいろ定義され
ている
 F.relu, F.max_pooling_2d, F.lstm, ...
 Functionの呼び出し結果が、再びVariableになる
 v1.5からパラメータはLinkとして分離された(後述)
24
x = Variable(...)
y = F.relu(x) # yもVariable
Link オブジェクト
 パラメータ付きの関数
 最適化の対象となる
 save/loadができる(v1.5からsave/loadをサポート)
 chainer.links(以降L)に色々用意されている
 L.Linear, L.Convolution2D, L.EmbedID, ...
 Linkの呼び出し結果が、再びVariableになる
 v1.5からFunctionとパラメータは分離され、パラメータ
付きの関数はLinkオブジェクトになった
25
v1.5~
ChainでLinkをまとめる
 一般的にパラメータ付きの関数(Link)は複数あるので、
Chainでまとめて管理できる
 Chainを継承すると再利用しやすくなる
model = Chain(embed=L.EmbedID(10000, 100),
layer1=L.Linear(100, 100),
layer2=L.Linear(100, 10000))
x = Variable(...)
h = F.relu(model.layer1(model.embed(x)))
y = model.layer2(h)
26
v1.5~
ロス関数、勾配計算
 ロス関数もFunctionの一種
 ロス関数の出力に、Variable.backward() を呼ぶと
勾配が計算できる
loss = F.softmax_cross_entropy(y, t)
loss.backward()
27
Optimizer の設定
 勾配が計算できたら、あとは勾配法をまわす
 勾配法のアルゴリズムは Optimizer クラスの子クラス
 chainer.optimizers に定義されている
 実装されている最適化手法:SGD, MomentumSGD, AdaGrad,
RMSprop, RMSpropGraves, AdaDelta, Adam
 最適化対象をsetup メソッドに渡す
 正則化はhook関数として登録する
optimizer = optimizers.SGD()
optimizer.setup(model)
optimizer.add_hook(optimizer.WeightDecay())
28
Optimizer による最適化
 まず勾配をゼロ初期化:zerograds()
 順伝播・逆伝播を実行
 最適化ルーチンを実行:update()
 以上を何回も繰り返す
model.zerograds()
loss = ...
loss.backward()
optimizer.update()
29
Chainer を使う場合の全体の流れ
1. Linkを使ってChainを定義する
2. Optimizer に、Chain を設定する
3. forward 関数を定義する
4. データセットを読み込み、訓練用と評価用にわける
5. 訓練ループを回す
a. 勾配をゼロ初期化
b. 順伝播して、得られたロス値の backward メソッドを呼ぶ
c. Optimizerを、update
6. 適当な頻度で評価ループを回す
a. テストデータで順伝播関数を呼んで結果を記録
30
例:MNIST
# Model definition
class MnistMLP(chainer.Chain):
def __init__(self, n_in,
n_units, n_out):
super(MnistMLP, self).__init__(
l1=L.Linear(n_in, n_units),
l2=L.Linear(n_units, n_units),
l3=L.Linear(n_units, n_out))
# Forward computation
def __call__(self, x):
h1 = F.relu(self.l1(x))
h2 = F.relu(self.l2(h1))
return self.l3(h2)
# Setup
model = L.Classifier(net.MnistMLP(
784, n_units, 10))
opt = optimizers.SGD()
opt.setup(model)
# Training loop
for epoch in xrange(n_epoch):
for i in xrange(0, N, batchsize):
x = Variable(...)
t = Variable(...)
opt.update(model, x, t)
新しい Function を自分で定義する
 Function は Python で新しく作ることができる
 forward(_cpu/_gpu) と backward(_cpu/_gpu) を実装する必
要がある
 配列のタプルを受け取って、配列のタプルを返す
 Linkは内部でFunctionを呼んで作る
32
自作Functionの例
class SquaredDiff(Function):
def forward_cpu(self, inputs):
x, y = inputs
z = x – y
return z * z,
def backward_cpu(self, inputs, grad_outputs):
x, y = inputs
gz = grad_outputs
gx = 2 * (x – y) * gz
return gx, -gx
33
tupleを返す
勾配をtupleで返す
新しい Function を自分で定義する
 Function を書いたらテストしましょう
 とくに勾配チェック (gradient check) は必須
 有限差分法で forward のみから計算した勾配が、backward で計
算した勾配と一致するかを確かめる
 chainer.gradient_check.numerical_grad を使うと簡単
に書ける
 公式リポジトリの
tests/chainer_tests/function_tests にたくさん例
が書いてあります
34
CUDA サポート
 CuPy: 新しい CUDA 配列実装
 NumPy と同じようなインターフェイスで使える
 関数・メソッドのサブセットを実装
 配列のスライス、転置、reshape 等も自由にできます
 カスタムカーネルも記述できる(elementwise, reduction)
35
CuPy を使う準備
 まず CUDA が使える GPU を用意する
 CUDA 6.5 以上をインストール
 Ubuntu なら公式に deb パッケージがお薦め(aptがdriverも管理してくれる)
 パスを通す
 PATH を通すことが必要
 CuPyはnvccのパスからライブラリの場所を見つけます
 デフォルトでは /usr/local/cuda にインストールされます
 PATH=/usr/local/cuda/bin:$PATH
 Chainer をインストールしたらimport cupyで動作を確認
36
cuDNNの使い方
 cuDNN
 NNの計算を省メモリで高速におこなってくれるライブラリ
 特にConvolutionに効果がある
 cuDNNは画像系では超重要(メモリ使用量が数分の1に減る場合も)
 NVIDIAのページでユーザー登録してダウンロード
 ダウンロードできるようになるまで数日かかります
 インストーラーはありません
 展開して手動でCUDAのフォルダにコピー(おすすめ)
 lib64とinclude に対応するファイルを放り込む
 もしくはパスを通す
 CPATH、 LIBRARY_PATH、LD_LIBRARY_PATHの設定が必要
 CuDNNを導入したらChainerを再インストール
 import cupy.cudnn で動作を確認
37
CuPy の使い方
 numpy の代わりに cupy を使う(だいたい動く)
 CPU/GPU の両方で動く関数の書き方
 chainer.cuda.get_array_module() を使うと、引数に
cupy.ndarray があるかないかで numpy / cupy のどちらかを返してくれ
ます
 例えば下は NumPy と CuPy の両方で動く logsumexp の実装例(より省
メモリな実装を考えてみてください)
38
def logsumexp(x, axis=None):
xp = cuda.get_array_module(x)
x_max = x.max(axis=axis)
return x_max + xp.log(
xp.exp(x – x_max).sum(axis=axis))
公式の Examples
公式リポジトリの examples にいくつか例があります
 画像系
 mnist: MNIST を多層パーセプトロンで学習。NN界のHello World
 imagenet: ImageNet からの大規模ConvNet学習
 modelzoo: Caffe 公式モデルを読み込んで使うサンプル
 言語系
 ptb: Penn-Tree Bank から LSTM 言語モデルを学習する
 無限長の入力に対する Truncated BPTT の例にもなっています
 word2vec: word2vec の実装と PTB からの学習
 sentiment: Recursive Net を使った極性判定
39
Chainer を使う利点
 Pythonで書ける
 NumPyが書ければCuPyを使ってGPU化できる
 自作のレイヤーも前処理もPythonで書ける
 CuPyを使うことでPythonのまま簡単にGPU化
 ループや複雑な分岐があるNNも直感的に書ける
 Pythonの制御構文でNNのforward処理が書ける
 Define by Run
 デバッグが楽
 Pythonのスタックトレースを活用してのデバッグが可能
 ファンクションの中身もほとんどPythonコード
 NNのバグの原因がどの行で起きているかが分かる
40
Chainer 1.5が正しくインストールできないときは?
 v1.5 からHDF5とCythonに依存
 周辺パッケージとの兼ね合いでインストールにちょっとしたテ
クニックが必要
 ログを活用する
 pip install chainer –vvvv
 何が問題かが分かります
 Cythonをあらかじめインストール
 pip install -U cython
 メモリを食いつぶすエラーを防げます
 sudo に注意する
 環境変数が引き継がれません
 「Chainer 1.5 インストール」で検索
 対処法が出てきます 41
まとめ
 ニューラルネットを実装面から簡単におさらいしました
 Chainer の構成と使い方をざっくりお伝えしました
 本チュートリアルを参考にChainer を使っていただけれ
ば幸いです
 Chainer 自体へのフィードバックもお待ちしております
42
 ご清聴ありがとうございました
43
We are Hiring!
https://www.preferred-networks.jp/job_ja

More Related Content

Chainerチュートリアル -v1.5向け- ViEW2015