tensorflowなしでlinear regression作ってみた

# tensorflowなしでlinear regression作ってみた

### ディープラーニングの基本原理の理解

ディープラーニングの勉強を始めたら、「線形回帰」を先に学ぶと簡単です　　　

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497528/2b5c2e8b-2230-3059-fc23-15c105507966.png)

###### 問題

$$H(x)=wx+b$$

ここでwとbは何でしょうか？

###### 正解

wは１です
bは０です

$$H(x) = x$$

私達は高校で関数について学んだので答えをすぐ見つけることが可能です

しかし、コンピューターは xと yだけでは数式を考え出すことができません
コンピュータが学習すれば、数式を見つけることができます

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497528/a31155a5-8303-92ef-96a5-46a06cecf0c6.png)

はじめはwとbの値がわからないのでランダムに値をリセットします
その後、wとbを変更して数式を探します！
方法は以下の通りです

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497528/9138f75c-03d7-589a-c05c-a93297021d54.png)



$$cost = \frac{1}{m} \sum_{i=1}^{m} (H(x)_i-y_i)^2$$

上記の数式を見て「コスト関数」または「損失関数」
英語では「cost function」または「loss function」と呼びます

$$H(x) = wx$$

H(x)をcost functionにそのまま代入すれば、以下のように定義することができます

$$cost(w) = \frac{1}{m} \sum_{i=1}^{m} (wx_i-y_i)^2 $$

wを0、1、2と仮定し、wを公式に代入してcost(w)を計算してみましょう

###### w = 0 の場合

$$cost(w) =  \frac{ (0*0-0)^2 + (0*1-1)^2 + (0*2-2)^2 + (0*3-3)^2 + (0*4-4)^2 }{5}$$

$$cost(w) =  \frac{ (0)^2 + (-1)^2 + (-2)^2 + (-3)^2 + (-4)^2 }{5}$$

$$cost(w) =  \frac{ 0 + 1 + 4 + 9 + 16 }{5}$$

$$cost(w) =  \frac{ 30 }{5}$$

$$cost(w) =  6$$

###### w = 1 の場合

$$cost(w) =  \frac{ (1*0-0)^2 + (1*1-1)^2 + (1*2-2)^2 + (1*3-3)^2 + (1*4-4)^2 }{5}$$

$$cost(w) =  \frac{ (0)^2 + (0)^2 + (0)^2 + (0)^2 + (0)^2 }{5}$$

$$cost(w) =  \frac{ 0 + 0 + 0 + 0 + 0 }{5}$$

$$cost(w) =  \frac{ 0 }{5}$$

$$cost(w) =  0$$

###### w = 2 の場合

$$cost(w) =  \frac{ (2*0-0)^2 + (2*1-1)^2 + (2*2-2)^2 + (2*3-3)^2 + (2*4-4)^2 }{5}$$

$$cost(w) =  \frac{ (0)^2 + (1)^2 + (2)^2 + (3)^2 + (4)^2 }{5}$$

$$cost(w) =  \frac{ 0 + 1 + 4 + 9 + 16 }{5}$$

$$cost(w) =  \frac{ 30 }{5}$$

$$cost(w) =  6$$

つまり、以下のような値を導くことができます！

w = 0, cost(w) = 6
w = 1, cost(w) = 0
w = 2, cost(w) = 6

上の値をwとcost(w)に対するグラフで表すと以下のようになります

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497528/84a5649e-2f49-0ff5-98e5-8ae96f3d4045.png)

実際にはcost function は曲線（U）の形です

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497528/dfce3f9f-a136-a4ca-4d7b-aa55cff1fbce.png)

もし初期w値が2に設定された場合、

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497528/87d2c49f-a365-6d16-300f-9438380d11bf.png)


正解 w = 1 の値に変化するため、
この場合使われるのが「傾斜下降」 英語では「gradient descent」です

w 値を更新する際に使用される公式は以下の通りです

$$\alpha = learning rate$$

$$w := w - \alpha \frac{\partial}{\partial W} cost(w)$$

cost functionにwに対して微分した後、learning rate(学習比率)をかけて出た結果値をwから引いて更新します

$$cost(w) = \frac{1}{m} \sum_{i=1}^{m} (wx_i-y_i)^2 $$

