【機械学習】pytorchで回帰直線を推定してみた!!

機械学習

こんにちは

今回は「pytorchによる回帰直線の推定」を行っていきたいと思います。

「誤差逆伝播」という機械学習の基本的な手法で回帰直線を推定します。

本当に基礎中の基礎なので、しっかり押さえておきましょう。

スポンサーリンク

pytorchによる回帰直線の推定

回帰直線の推定は

  1. データを取得(設定)する
  2. 損失関数を決める
  3. ハイパーパラメータを決める
  4. 繰り返し処理で学習する
  5. 結果を確かめる

という順番でやっていきます。それでは順番に見ていきましょう。

データを取得(設定)する

ではまず、データを設定します。

今回は簡単のため、完全に直線に乗ったデータを用意します。つまり、

X = torch.tensor([1,2,3,4], dtype=torch.float32)
Y = torch.tensor([2,4,6,8], dtype=torch.float32)
w = torch.tensor(5.0, requires_grad = True, dtype=torch.float32)

という\(Y = 2X\)という直線に乗っているデータです。

今回は直線の傾き\(w\)である\(2\)という値を機械学習で推定していきます。

なお、\(w\)は初期値として\(5\)を設定しています。(この値は何でもいいです。)

さらに、\(X\)の値から予想される\(Y\)の推定値\(y_p\)を

def forward(x): 
  y_p = w*x 
  return y_p

という直線モデルで表現することを考えます。

損失関数を決める

次に損失関数\(loss\)を決めます。

損失関数とは、推定精度の指針になるものです。この値は小さいほど推定精度が良いことを示します。

なので損失関数が小さくなるように、学習を行っていきます。

今回は平均二乗誤差という損失関数を使います。

def loss(y, y_p):
  return ((y_p - y)**2).mean()

\(y_p\)は\(y\)の推定値, \(y\)はデータの値です。

つまり、データとデータの推定値の差を二乗し、平均(mean)を取ったものになります。

データとデータの推定値の差は小さい方がいいので、これが最小になるような傾き\(w\)を求めていきます。

ハイパーパラメータを決める

ハイパーパラメータとは、人の手で決めるパラメータのことです。

今回は「学習ループの回数」と「学習率」をハイパーパラメータとして決めます。

ite = 1000  
lr = 0.01

繰り返し処理で学習をする

ではいよいよ学習を行っていきます。

学習は大きく分けて2ステップで

  1. 損失関数を微分
  2. 傾き\(w\)を更新

となります。これを上で決めたite回繰り返します。

for i in range(ite):  
  y_p = forward(X) #2回目から更新されたwが入る→Loss関数が小さくなる  
  l = loss(Y, y_p)  
  l.backward()  
  with torch.no_grad():  
    w -= lr*w.grad  
  w.grad.zero_()  
  if i % 50 == 0:  
    print(f'epoch : {i}, w : {w:.3f}, Loss : {l:.8f}')

4行目が損失関数の微分, 5-6行目が傾きの更新を表しています。

with torch.no_grad()は「演算を行ったときに、その誤差逆伝播を記録しない」という意味です。pytorchは自動で誤差逆伝播を計算しますが、傾き(重み)を更新するための演算に対しては、その必要がないのです。

また、w.gradつまり\(\frac{dLoss}{dw}\)は呼び出されるたびに、値がどんどん足されていくため、ループの最後でw.grad.zero_()として\(\frac{dLoss}{dw}\)をリセットします。

結果を確かめる

学習ループが終わったら、思い通りの結果が出ているか確かめてみましょう。

print(f' w = {w:.3f}')  
# w=2.000

となれば、予想通り\(w = 2.0\)が得られていることが分かります!!

よって、機械学習を使って

$$
X = (1,2,3,4) Y = (2,4,6,8)
$$

というデータから、\(Y = 2X\)という回帰直線を推定することができました!!

まとめ

以下のようなコードで回帰直線を推定しました。

 
import torch

X = torch.tensor([1,2,3,4], dtype=torch.float32)
Y = torch.tensor([2,4,6,8], dtype=torch.float32)
w = torch.tensor(5.0, requires_grad = True, dtype=torch.float32)
def loss(y, y_p):
    return ((y_p - y)**2).mean()

def forward(x):
    y_p = w*x
    return y_p

ite = 1000
lr = 0.01
for i in range(ite):
    y_p = forward(X)
    l = loss(Y, y_p)
    l.backward()
    with torch.no_grad():
        w -=  lr*w.grad
    w.grad.zero_()
    if i % 50 == 0:
        print(f'epoch : {i}, w : {w:.3f}, Loss : {l:.8f}')

print(f' w = {w:.3f}')
        

手順としては

  1. データを取得(設定)する
  2. 損失関数を決める
  3. ハイパーパラメータを決める
  4. 繰り返し処理で学習する
  5. 結果を確かめる

といったものになります。

タイトルとURLをコピーしました