DonHurry

step42. μ„ ν˜• νšŒκ·€ λ³Έλ¬Έ

DeZero/πŸ—»μ œ4κ³ μ§€

step42. μ„ ν˜• νšŒκ·€

_도녁 2023. 2. 18. 01:59

πŸ“’ λ³Έ ν¬μŠ€νŒ…μ€ λ°‘λ°”λ‹₯λΆ€ν„° μ‹œμž‘ν•˜λŠ” λ”₯λŸ¬λ‹3을 기반으둜 μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 배운 λ‚΄μš©μ„ κΈ°λ‘ν•˜κ³ , 개인적인 곡뢀λ₯Ό μœ„ν•΄ μž‘μ„±ν•˜λŠ” ν¬μŠ€νŒ…μž…λ‹ˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ ꡐ재 ꡬ맀λ₯Ό κ°•λ ₯ μΆ”μ²œλ“œλ¦½λ‹ˆλ‹€.

 

 

이번 λ‹¨κ³„μ—μ„œλŠ” μ„ ν˜•νšŒκ·€(linear regression)을 κ΅¬ν˜„ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€. λ¨Έμ‹ λŸ¬λ‹ λ¬Έμ œμ—μ„œ κ°€μž₯ 기본이 λ˜λŠ” μ£Όμ œμž…λ‹ˆλ‹€. μš°μ„  같은 λ°μ΄ν„°λ‘œ 계속 μ§„ν–‰ν•΄μ•Όν•˜λ‹ˆ, μ‹œλ“œκ°’μ„ 고정해놓고 μž‘μ€ 데이터셋을 μƒμ„±ν•©λ‹ˆλ‹€.

import numpy as np

np.random.seed(0)
x = np.random.rand(100, 1)
y = 5 + 2 * x + np.random.randn(100, 1)

 

 

λͺ©ν‘œλŠ” μ£Όμ–΄μ§„ xκ°’μœΌλ‘œ y값을 μ˜ˆμΈ‘ν•˜λŠ” λͺ¨λΈ(μˆ˜μ‹)을 λ§Œλ“œλŠ” κ²ƒμž…λ‹ˆλ‹€. 이렇듯 xλ‘œλΆ€ν„° μ‹€μˆ«κ°’ yλ₯Ό μ˜ˆμΈ‘ν•˜λŠ” 것을 νšŒκ·€λΌκ³  ν•˜λ©° μ˜ˆμΈ‘κ°’μ΄ μ„ ν˜•μ„ μ΄λ£¨λŠ” 것을 μ„ ν˜• νšŒκ·€λΌ ν•©λ‹ˆλ‹€. ν˜„μž¬ μ˜ˆμ—μ„œ y와 xκ°€ μ„ ν˜• 관계라고 κ°€μ •ν•˜κ³  있기 λ•Œλ¬Έμ— $y = Wx + b$λΌλŠ” μ‹μœΌλ‘œ ν‘œν˜„μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.

 

 

데이터에 λ§žλŠ” 직선 $y=Wx + b$λ₯Ό μ°ΎκΈ° μœ„ν•΄ 데이터와 예츑치의 차이인 μž”μ°¨λ₯Ό μ΅œμ†Œν™”ν•΄μ•Ό ν•©λ‹ˆλ‹€. μ˜ˆμΈ‘μΉ˜μ™€ λ°μ΄ν„°μ˜ 였차λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μ§€ν‘œλŠ” [식 42.1]κ³Ό κ°™μŠ΅λ‹ˆλ‹€. 이 μˆ˜μ‹μ„ 평균 제곱 였차, mean squared error라고 ν•©λ‹ˆλ‹€. 이 μ‹μœΌλ‘œ ν‘œν˜„λ˜λŠ” μ†μ‹€ν•¨μˆ˜μ˜ 좜λ ₯을 μ΅œμ†Œν™”ν•˜λŠ” W와 bλ₯Ό μ°ΎλŠ” 것이 우리의 λͺ©ν‘œμž…λ‹ˆλ‹€. 손싀 ν•¨μˆ˜λŠ” λͺ¨λΈμ˜ μ„±λŠ₯이 μ–Όλ§ˆλ‚˜ λ‚˜μœκ°€λ₯Ό ν‰κ°€ν•˜λŠ” ν•¨μˆ˜μ΄λ―€λ‘œ μ΅œλŒ€ν•œ 쀄여야할 κ°’μž…λ‹ˆλ‹€.

 

 

