1.4 モデル

一連のレイヤよりなるモデルはmodelモジュールのsequential関数で構築することができます。このメソッドはレイヤクラス名をスネークケースで記述した「レイヤ表現」を引数に取り、Modelクラスのインスタンスを返します。最終レイヤは損失関数を出力するレイヤである必要があります。各レイヤのパラメータには変数が自動で割り当てられます。

from ivory.core.model import sequential

net = [("input", 5), ("affine", 10, "relu"), ("affine", 4, "softmax_cross_entropy")]
model = sequential(net)
model.layers

[1] 2019-06-12 20:00:19 (191ms) python3 (191ms)

[<Affine('Affine.1', (5, 10)) at 0x1d5e431ec88>,
 <Relu('Relu.1', (10,)) at 0x1d5e431ed68>,
 <Affine('Affine.2', (10, 4)) at 0x1d5e431ee10>,
 <SoftmaxCrossEntropy('SoftmaxCrossEntropy.1', (4,)) at 0x1d5e431efd0>]

ここで、最初の("input", 5)が、5次元の入力を示すプレースホルダです。上記のようにModelインスタンスはlayers属性を持ち、所属するレイヤを返します。各レイヤにはクラスごとに連番で名前が付けられています。

sequential関数は、同じパターンの繰り返しを簡潔に書く方法が用意されています。

net = [
    ("input", 784),
    (3, "affine", 100, "relu"),
    ("affine", 10, "softmax_cross_entropy"),
]
model_complex = sequential(net)
model_complex.layers

[2] 2019-06-12 20:00:19 (12.0ms) python3 (203ms)

[<Affine('Affine.3', (784, 100)) at 0x1d5e4330668>,
 <Relu('Relu.2', (100,)) at 0x1d5e43307b8>,
 <Affine('Affine.4', (100, 100)) at 0x1d5e4330860>,
 <Relu('Relu.3', (100,)) at 0x1d5e4330a20>,
 <Affine('Affine.5', (100, 100)) at 0x1d5e4330b00>,
 <Relu('Relu.4', (100,)) at 0x1d5e4330c88>,
 <Affine('Affine.6', (100, 10)) at 0x1d5e4330d68>,
 <SoftmaxCrossEntropy('SoftmaxCrossEntropy.2', (10,)) at 0x1d5e4330f28>]

このように、レイヤ表現の最初の要素が整数の場合、その数だけ残りの要素を繰り返します。

layers属性のほかにも、損失に影響を与えるパラメータを取得できます。

model.inputs

[3] 2019-06-12 20:00:20 (6.00ms) python3 (209ms)

[<Input('Affine.1.x', (5,)) at 0x1d5e431ec50>,
 <Input('Relu.1.x', (10,)) at 0x1d5e431eda0>,
 <Input('Affine.2.x', (10,)) at 0x1d5e431ee80>,
 <Input('SoftmaxCrossEntropy.1.x', (4,)) at 0x1d5e4330048>,
 <Input('SoftmaxCrossEntropy.1.t', ()) at 0x1d5e43300b8>]
model.outputs

[4] 2019-06-12 20:00:20 (15.6ms) python3 (225ms)

[<Output('Affine.1.y', (10,)) at 0x1d5e431ec18>,
 <Output('Relu.1.y', (10,)) at 0x1d5e431edd8>,
 <Output('Affine.2.y', (4,)) at 0x1d5e431eef0>,
 <Output('SoftmaxCrossEntropy.1.y', (4,)) at 0x1d5e43300f0>]
model.weights

[5] 2019-06-12 20:00:20 (17.0ms) python3 (242ms)

[<Weight('Affine.1.W', (5, 10)) at 0x1d5e431ecc0>,
 <Weight('Affine.1.b', (10,)) at 0x1d5e431ecf8>,
 <Weight('Affine.2.W', (10, 4)) at 0x1d5e431ef28>,
 <Weight('Affine.2.b', (4,)) at 0x1d5e431ef60>]
model.losses

[6] 2019-06-12 20:00:20 (10.00ms) python3 (252ms)

[<Loss('SoftmaxCrossEntropy.1.loss', ()) at 0x1d5e4330128>]

期待通りの結果が得られました。パラメータだけでなく、変数の取得もできます。

model.input_variables

[7] 2019-06-12 20:00:20 (8.00ms) python3 (260ms)

[<Variable(['Affine.1.x'], (5,)) at 0x1d5e4330240>,
 <Variable(['Affine.1.y', 'Relu.1.x'], (10,)) at 0x1d5e431eeb8>,
 <Variable(['Relu.1.y', 'Affine.2.x'], (10,)) at 0x1d5e4330080>,
 <Variable(['Affine.2.y', 'SoftmaxCrossEntropy.1.x'], (4,)) at 0x1d5e43301d0>,
 <Variable(['SoftmaxCrossEntropy.1.t'], ()) at 0x1d5e4330278>]
model.output_variables

[8] 2019-06-12 20:00:20 (31.3ms) python3 (291ms)

[<Variable(['Affine.1.y', 'Relu.1.x'], (10,)) at 0x1d5e431eeb8>,
 <Variable(['Relu.1.y', 'Affine.2.x'], (10,)) at 0x1d5e4330080>,
 <Variable(['Affine.2.y', 'SoftmaxCrossEntropy.1.x'], (4,)) at 0x1d5e43301d0>,
 <Variable(['SoftmaxCrossEntropy.1.y'], (4,)) at 0x1d5e43302b0>]
model.weight_variables

[9] 2019-06-12 20:00:20 (15.6ms) python3 (306ms)

[<Variable(['Affine.1.W'], (5, 10)) at 0x1d5e43302e8>,
 <Variable(['Affine.1.b'], (10,)) at 0x1d5e4330320>,
 <Variable(['Affine.2.W'], (10, 4)) at 0x1d5e4330358>,
 <Variable(['Affine.2.b'], (4,)) at 0x1d5e4330390>]

inputs_variablesoutput_variablesを比べると一部重複していることが分かります。これは、あるレイヤの出力が次段のレイヤの入力となるためです。外部から入力する変数、もしくは最終的な結果を出力する変数は、以下のように取得できます。

model.data_input_variables

[10] 2019-06-12 20:00:20 (8.05ms) python3 (315ms)

[<Variable(['Affine.1.x'], (5,)) at 0x1d5e4330240>,
 <Variable(['SoftmaxCrossEntropy.1.t'], ()) at 0x1d5e4330278>]
model.data_output_variables

[11] 2019-06-12 20:00:20 (8.98ms) python3 (324ms)

[<Variable(['SoftmaxCrossEntropy.1.y'], (4,)) at 0x1d5e43302b0>]

data_input_variablesにデータを与えて、ニューラルネットワークを評価し、出力をdata_output_variablesから取り出します。損失の評価は、loss_variablesを通じて行います。

model.loss_variables

[12] 2019-06-12 20:00:20 (6.01ms) python3 (330ms)

[<Variable(['SoftmaxCrossEntropy.1.loss'], ()) at 0x1d5e4330438>]

学習は、これらのVariableインスタンスを介して行われます。