cost functionは上のようなものですから、傾斜下降公式に代入すると以下のようになります

$$w := w - \alpha \frac{\partial}{\partial W} \frac{1}{m} \sum_{i=1}^{m} (wx_i-y_i)^2$$

wに対して微分すると公式は以下のようになります

$$w := w - \alpha \frac{1}{m} \sum_{i=1}^{m} 2(wx_i-y_i)x_i$$

一回実行すると以下の通りになります！

learning rate = 0.01
w = 2

$$w := 2 - 0.01 *  \frac{ 0 + 2 + 8 + 18 + 32 }{5}$$

$$w := 2 - 0.01 *  \frac{ 60 }{5}$$

$$w := 2 - 0.01 * 12$$

$$w := 2 - 0.12$$

$$w := 1.88$$

つまり、wの値が2から1.88に更新されたことが確認できます

このように反復して学習する場合、wの値が傾斜下降によってwが正解に近くなります

### pythonコードでつくる

x = [0, 1, 2, 3, 4]
y = [0, 1, 2, 3, 4]
w = 2
learning_rate = 0.01

```
for step in range(0, 1000):
    for i in range(0, len(x)):
        sum = 2 * (w * x[i] - y[i]) * x[i]
    update_w = learning_rate * ( sum / len(x) )
    w = w - update_w
    if step % 50 == 0:
        print('step = {}, w = {}'.format(step, w))
```

### 下の仮説も解いてみよう

$$H(x)=wx+b$$

上記のweight値についてのみ更新したので、bias値についても更新してみましょう

###### cost function

$$cost(w, b) = \frac{1}{m} \sum_{i=1}^{m} (wx_i + b_i - y_i)^2 $$

###### 学習比率

$$\alpha = learning rate$$

###### w更新の公式

$$w := w - \alpha \frac{\partial}{\partial W} \frac{1}{m} \sum_{i=1}^{m} (wx_i + b_i - y_i)^2$$

$$w := w - \alpha \frac{1}{m} \sum_{i=1}^{m} 2(wx_i + b_i - y_i)x_i$$

###### b更新の公式

$$b := b - \alpha \frac{\partial}{\partial b} \frac{1}{m} \sum_{i=1}^{m} (wx_i + b_i - y_i)^2$$

$$b := b - \alpha \frac{1}{m} \sum_{i=1}^{m} 2(wx_i + b_i - y_i)$$

### pythonコードでつくる

```
import matplotlib.pyplot as plt

def linear(input, w, y):
    output = []
    for x in input:
        h = w * x + y
        output.append(h)
    return output

x = [0, 1, 2, 3, 4]
y = linear(x, 1, 3) # w=1 b=3
b = 0
w = 5
learning_rate = 0.01

for step in range(0, 1000):
    w_sum = 0
    b_sum = 0
    for i in range(0, len(x)):
        # update w
        w_sum += 2 * (w * x[i] + b - y[i]) * x[i]
        
        # update b
        b_sum += 2 * (w * x[i] + b - y[i])
    update_w = learning_rate * ( w_sum / len(x) )
    update_b = learning_rate * ( b_sum / len(x) )
    
    w = w - update_w
    b = b - update_b
    
    if step % 50 == 0:
        print('step = {}, w = {}, b = {}'.format(step, w, b))
```

### 結果

![anim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497528/c7d1aae3-ffa3-0778-f179-0fa0fbbc376f.gif)

### これをtensorflowで作ると...
```
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

x_train = np.array([1, 2, 3, 4, 5])
y_train = x_train * 2

model = tf.keras.models.Sequential([
  tf.keras.layers.Dense(1, activation=None),
])

model.compile(
    optimizer=tf.optimizers.Adam(learning_rate=0.1),
    loss='mean_absolute_error',
    metrics=['accuracy']
)

model.fit(x_train, y_train, epochs=1000)
model.evaluate(x_train,  y_train, verbose=2)

x_test = np.array([6, 7, 8, 9, 10])
p_model = model(x_test)
y_hat = p_model.numpy()
```

### まとめ

ディープラーニングは数学がすべてです
最初からframeworkを使うより原理を理解することが大切です!