Chainerには4.0からSequentialという機能が導入されています。
これは
h1 = L1.(x)
h2 = L2.(h1)
...
のような層が連続的に重なったネットワークを簡単に記述する機能です。
Kerasを知っている人は、それを思い浮かべるといいかもしれません。
公式のソースコードを一部引用して説明すると、
Model(chainer.Chain):
def __init__(self, n_in, n_hidden, n_out):
super(Model, self).__init__()
with self.init_scope():
self.L1 = L.Linear(n_in, n_hidden)
self.L2 = L.Linear(n_hidden, n_hidden)
self.L3 = L.Linear(n_hidden, n_out)
def __call__(x):
h1 = F.relu(self.L1(x))
h2 = F.relu(self.L1(h1))
return F.relu(self.L1(h2))
model = Model(in,hidden,out)
というネットワークが
from chainer import Sequential
model = Sequential(
L.Linear(n_in, n_hidden),
F.relu,
L.Linear(n_hidden, n_hidden),
F.relu,
L.Linear(n_hidden, n_out)
)
として書けます。
Sequential同士は加算によりつなぐこともできます。
from chainer import Sequential
model_A = Sequential(L.Linear(10, 10), F.relu)
model_B = Sequential(L.Linear(10, 10), F.sigmoid)
model_C = model_A + model_B
max_poolingのような引数が必要な関数はpythonのpartialを用いることで使用できます。
from functools import partial
model = Sequential(
L.Convolution2D(None, 64, 3, 1, 1),
partial(F.max_pooling_2d, ksize=2)
)
最初に固定のネットワークを指定するのではなく、生成した後にappendで層を順番にすることでネットワークを構築できます。
model = Sequential()
model.append(L.Linear(n_in, n_hidden))
model.append(F.relu)
model.append(L.Linear(n_hidden, n_hidden))
model.append(F.relu)
model.append(L.Linear(n_hidden, n_out))
引数にリストを渡すことでネットワークを構築することもできます。
layers = []
layers += [L.Convolution2D(64, 64, ksize=3, pad=1)]
layers += [L.Convolution2D(64, 64, ksize=3, pad=1)]
layers += [L.Convolution2D(64, 64, ksize=3, pad=1)]
...
model = Sequential(*layers)
この方法を使うことで数値が入力された配列からネットワークを構築することもできます。
lns = [512, 512, 512,256,128,64]
in_layer = 512
layers = []
for ln in lns:
layers += [L.Convolution2D(in_layer, ln, ksize=3, pad=1),partial(F.relu)]
in_layer = ln
model = Sequential(*layers)
公式のサンプルを使用しつつ、Sequentialの使い方について説明しました。
複雑なネットワークはこの方法では記述できないですが、
簡単なネットワークやネットワークの一部はSequentialを用いると短く記述できます。