0
0

More than 3 years have passed since last update.

pytorchの線形回帰を練習

Posted at

ここ数日、PyTorch for Deep Learning - Full Course / Tutorialという動画を見ています。
この動画を見終えると、GANで画像を生成する技術が身につくそうです。

PyTorch for Deep Learning - Full Course / Tutorial: https://youtu.be/GIsg-ZUy0MY
GANでの画像生成のすごいやつ:
 GANを使って簡単に架空アイドル画像を自動生成(Progressive Growing of GANs)https://www.mahirokazuko.com/entry/2018/12/15/201501

この9時間のコースの第2章、"Linear Regression"の内容が頭にまだ入りきっていないので、qiitaの記事を書くことで定着を図ろうとしています。

目標

以下で行っていることを、pytorchを使って表現できるようになることです。
できれば、サンプル数を900000などに設定しなくても、うまくいってほしいです。


import random

# a * x + c の a, cを予測する。

def two_x_plus_three(x):
    return 2 * x + 3
#入力をランダムに作る。
inputs = [random.randint(0, 100) for _ in range(900000)]

#入力の個数にあわせて、targetを作る。
targets = [two_x_plus_three(x) for x in inputs]

#学習される前のa, cの予測値をランダムに作る。
a_assumed = float(random.randint(0, 100))
c_assumed = float(random.randint(0, 100))

#学習率
learning_rate = 0.01

for i, x in enumerate(inputs):
    #e: 微分に使う微小な値
    e = 0.001

    #pred: 予測値
    pred = a_assumed * x + c_assumed
    #予測値と目標値の差を表す関数diffを、a_assumed, c_assumedについて微分する。
    pred_ae = (a_assumed - e) * x + c_assumed
    pred_ce = a_assumed * x + (c_assumed - e)

    diff = (pred - targets[i]) ** 2
    diff_da = diff - (pred_ae - targets[i]) ** 2
    diff_dc = diff - (pred_ce - targets[i]) ** 2

    #得られた傾きと逆方向に、a_assumed, c_assumedを動かす。
    a_assumed -= diff_da * learning_rate
    c_assumed -= diff_dc * learning_rate

print(a_assumed) #1.99など
print(c_assumed) #3.37など


Gradient Descentを用いた学習の6つのステップ

学習は、以下の6つのステップをたどります。

0 データセットを用意する
1 予測を生成する
2 損失を計算する
3 重さとバイアスに関連する勾配を計算する
4 学習率の分だけ、勾配を重さとバイアスに反映する
5 勾配をゼロに戻す


import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader
import random

# 0 データセットを用意する

def two_x_plus_three(x):
    return 2 * x + 3

inputs = np.array(\
         [[random.randint(0, 100)] for _ in range(300)],\
         dtype = 'float32')

targets = np.array(\
          [two_x_plus_three(x) for x in inputs],\
          dtype = 'float32')

inputs  = torch.from_numpy(inputs)
targets = torch.from_numpy(targets)

train_ds = TensorDataset(inputs, targets)
batch_size = 5
#DataLoaderを使うと、batch_sizeの分だけ毎回学習を行える。
train_dl = DataLoader(train_ds, batch_size, shuffle = True)

# 1 予測を生成する に使う
model = nn.Linear(1,1)

# 2 損失を計算する, 3 勾配を計算する に使う
loss_fn = F.mse_loss
loss = loss_fn(model(inputs), targets)

# 4 学習率の分だけ、勾配を重さとバイアスに反映する に使う
opt = torch.optim.SGD(model.parameters(), lr = 0.0001)

def fit(num_epochs, model, loss_fn, opt, train_dl):
    for epoch in range(num_epochs):

        for x_batch, y_batch in train_dl:
            # 1 予測を生成する。
            pred = model(x_batch)

            # 2 損失を計算する
            loss = loss_fn(pred, y_batch)

            # 3 勾配を計算する
            loss.backward()

            # 4 学習率の分だけ、勾配を重さとバイアスに反映する
            opt.step()

            # 5 勾配をゼロに戻す
            opt.zero_grad()

fit(2000, model, loss_fn, opt, train_dl)

print(list(model.parameters()))

結果:


[Parameter containing:
tensor([[2.0002]], requires_grad=True), Parameter containing:
tensor([2.9884], requires_grad=True)]

y =2x + 3なので、なかなかいいんじゃないでしょうか。

0
0
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
0
0