2017年3月14日火曜日

Chainerのソースを解析。Linear クラス

全結合層は Linear クラス

Chainer では全結合層を Linear クラスで組み立てます。
(chainer/links/connection/linear.py)

全結合とは、隣接レイヤーのユニット同士が下図のようにすべてつながる形態のことです。

全結合を構成する要素

全結合を構成する要素として

  • 重み
  • バイアス
  • 活性化関数

があります。この中で、Linear クラスが関わるのは重みとバイアスです。
活性化関数については関与しません。

Linear のインスタンスはレイヤーに相当

Linear の 1 インスタンスが 1 レイヤーに相当します。そして、レイヤー内の各ユニットが持つパラメータ(重み、バイアス)は Linear インスタンスの属性として管理されます。

補足
ユニットに相当するクラスは存在しません。したがって、Linear インスタンスが直接、重みとバイアスを保持します。

重み、バイアスの生成は Chainer まかせ

たとえば、図のような 3 ユニットのレイヤーがあるとします。

このレイヤーに必要な重みは 3 × 2 桁、バイアスは 3 桁の配列ですが、

Linear 生成時に Chainer がデフォルトで生成、管理してくれます。
必要な処理はサイズを指定するだけで、上記の例であれば、入力を 2、出力を 3 と指定します。

呼び出される Linear の__init__はこう定義されてます。

インスタンスのイメージ

生成される Linear インスタンスは 「重み」 と 「バイアス」 を Variable で保持します。

W が重み、b がバイアスです。

Variable インスタンスには data と grad があり

  • data にはパラメータ (重み、バイアスそのもの)
  • grad には逆伝播で求める勾配

がセットされます。

data、grad はともに同サイズの配列で、イメージとしては図のようになります。

重み、バイアスを指定する場合

重み、バイアスの初期値を指定したければ、引数 initialW、initial_bias で渡します。

順伝播、逆伝播のロジックはどこに?

Linear クラスの役割は重みとバイアスを保持することであり、計算のロジックは持っていません。では、ロジックはどこにあるかというと、別クラス LinearFunction(functions/connection /linear.py)に定義されており、forward メソッド、backward メソッドがそれぞれ順伝播、逆伝播に相当します。

forward メソッド

forward は入力 x を受け取り、下図の計算で出力 y を求めます。

backward メソッド

  • 重みとバイアスの勾配を計算し
  • 下位層へのデータ引き渡し

を行います。> くわしくは、こちらで説明

ソースを確認

foward の呼び出し方

自分で foward を呼び出す必要はありません。Linear インスタンスに学習データを渡すと、__call__メソッド経由で forward が自動で呼ばれます。

backward の呼び出し方

順伝播が終わると、その出力が Variable で返ってきます。Variable にも backward メソッドが存在するのですが、そのメソッドを呼ぶと逆伝播が始まり、LinearFunction の backward が呼ばれる仕組みになっています。> くわしくは、こちらで説明

図にすると

Function は抽象クラス、LinearFunction はその具象クラスです。

オプティマイザ

backward は勾配を計算してくれますが、その計算した値を重みとバイアスに反映することまではやってくれません。では、誰がやるのかというと、オプティマイザです。> こちらで説明

Linear インスタンスができるまで

見てもあまり役にたたないとは思いますが。

0 件のコメント:

コメントを投稿