空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

機械学習のお勉強(chainerの概要)

chainerの特徴

ネットワーク構築と学習を同時に行う「Define-by-Run」方式。イメージはインタプリタデバッグしやすい。

tensorflowは「Define-and-Run」方式。イメージはコンパイラ

計算グラフ

class MulAdd(Function):
    def forward_cpu(self, inputs):
        x, y, z = inputs
        w = x * y + z
        return w,

    def backward_cpu(self, inputs, grad_outputs):
        x, y, z = inputs
        gw, = grad_outputs

        gx = y * gw
        gy = x * gw
        gz = gw
        return gx, gy, gz

Define your own function — Chainer 3.0.0rc1 documentation

全結合層におけるバックワード計算

class LinearFunction(Function):
    def forward(self, inputs):
        x, W, b = inputs
        return x.dot(W.T) + b,

    def backward(self, inputs, grad_outputs):
        x, W, b = inputs
        gy, = grad_outputs

        gx = gy.dot(W)
        gW = gy.T.dot(x)
        gb = gy.sum(axis=0)
        return gx, gW, gb

def linear(x, W, b):
    return LinearFunction()(x, W, b)

Config オブジェクト

train/test flagを立てれたり、debug modeの指定などができる

Configuring Chainer — Chainer 3.0.0rc1 documentation

Variableクラス

最高にわかりやすい 👉 Chainerのソースを解析。順伝播と逆伝播の仕組み | コード7区

参考:

chainer-cifar10/Cifar10.py at master · mitmul/chainer-cifar10 · GitHub

ノート/Chainerでネットを可視化する(備忘) 2017-04-27 - 東邦大学理学部情報科学科 山内のサイト

Functionクラス

最高にわかりやすい 👉 Chainerのソースを解析。順伝播と逆伝播の仕組み | コード7区

Standard Function implementations — Chainer 3.0.0rc1 documentation

Linkクラス

イメージ: Function Class + Parameter Class

import chainer
import chainer.functions as F
from chainer import initializers
import numpy as np

class LinearLayer(chainer.Link):

    def __init__(self, n_in, n_out):
        super(LinearLayer, self).__init__()
        with self.init_scope():
            self.W = chainer.Parameter(
                initializers.Normal(), (n_out, n_in))
            self.b = chainer.Parameter(
                initializers.Zero(), (n_out,))

    def __call__(self, x):
        return F.linear(x, self.W, self.b)

chainer.Link — Chainer 3.0.0rc1 documentation

Chainクラス

  • 上記のクラスを統合、管理するクラス

  • これを継承して作成したネットワーク構造のインスタンスをモデルオブジェクトとして使用する

  • Link機能のように機能させることも可能(ChainクラスはLinkクラスの子クラス)

以下の例ではchainクラスを通常のLinkと同様に用いている

import chainer
import chainer.functions as F
import chainer.links as L


class Fire(chainer.Chain):
    def __init__(self, in_size, s1, e1, e3):
        super(Fire, self).__init__(
            conv1=L.Convolution2D(in_size, s1, 1),
            conv2=L.Convolution2D(s1, e1, 1),
            conv3=L.Convolution2D(s1, e3, 3, pad=1),
            bn4=L.BatchNormalization(e1 + e3)
        )

    def __call__(self, x):
        h = F.relu(self.conv1(x))
        h_1 = self.conv2(h)
        h_3 = self.conv3(h)
        h_out = F.concat([h_1, h_3], axis=1)

        return F.relu(self.bn4(h_out))


class SqueezeNet(chainer.Chain):
    def __init__(self, ):
        super(SqueezeNet, self).__init__(
            conv1=L.Convolution2D(3, 96, 7, stride=2),
            fire2=Fire(96, 16, 64, 64),
            fire3=Fire(128, 16, 64, 64),
            fire4=Fire(128, 16, 128, 128),
            fire5=Fire(256, 32, 128, 128),
            fire6=Fire(256, 48, 192, 192),
            fire7=Fire(384, 48, 192, 192),
            fire8=Fire(384, 64, 256, 256),
            fire9=Fire(512, 64, 256, 256),
            conv10=L.Convolution2D(512, 1000, 1,
                pad=1, initialW=normal(0, 0.01 (1000, 512, 1, 1)))
        )

    def __call__(self, x, train=False):
        h = F.relu(self.conv1(x))
        h = F.max_pooling_2d(h, 3, stride=2)

        h = self.fire2(h)
        h = self.fire3(h)
        h = self.fire4(h)

        h = F.max_pooling_2d(h, 3, stride=2)

        h = self.fire5(h)
        h = self.fire6(h)
        h = self.fire7(h)
        h = self.fire8(h)

        h = F.max_pooling_2d(h, 3, stride=2)

        h = self.fire9(h)
        h = F.dropout(h, ratio=0.5, train=train)

        h = F.relu(self.conv10(h))
        h = F.average_pooling_2d(h, 13)

return F.reshape(h, (-1, 1000))

squeezenet-chainer/model.py at master · ejlb/squeezenet-chainer · GitHub

Optimizerクラス

登録

optimizer = optimizers.SGD(lr=0.01)
optimizer.setup(model)

更新

loss = model(x,t)
loss.backward()
optimizer.update()

正規化するメソッドもある

optimizer.add_hook(chainer.optimizer.WeightDecay())

optimizerオブジェクトを作成したあとにadd_hookメソッドを用いて、最適化計算に追加する

Optimizers — Chainer 3.0.0rc1 documentation

Optimizer — Chainer 3.0.0rc1 documentation

Trainerクラス

これを用いることで途中経過や学習経過の監視が一行でかける

ChainerのTrainerを使ってみた - のんびりしているエンジニアの日記

Chainer の Trainer 解説と NStepLSTM について

Reporterによる監視対象のフック

self.loss = F.softmax_cross_entropy(y, t)
self.accuracy = F.accuracy(y, t)

chainer.report({'loss': self.loss, 'accuracy':self.accuracy},self)

Updateクラス

chainer 1.11.0のMNISTサンプルを例にtrainerを読み解く - Monthly Hacker's Blog

複数のモデルをchainerのTrainerで扱うための3つのポイント - Qiita