1.1 Linear Regression
지훈이는 오늘도 싱글벙글 게임을 켰다. 슬라임을 1시간 동안 사냥을 하면 30원을 번다. 2시간을 사냥하면 60원을, 3시간을 사냥하면 90원을 벌 수 있다. 이로부터 지훈이는 4시간 동안 사냥했을 때 얼마나 벌 수 있을까를 예측할 수 있다.
| Hours ($x$) | Money ($y$) |
|---|---|
| 1 | 30 |
| 2 | 60 |
| 3 | 90 |
| 4 | ? |
모델을 학습시킬 때 우리는 기존에 알고 있는 데이터를 사용한다. 위 표에서 1시간, 2시간, 3시간 사냥 시 얻을 수 있는 금액을 나타낸 데이터를 Training dataset, 학습이 끝난 후 모델이 잘 작동하는지 확인하기 위해 집어넣는 데이터를 Test dataset이라고 한다.
1.1.1 Linear Regression
모델 학습을 위한 데이터는 torch.tensor 데이터 타입을 사용한다. 입력은 x, 출력은 y로 표기한다.
모델은 다음과 같이 가정하자. Linear regression은 학습 데이터와 가장 유사한 직선을 찾는 것이므로,
\[y = Wx + b\]여기서 $W$를 weight, $b$를 bias라고 한다.
먼저 초기 weight와 bias를 0으로 초기화하자. 즉 항상 출력 0을 예측한다.
- required_grad=True : 이 데이터를 학습할 것이라고 명시하는 의미
학습을 위해 이 모델이 실제와 얼마나 다른지를 확인해야 한다. 다음과 같은 loss를 정의하자.(Mean Squared Error, MSE)
\[cost(W, b) = \frac{1}{m} \sum_{i=1}^m (H(x^{(i)}) - y^{(i)})^2\] - torch.mean : 평균을 계산
이 loss function으로부터 모델을 개선시키자. torch.optim 라이브러리에서 Stochastic Gradient Descent, SGD optimizer 를 사용할 것이다. Loss가 최소가 되는 지점을 알고 싶으므로, gradient가 (-)가 되도록 값을 이동시키는 방법이다.
- torch.optim.SGD(params, lr) : 학습할 텐서와 learning rate를 input으로 받아 모델을 학습
- zero_grad() : gradient 초기화
- backward() : gradient 계산
- step() : 계산된 gradient로 텐서 개선
학습할 tensor를 [W, b]로, learning rate를 lr = 0.01로 두자.
전체 코드는 다음과 같다. 데이터를 정의하고 hypothesis를 초기화한다. 어떤 Optimizer를 사용할 것인지 정의한다. 이 부분은 처음 한 번만 있으면 된다.
이후 hypothesis를 예측하고 cost를 계산해 optimizer로 학습하는 내용을 반복한다.
- Result : [tensor([29.5617], requires_grad=True), tensor([0.9963], requires_grad=True)]
SGD는 어떤 방식으로 모델을 학습시킬까? 다시 linear regression model로 돌아가면,
\[cost(W) = \frac{1}{m} \sum_{i=1}^m (Wx^{(i)} + b - y^{(i)})^2\]cost의 gradient를 구한다.
\[D_W = \frac{\partial cost}{\partial W} = \frac{2}{m} \sum_{i=1}^m (Wx^{(i)} + b - y^{(i)})x^{(i)}\]Gradient가 양수이면 weight를 줄여야 하고, gradient가 음수이면 weight를 늘려야 한다. 따라서 weight는 다음과 같이 재정의된다.
\[W := W - \alpha D_W\]여기서 $\alpha$가 learning rate, $D_W$가 weight에 대한 cost의 gradient이다.
마찬가지로 bias는
\[D_b = \frac{\partial cost}{\partial b} = \frac{2}{m} \sum_{i=1}^m (Wx^{(i)} + b - y^{(i)})\] \[b := b - \alpha D_b\]이를 바탕으로 torch.optim 라이브러리 없이 구현한 코드가 다음과 같다.
- Result:
Epoch 100/1000 W: 26.1762, b: 8.6920, Cost: 10.890694
Epoch 200/1000 W: 26.9943, b: 6.8328, Cost: 6.729773
Epoch 300/1000 W: 27.6372, b: 5.3712, Cost: 4.158598
Epoch 400/1000 W: 28.1426, b: 4.2222, Cost: 2.569760
Epoch 500/1000 W: 28.5399, b: 3.3191, Cost: 1.587953
Epoch 600/1000 W: 28.8523, b: 2.6091, Cost: 0.981258
Epoch 700/1000 W: 29.0978, b: 2.0510, Cost: 0.606357
Epoch 800/1000 W: 29.2908, b: 1.6123, Cost: 0.374696
Epoch 900/1000 W: 29.4425, b: 1.2674, Cost: 0.231537
Epoch 1000/1000 W: 29.5617, b: 0.9963, Cost: 0.143077