PFNがChainerという新しいDeep Learningのフレームワークを公開したので、早速インストールしてみた。
http://chainer.org/chainer.org
インストールは、git cloneを使えば簡単にできる。
> git clone https://github.com/pfnet/chainer.git
次に、MNISTのサンプルコードを実行してみたが、次のようなエラーがでた。
> python chainer/examples/mnist/train_mnist.py Traceback (most recent call last): File "chainer/examples/mnist/train_mnist.py", line 11, in <module> from chainer import cuda, Variable, FunctionSet, optimizers ImportError: No module named chainer
環境変数PYTHONPATHに、chainerモジュールのパスを追加してみると、下記のようにMNISTのサンプルコードを実行することが出来た。
> export PYTHONPATH=~/Works/DeepNet/chainer:$PYTHONPATH > python chainer/examples/mnist/train_mnist.py fetch MNIST dataset epoch 1 train mean loss=0.275178533252, accuracy=0.915666669135 test mean loss=0.108640040111, accuracy=0.966200004816 epoch 2 train mean loss=0.139073197367, accuracy=0.956600004435 test mean loss=0.0889382731105, accuracy=0.97180000782 epoch 3 train mean loss=0.109916572729, accuracy=0.966483339965 test mean loss=0.0765921290717, accuracy=0.975200003386 epoch 4 ... epoch 19 train mean loss=0.0452081310556, accuracy=0.986866676609 test mean loss=0.0711012239701, accuracy=0.982900006175 epoch 20 train mean loss=0.0445344028511, accuracy=0.986650010943 test mean loss=0.0631615034466, accuracy=0.983500006795
Chainerの特徴は、ネットワーク構造の定義から学習したモデルの保存まで、全ての処理を、Python上で行うシンプルなところである。例えば、caffeではネットワーク構造はprotocol bufferで定義し、学習したモデルはcaffemodelという拡張子のファイルに保存されていたが、Chainerではそんなまどろこしいはしない。
例えば、MNISTのサンプルコードでは、4層のネットワーク(入力層:784ノード、中間層1:1000ノード、中間層2:1000ノード、出力層:10ノード)をpythonコード上で次のように定義している。
# Prepare multi-layer perceptron model model = FunctionSet(l1=F.Linear(784, 1000), l2=F.Linear(1000, 1000), l3=F.Linear(1000, 10)) # Neural net architecture def forward(x_data, y_data, train=True): x, t = Variable(x_data), Variable(y_data) h1 = F.dropout(F.relu(model.l1(x)), train=train) h2 = F.dropout(F.relu(model.l2(h1)), train=train) y = model.l3(h2) return F.softmax_cross_entropy(y, t), F.accuracy(y, t)
具体的には、まず、F.Linearは、2つの層の間にある重み行列Wのサイズを設定し、バイアスbとともに初期化している。例えば、l1=F.Linear(784,1000)では、784x1000の大きさの重み行列W1と、1000次元のベクトルb1を初期化している。
次に、forward関数では、各層の処理を入力層から順番に記述している。例えば、「h1 = F.dropout(F.relu(model.l1(x)), train=train)」では、変数xが与えられた下で、W1^Tx+bを計算し、次にReLUをかけて、その後dropoutしたものを、h1変数に入力する処理を記述している。
MNISTのサンプルコードでは、学習したモデルは保存されていないが、imagenetのサンプルコード、examples/imagenet/train_imagenet.pyでは、最後に、pickleダンプを使って保存している。
# Save final model pickle.dump(model, open('model', 'wb'), -1)
まさに、最初から最後までpythonで簡潔するので、非常にわかりやすいコードである。ちなみに、私は学生の頃に書いたことがある自分のニューラルネットワークのコードを思い出した。ということで、Chainerは学生には受けそうである(企業ではどうだろうか?)。