이제 κ΅¬ν˜„μœΌλ‘œ λ„˜μ–΄κ°€κ² μŠ΅λ‹ˆλ‹€. ν•¨μˆ˜λ₯Ό μ΅œμ ν™”ν•˜λŠ” λ¬Έμ œλŠ” 이미 28λ‹¨κ³„μ—μ„œ μ§„ν–‰ν–ˆμ—ˆμŠ΅λ‹ˆλ‹€. 큰 틀은 λΉ„μŠ·ν•©λ‹ˆλ‹€. 평균 제곱 였차λ₯Ό κ΅¬ν•˜λŠ” ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜κ³ , κ²½μ‚¬ν•˜κ°•λ²•μ„ 톡해 λ§€κ°œλ³€μˆ˜λ₯Ό κ°±μ‹ ν•˜λ©΄ λ©λ‹ˆλ‹€.

np.random.seed(0)
x = np.random.rand(100, 1)
y = 5 + 2 * x + np.random.randn(100, 1)
x, y = Variable(x), Variable(y)

W = Variable(np.zeros((1, 1)))
b = Variable(np.zeros(1))


def predict(x):
    y = F.matmul(x, W) + b
    return y


def mean_squared_error(x0, x1):
    diff = x0 - x1
    return F.sum(diff ** 2) / len(diff)


lr = 0.1
iters = 100

for i in range(iters):
    y_pred = predict(x)
    loss = mean_squared_error(y, y_pred)

    W.cleargrad()
    b.cleargrad()
    loss.backward()

    W.data -= lr * W.grad.data
    b.data -= lr * b.grad.data
    print(W, b, loss)


# Plot
plt.scatter(x.data, y.data, s=10)
plt.xlabel('x')
plt.ylabel('y')
y_pred = predict(x)
plt.plot(x.data, y_pred.data, color='r')
plt.show()

 

μ½”λ“œλ₯Ό 톡해 μ–»μ–΄μ§€λŠ” 직선 κ·Έλž˜ν”„λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€. (μ‹€μ œλ‘œ μœ„ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ 데이터가 쑰금 더 νΌμ Έμžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.) 좜λ ₯값을 보면 μ μ§„μ μœΌλ‘œ 손싀 ν•¨μˆ˜μ˜ 좜λ ₯값이 μ€„μ–΄λ“œλŠ” 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

 

사싀 μœ„μ—μ„œ κ΅¬ν˜„ν•œ 평균 제곱 였차 ν•¨μˆ˜μ—λŠ” μ•½κ°„μ˜ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€. [κ·Έλ¦Ό 42-6]κ³Ό 같이 쀑간에 이름 μ—†λŠ” λ³€μˆ˜ 3κ°œκ°€ λ“±μž₯ν•˜λŠ”λ°, λ¬Έμ œλŠ” 계산 κ·Έλž˜ν”„κ°€ μ‘΄μž¬ν•˜λŠ” λ™μ•ˆ λ©”λͺ¨λ¦¬μ— 계속 μ‚΄μ•„μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λ©”λͺ¨λ¦¬κ°€ μΆ©λΆ„ν•˜λ‹€λ©΄ 문제될 것이 μ—†μ§€λ§Œ, 더 λ‚˜μ€ 방식을 λ„μž…ν•˜λŠ” 것이 μ’‹μ•„ λ³΄μž…λ‹ˆλ‹€.

 

 

λ”°λΌμ„œ λ‹€μŒκ³Ό 같이 κ°œμ„ ν•˜κ² μŠ΅λ‹ˆλ‹€. 이와 같이 κ΅¬ν˜„ν•˜λ©΄ 쀑간에 λ“±μž₯ν•˜λ˜ λ³€μˆ˜λ“€μ΄ MeanSquaredError 클래슀의 forward λ©”μ„œλ“œμ—μ„œλ§Œ μ‚¬μš©λ©λ‹ˆλ‹€. λ”°λΌμ„œ 이 λ³€μˆ˜λ“€μ€ ndarray μΈμŠ€ν„΄μŠ€λ‘œ μ‚¬μš©λ˜κ³ , forward λ©”μ„œλ“œλ₯Ό λ²—μ–΄λ‚˜λŠ” μˆœκ°„ λ©”λͺ¨λ¦¬μ—μ„œ μ‚­μ œλ˜κ²Œ λ©λ‹ˆλ‹€.

class MeanSquaredError(Function):
    def forward(self, x0, x1):
        diff = x0 - x1
        y = (diff ** 2).sum() / len(diff)
        return y
    
    def backward(self, gy):
        x0, x1 = self.inputs
        diff = x0 - x1
        gx0 = gy * diff * (2. / len(diff))
        gx1 = -gx0
        return gx0, gx1


def mean_squared_error(x0, x1):
    return MeanSquaredError()(x0, x1)