4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Chainer で単回帰

Last updated at Posted at 2017-03-22

概要

いま Chainer を学習中です。本来の Chainer の使い方ではないのですが、chainer.Link と chainer.Optimizer という一番基本的なクラスだけを用いて、ベタに単回帰を実装したらどうなるか?という実験を行いました(もちろん、実際に単回帰を行いたいときは別の方法でやったほうがいいです)。

単回帰

3点 $ (1, 1), (2, 3), (3, 4) $ のなるべく近くを通る直線 $ y_p = wx + b $ を考え、その傾き $ w $ と 切片 $ b $ を求めることを考えます。

$i$ 番目の点を$(x^{(i)},y^{(i)})$と表すと、平均二乗誤差 $loss$

loss = (1/3)  \sum_{i=1}^{3} ((wx^{(i)} + b) - y^{(i)})^2

が最小になるように $w$ と $b$ を定めることにします。

実際に別のツールで計算してみると、

w = 1.5, b = -0.333333

となります。

image

この計算を以下で Chainer を使ってやってみます。

コード

import numpy as np
import chainer

class SimpleRegression(chainer.Link):
    def __init__(self):
        super().__init__(
            w = (1),
            b = (1),
        )
        self.w.data = np.array([2], dtype = np.float32)
        self.b.data = np.array([0], dtype = np.float32)

    def __call__(self, x):
        return (self.w * x) + self.b

def lossfun(model, xs, ys):
    loss = 0
    for i in range(len(xs)):
        yp = model(xs[i])
        z = yp - ys[i]
        loss += z * z
    return loss / len(xs)

def main():
    xs = [1, 2, 3]
    ys = [1, 3, 4]
    model = SimpleRegression()
    optimizer = chainer.optimizers.SGD(lr = 0.1)
    optimizer.setup(model)
    for i in range(500):
        model.zerograds()
        print("=== Epoch %d ===" % (i + 1))
        print("model.w.data = %f" % model.w.data)
        print("model.w.grad = %f" % model.w.grad)
        print("model.b.data = %f" % model.b.data)
        print("model.b.grad = %f" % model.b.grad)
        loss = lossfun(model, xs, ys)
        print("loss = %f" % loss.data)
        print("")
        loss.backward()
        optimizer.update()

main()

実行結果

=== Epoch 1 ===
model.w.data = 2.000000
model.w.grad = 0.000000
model.b.data = 0.000000
model.b.grad = 0.000000
loss = 2.000000

=== Epoch 2 ===
model.w.data = 1.400000
model.w.grad = 0.000000
model.b.data = -0.266667
model.b.grad = 0.000000
loss = 0.080000

=== Epoch 3 ===
model.w.data = 1.466667
model.w.grad = 0.000000
model.b.data = -0.240000
model.b.grad = 0.000000
loss = 0.057007

...
=== Epoch 499 ===
model.w.data = 1.500000
model.w.grad = 0.000000
model.b.data = -0.333333
model.b.grad = 0.000000
loss = 0.055556

=== Epoch 500 ===
model.w.data = 1.500000
model.w.grad = 0.000000
model.b.data = -0.333333
model.b.grad = 0.000000
loss = 0.055556

$ w $(model.w.data) = 1.5, $b$(model.b.data) = - 0.333333 という解に収束しているのがわかります。

解説

SimpleRegression は、chainer.Link クラスのサブクラスで、$ y_p = wx + b $ というモデルを表現しています(仮説関数(hypothesis function))。それに対して、lossfun 関数が、このモデル(仮説関数)を使った場合の平均二乗誤差を計算しています。この関数の戻り値が chainer.Variable オブジェクトであることに注意してください。loss.backward() で、$w$ と $b$ の傾き(model.w.gradmodel.b.grad) を計算し、optimizer.update() で $w$ と $b$ (model.w.datamodel.b.data) を更新していきます。

参考文献

Introduction to Chainer

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?