-
[기계학습] 선형회귀(Linear Regression) (Part 2/2)코딩(Coding)/기계학습 2022. 1. 18. 12:49728x90
이전 포스팅의 개념적인 부분을 python의 pytorch 패키지를 통해 구현하는 포스팅입니다.
이전 포스팅을 보고오세요~ :D (https://jsy-coding-blog.tistory.com/45)포스팅에서 사용하는 PPT 자료는 제 Github에서 pdf 형식으로 받을 수 있습니다.
(https://github.com/JoSangYeon/Machine_Learning_Project/blob/master/PPT/01.%20Machine%20Learning.pdf)
선형회귀 구현(with Pytorch)
이전 포스팅에서 다뤘던 선형회귀의 개념을 Pytorch를 통해 구현해보자!
사용할 라이브러리를 import 한다.
import numpy as np import pandas as pd import matplotlib.pyplot as plt import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torch.utils.data import Dataset, DataLoader
머신러닝 연산 과정
데이터들을 가장 잘 대변하는 직선 방정식을 찾는 것
순서는 아래와 같이 정의할 수 있겠다.
- 가설 설정
- H(X) = W * X + b
- 가설 직선은 W(기울기)와 b(절편)으로 선의 모양이 결정된다.
- Loss 값 계산
- Loss = (Label - H(x)) ** 2
- 실제값(Label)과 예측값(H(x))간의 차이를 계산
- MSE(평균오차제곱) : Loss(W,b) = Mean((Label - H(x))^2)
- 실제값과 예측값의 대한 차이 Loss는 W,b에 대한 함수로 표현 할 수 있음
- 즉 축이 W축, b축, Loss축인 3차원 그래프가 형성 됨.
- Loss = (Label - H(x)) ** 2
- 비용 최소화
- Loss(W,b)가 최소가 되는 W와 b를 찾는 작업
- 경사하강법을 통해 W,b 값을 갱신 해나간다.
- H(X) = W * X + b
- 가설 직선은 W(기울기)와 b(절편)으로 선의 모양이 결정된다.
- Loss(W,b)가 최소가 되는 W와 b를 찾는 작업
# 예제 x_data = torch.tensor([[1],[2],[3],[4],[5]]).float() y_data = torch.tensor([[3],[5],[2],[4],[1]]).float() plt.plot(x_data, y_data, 'ro--') plt.show()
# 가설 설정 def H(x): return x*W.detach().numpy() + b.detach().numpy() W = torch.tensor([3.2], requires_grad=True) b = torch.tensor([-1.5], requires_grad=True) plt.plot(x_data, y_data, 'ro--') plt.plot(x_data, H(x_data), 'b-') plt.show()
학습을 통해 오차가 최소가 되는 가설 직선 H(x)를 구해보자
hypothesis = lambda x : x * W + b loss_fn = lambda x : torch.mean((hypothesis(x) - y_data) ** 2) opt = optim.SGD([W, b], lr=0.01)
print("학습 전 >>> W : {:.3f}\tb : {:.3f}\n".format(W.item(), b.item())) for epoch in range(1, 1001): output = hypothesis(x_data) loss = loss_fn(x_data) opt.zero_grad() loss.backward() opt.step() if epoch % 25 ==0: print("epoch {} >>> loss : {:.4f}".format(epoch,loss.item())) print("\n학습 후 >>> W : {:.3f}\tb : {:.3f}".format(W.item(), b.item()))
학습 전 >>> W : 0.154 b : 2.138 epoch 25 >>> loss : 2.3632 epoch 50 >>> loss : 2.2287 epoch 75 >>> loss : 2.1152 epoch 100 >>> loss : 2.0194 ... 중간생략 ... epoch 800 >>> loss : 1.5045 epoch 825 >>> loss : 1.5038 epoch 850 >>> loss : 1.5032 epoch 875 >>> loss : 1.5027 epoch 900 >>> loss : 1.5023 epoch 925 >>> loss : 1.5019 epoch 950 >>> loss : 1.5016 epoch 975 >>> loss : 1.5014 epoch 1000 >>> loss : 1.5012 학습 후 >>> W : -0.478 b : 4.420
print("\n학습 후 >>> W : {:.3f}\tb : {:.3f}".format(W.item(), b.item())) plt.plot(x_data, y_data, 'ro--') plt.plot(x_data, H(x_data), 'b-') plt.show()
학습 후 >>> W : -0.478 b : 4.420
nn.Module
- 1Layer 딥러닝 관점
class MyModel(nn.Module): def __init__(self): super(MyModel, self).__init__() self.fc = nn.Linear(1,1) def forward(self, x): x = self.fc(x) return x model = MyModel() loss_fn = nn.MSELoss() opt = optim.SGD(model.parameters(), lr=0.01) print(model) print(list(model.parameters()))
MyModel( (fc): Linear(in_features=1, out_features=1, bias=True) ) [Parameter containing: tensor([[0.4373]], requires_grad=True), Parameter containing: tensor([-0.8967], requires_grad=True)]
W, b = get_weights(model) print("학습 전 >>> W : {:.3f}\tb : {:.3f}\n".format(W, b)) plt.plot(x_data, y_data, 'ro--') plt.plot(x_data, x_data*W + b, 'b-') plt.show()
학습 전 >>> W : 0.437 b : -0.897
def get_weights(model): weights = list(model.parameters()) W = weights[0].item() b = weights[1].item() return W,b W, b = get_weights(model) print("학습 전 >>> W : {:.3f}\tb : {:.3f}\n".format(W, b)) for epoch in range(1, 1001): output = model(x_data) loss = loss_fn(output, y_data) opt.zero_grad() loss.backward() opt.step() if epoch % 25 ==0: print("epoch {} >>> loss : {:.4f}".format(epoch,loss.item())) W, b = get_weights(model) print("\n학습 후 >>> W : {:.3f}\tb : {:.3f}".format(W, b))
학습 전 >>> W : 0.437 b : -0.897 epoch 25 >>> loss : 5.7695 epoch 50 >>> loss : 5.1044 epoch 75 >>> loss : 4.5430 epoch 100 >>> loss : 4.0690 ... 중간 생략 ... epoch 800 >>> loss : 1.5224 epoch 825 >>> loss : 1.5189 epoch 850 >>> loss : 1.5160 epoch 875 >>> loss : 1.5135 epoch 900 >>> loss : 1.5114 epoch 925 >>> loss : 1.5096 epoch 950 >>> loss : 1.5081 epoch 975 >>> loss : 1.5069 epoch 1000 >>> loss : 1.5058 학습 후 >>> W : -0.451 b : 4.322
print("\n학습 후 >>> W : {:.3f}\tb : {:.3f}".format(W, b)) plt.plot(x_data, y_data, 'ro--') plt.plot(x_data, x_data*W + b, 'b-') plt.show()
학습 후 >>> W : -0.451 b : 4.322
다변수 회귀
- Input_Feature의 개수가 2개 이상
- 따라서 가설직선 함수의 모양은
H(X1,X2,X3... Xn) = W1*X1 + W2*X2 + ... + Wn * Xn + b
- 학습시켜야할 가중치들은 W1 ~ Wn와 b이다.
# Data & Label x1 = torch.tensor([[73.],[93.],[89.],[96.],[73.]]) x2 = torch.tensor([[80.],[88.],[91.],[98.],[66.]]) x3 = torch.tensor([[75.],[93.],[90.],[100.],[70.]]) Y = torch.tensor([[152.],[185.],[180.],[196.],[142.]])
# 가설 설정 def H(x1, x2, x3): return x1*W1.detach().numpy() + x2*W2.detach().numpy() + x3*W3.detach().numpy() + b.detach().numpy() W1 = torch.tensor([-1.5], requires_grad=True) W2 = torch.tensor([1.5], requires_grad=True) W3 = torch.tensor([-3.], requires_grad=True) b = torch.tensor([3.], requires_grad=True)
즉, 초기
H(x) = -1.5*x1 + 1.5*x2 -3*x3 + 3
print("실제값 Y :", Y[0].item()) print("예측값 Y :", H(x1[0], x2[0], x3[0]).item())
실제값 Y : 152.0 예측값 Y : -211.5
아직 학습 전이라 완전히 다른 값이 나오게 된다.
# 학습 설계 opt = optim.SGD([W1, W2, W3, b], lr=0.0000005) print("\n학습 전 >>> W1 : {:.3f}\tW2 : {:.3f}\n\t W3 : {:.3f}\tb : {:.3f}\n".format(W1.item(), W2.item(), W3.item(), b.item())) for epoch in range(1, 251): output = x1*W1 + x2*W2 + x3*W3 + b loss = torch.mean(output - Y) ** 2 opt.zero_grad() loss.backward() opt.step() if epoch % 25 ==0: print("epoch {} >>> loss : {:.4f}".format(epoch,loss.item())) print("\n학습 후 >>> W1 : {:.3f}\tW2 : {:.3f}\n\t W3 : {:.3f}\tb : {:.3f}".format(W1.item(), W2.item(), W3.item(), b.item()))
학습 전 >>> W1 : -1.500 W2 : 1.500 W3 : -3.000 b : 3.000 epoch 25 >>> loss : 63116.0977 epoch 50 >>> loss : 21099.0605 epoch 75 >>> loss : 7053.1982 epoch 100 >>> loss : 2357.8110 epoch 125 >>> loss : 788.1897 epoch 150 >>> loss : 263.4839 epoch 175 >>> loss : 88.0808 epoch 200 >>> loss : 29.4445 epoch 225 >>> loss : 9.8428 epoch 250 >>> loss : 3.2905 학습 후 >>> W1 : 0.156 W2 : 3.152 W3 : -1.328 b : 3.020
print("실제값 Y :", Y) print("예측값 Y :", H(x1, x2, x3))
실제값 Y : tensor([[152.], [185.], [180.], [196.], [142.]]) 예측값 Y : tensor([[166.9637], [171.3931], [184.2102], [194.0849], [129.4749]])
Matrix(행렬)
- 행렬의 곱셈 공식을 이용(내적 = Dot Product)
- H(x)=wx+b
H(x1,x2,x3)=w1x1+w2x2+w3x3+b
여기서 H(x1,x2,x3)는...
- H(x1,x2,x3)=w1x1+w2x2+w3x3_+b
w1x1+w2x2+w3x3
(w1w2w3)⋅(x1 x2 x3)
WX
- (W, X 는 matrix)
H(x1,x2,x3)=w1x1+w2x2+w3x3+b
=b+w1x1+w2x2+w3x3
=(1x1x2x3)⋅(b w1 w2 w3)
=XW
- 즉, 복잡한 모양의 데이터(데이터의 개수 모양에 상관 X)에도 간략하게 표현이 가능
- 따라서, H(x1, x2, x3) => H(X) = Xn * Wn + b
X도 여러개, Y도 여러개일 경우
### 연습 ### x_data = torch.tensor([ [13, 24, 52], [42, 53, 42], [33, 29, 57], [25, 26, 81], [17, 28, 39] ]).float() y_data = torch.tensor([ [21,45], [67,42], [82,91], [57,52], [17,49] ]).float()
class MyModel(nn.Module): def __init__(self): super(MyModel, self).__init__() self.fc = nn.Linear(3,2) def forward(self, x): x = self.fc(x) return x model = MyModel() loss_fn = nn.MSELoss() opt = optim.SGD(model.parameters(), lr=0.0001) print(model) print(list(model.parameters()))
MyModel( (fc): Linear(in_features=3, out_features=2, bias=True) ) [Parameter containing: tensor([[-0.2880, -0.3012, -0.3388], [-0.0368, 0.3511, -0.2049]], requires_grad=True), Parameter containing: tensor([ 0.0319, -0.2258], requires_grad=True)]
print("학습 전 파라미터 : \n\t\t\t {}\n".format(list(model.parameters()))) for epoch in range(1, 1001): output = model(x_data) loss = loss_fn(output, y_data) opt.zero_grad() loss.backward() opt.step() if epoch % 25 ==0: print("epoch {} >>> loss : {:.4f}".format(epoch,loss.item())) print("학습 후 파라미터 : \n\t\t\t {}\n".format(list(model.parameters())))
학습 전 파라미터 : [Parameter containing: tensor([[-0.2880, -0.3012, -0.3388], [-0.0368, 0.3511, -0.2049]], requires_grad=True), Parameter containing: tensor([ 0.0319, -0.2258], requires_grad=True)] epoch 25 >>> loss : 353.1830 epoch 50 >>> loss : 320.6848 epoch 75 >>> loss : 300.9650 epoch 100 >>> loss : 285.6898 epoch 125 >>> loss : 272.5851 epoch 150 >>> loss : 260.9588 epoch 175 >>> loss : 250.5402 epoch 200 >>> loss : 241.1762 ... 중간생략 ... epoch 800 >>> loss : 163.6429 epoch 825 >>> loss : 162.9643 epoch 850 >>> loss : 162.3523 epoch 875 >>> loss : 161.8005 epoch 900 >>> loss : 161.3027 epoch 925 >>> loss : 160.8535 epoch 950 >>> loss : 160.4481 epoch 975 >>> loss : 160.0821 epoch 1000 >>> loss : 159.7514 학습 후 파라미터 : [Parameter containing: tensor([[ 3.1737, -1.4059, 0.2107], [ 1.3804, -0.5531, 0.6554]], requires_grad=True), Parameter containing: tensor([-0.0266, -0.0338], requires_grad=True)]
model.eval() output = model(x_data) print("실제 값 : {}".format(y_data)) print("예측 값 : {}".format(output))
실제 값 : tensor([[21., 45.], [67., 42.], [82., 91.], [57., 52.], [17., 49.]]) 예측 값 : tensor([[18.4441, 38.7139], [67.6032, 56.1495], [75.9423, 66.8319], [59.8264, 73.1771], [22.7765, 33.5031]], grad_fn=
) 전체코드는 아래 링크에서 확인할 수 있다.
https://github.com/JoSangYeon/Machine_Learning_Project/blob/master/01.%20Linear_regression.ipynb728x90'코딩(Coding) > 기계학습' 카테고리의 다른 글
[기계학습] IRIS 데이터를 분류하는 분류기를 만들어보자(코드 실습) (0) 2022.02.08 [기계학습] 로지스틱 회귀(분류 Classification)(Logistic Regression) (Part 2/2) (0) 2022.01.25 [기계학습] 로지스틱 회귀(분류 Classification)(Logistic Regression) (Part 1/2) (0) 2022.01.21 [기계학습] 선형회귀(Linear Regression) (Part 1/2) (0) 2022.01.11 [기계학습] 기계학습(Machine Learning) 기본 개념 (0) 2022.01.10 - 가설 설정