어제는 딥러닝 모듈인 PyTorch를 사용하지 않고 선형회귀(Linear regression)식을 직접 구현하여 예측값을 얻었지만, 이번엔 본격적으로 PyTorch를 이용해 구현했다.
X = [1, 2, 3, 4, 5, 6, 7]
Y = [25000, 55000, 75000, 110000, 128000, 155000, 180000]
데이터가 위와 같이 주어졌을 때 x값이 8일 때의 y값을 예측하는 것이다.
우선 값들을 텐서화 하기 위해 다음과 같이 코딩한다.
X = [[i] for i in X]
Y = [[i] for i in Y]
x_data = torch.Tensor(X)
y_data = torch.Tensor(Y)
X, Y 텐서를 입력하여 다음 값을 예측해야 하며, 둘 다 1차원이다.
선형회귀 모델을 만들기 위해 LinearRegressionModel이라는 클래스를 준비한다. 딥러닝 신경망을 사용하기 위해 torch.nn.Module도 필요하다.
class LinearRegressionModel(torch.nn.Module):
def __init__(self, input_dim, output_dim):
super(LinearRegressionModel, self).__init__()
self.linear = torch.nn.Linear(input_dim, output_dim)
def forward(self, x):
y_pred = self.linear(x)
return y_pred
model = LinearRegressionModel(1, 1)
이렇게 입력값이 두개가 되도록 설정하고, y_pred 변수가 출력이 되도록 linear 함수를 저장시킨다. linear 변수에는 선형함수를 사용하도록 torch.nn.Linear를 입력한다.
손실함수는 mean square error를 사용하기 위해 다음과 같이 선언한다.
criterion = torch.nn.MSELoss()
그리고 딥러닝에는 최적화(optimization)이라는 과정이 있다. 학습을 반복하면서 손실(loss)이 최소가 되게 하는 과정이다. 대표적으로 Stochastic Gradient Descent, 줄여서 SGD라는 것이 있다. 기울기를 구할 때 전체 데이터가 아닌 일부만을 이용하여 계산이 부정확할 수 있지만 계산을 빠르게 할 수 있고, 극소값이 아닌 최소값에 빠지기 쉽게 해준다.
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)
lr은 learning rate(학습률)의 준말인데, 딥러닝 모델이 한번에 학습하는데 걸리는 시간을 뜻한다. 너무 크게 설정하면 데이터가 무질서하게 이동할 수 있어 최소값에 도달하지 못할 수 있고, 그렇다고 너무 작게 설정하면 학습이 느려져 최소값에 도달하기 전에 학습이 끝나게 될 수 있다. 그러므로 적당한 값이 중요하다.
for epoch in range(10001):
pred_y = model(x_data)
loss = criterion(pred_y, y_data)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 1000 == 0:
print("[ epoch: %d, cost: %.2f ]" % (epoch, loss.data))
print("w = %.2f, b = %.2f" % (model.linear.weight, model.linear.bias))
print("f(x) = %.2fx + %.2f" % (model.linear.weight, model.linear.bias))
print("예측값: [%.2f]" % (model(torch.Tensor([[8]]))))
마지막으로 학습을 위한 코딩을 하는데, 여기서 최적화를 할 때 optimizer.zero_grad()라는 코드를 볼 수 있다. 기울기를 0으로 초기화 하겠다는 뜻인데, 매번 다른 기울기를 정확하게 얻기 위한 것이며, 혹시나 있을 수 있는 불필요한 변화를 없에려는 것이다.
그리고 딥러닝 과정중에 back propagation(역전파)이라는 과정이 있다. 인공신경망에서 앞으로 진행하다가 뒤로도 가보면서 손실값을 변경하는 것이다. 적당히 뒤로가고 나서는 다시 앞으로 진행하면서 최적화(optimizer.step())를 한다.
최종적으로 X값이 8이었을 때 206523.78이 나왔다.
import torch
X = [1, 2, 3, 4, 5, 6, 7]
Y = [25000, 55000, 75000, 110000, 128000, 155000, 180000]
X = [[i] for i in X]
Y = [[i] for i in Y]
x_data = torch.Tensor(X)
y_data = torch.Tensor(Y)
class LinearRegressionModel(torch.nn.Module):
def __init__(self, input_dim, output_dim):
super(LinearRegressionModel, self).__init__()
self.linear = torch.nn.Linear(input_dim, output_dim)
def forward(self, x):
y_pred = self.linear(x)
return y_pred
model = LinearRegressionModel(1, 1) # X, Y 둘다 1차원 리스트
criterion = torch.nn.MSELoss() # 손실 함수: Mean Squared Error
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)
for epoch in range(10001):
pred_y = model(x_data) # model 데이터 x를 넣어서 결과를 구함
loss = criterion(pred_y, y_data) # 구한 데이터와 실제 데이터를 비교하는 손실 함수로 MSELoss 사용
optimizer.zero_grad() # zero_grad: back propagation 전에 기울기를 0으로 초기화 해줘야 함
loss.backward() # back propagation으로 parameter에 대해 gradient 구함
optimizer.step() # 최적화 진행; model parameter들을 learning rate만큼 기울기를 곱함
if epoch % 1000 == 0:
print("[ epoch: %d, cost: %.2f ]" % (epoch, loss.data))
print("w = %.2f, b = %.2f" % (model.linear.weight, model.linear.bias))
print("\nf(x) = %.2fx + %.2f" % (model.linear.weight, model.linear.bias))
print("예측값: [%.2f]" % (model(torch.Tensor([[8]]))))