Chainerチュートリアル -v1.5向け- ViEW2015
-
Upload
ryosuke-okuta -
Category
Software
-
view
81.100 -
download
0
Transcript of Chainerチュートリアル -v1.5向け- ViEW2015
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