코딩(Coding)/기계학습
[기계학습] 로지스틱 회귀(분류 Classification)(Logistic Regression) (Part 2/2)
J.S.Y
2022. 1. 25. 22:17
728x90
이전 포스팅의 개념적인 부분을 python의 pytorch 패키지를 통해 구현하는 포스팅입니다.
이전 포스팅을 보고오세요~ :D (https://jsy-coding-blog.tistory.com/47)
포스팅에서 사용하는 PPT 자료는 제 Github에서 pdf 형식으로 받을 수 있습니다.
(https://github.com/JoSangYeon/Machine_Learning_Project/blob/master/PPT/01.%20Machine%20Learning.pdf)
Logistic Regression
분류 문제
지난 포스팅 복습
코드 실습(With Pytorch)
패키지 Import
import numpy as np
import pandas as pd
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
print(torch.__version__)
1.10.1
예제 Data 생성
# 예제
x_data = [[0],[2],[1],[9],[10]]
y_data = [[0],[0],[0],[1],[1]]
X = torch.tensor(np.array(x_data)).float()
Y = torch.tensor(np.array(y_data)).float()
print(X)
print(Y)
tensor([[ 0.],
[ 2.],
[ 1.],
[ 9.],
[10.]])
tensor([[0.],
[0.],
[0.],
[1.],
[1.]])
예제로 사용할 데이터는 간단하게 PPT에서 봤던 데이터이다.
x가 0
5이면 Y는 0이고 5
10이면 Y는 1이다.
Model 정의(가설 정의)
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.fc1 = nn.Linear(1, 1)
self.act_fn = nn.Sigmoid()
def forward(self, input):
x = self.fc1(input)
x = self.act_fn(x)
return x
model = MyModel()
opt = optim.Adam(model.parameters())
loss_fn = nn.BCELoss()
print(model)
MyModel(
(fc1): Linear(in_features=1, out_features=1, bias=True)
(act_fn): Sigmoid()
)
모델은 간단하게 nn.Module로 sub-Classing하였다.
모델의 연산은 다음과 같다.(forward() 메소드 참고)
- input_Node : 1, output_Node : 1인 Linear Layer를 정의한다.
- 해당 Linear Layer의 output을 Sigmoid 함수에 대입한다.
모델 학습
# 학습
model.train()
for epoch in range(1, 1001):
x, y = X, Y
opt.zero_grad()
output = model(x)
loss = loss_fn(output, y)
loss.backward()
opt.step()
if epoch % 25 == 0:
print("EPOCH {} >>> Loss : {:.5f}".format(epoch, loss))
EPOCH 25 >>> Loss : 0.96217
EPOCH 50 >>> Loss : 0.93793
EPOCH 75 >>> Loss : 0.91404
EPOCH 100 >>> Loss : 0.89053
EPOCH 125 >>> Loss : 0.86741
EPOCH 150 >>> Loss : 0.84471
EPOCH 175 >>> Loss : 0.82245
EPOCH 200 >>> Loss : 0.80066
EPOCH 225 >>> Loss : 0.77935
EPOCH 250 >>> Loss : 0.75858
EPOCH 275 >>> Loss : 0.73837
EPOCH 300 >>> Loss : 0.71877
EPOCH 325 >>> Loss : 0.69983
EPOCH 350 >>> Loss : 0.68159
EPOCH 375 >>> Loss : 0.66413
EPOCH 400 >>> Loss : 0.64750
EPOCH 425 >>> Loss : 0.63176
EPOCH 450 >>> Loss : 0.61699
EPOCH 475 >>> Loss : 0.60323
EPOCH 500 >>> Loss : 0.59052
EPOCH 525 >>> Loss : 0.57887
EPOCH 550 >>> Loss : 0.56828
EPOCH 575 >>> Loss : 0.55868
EPOCH 600 >>> Loss : 0.55000
EPOCH 625 >>> Loss : 0.54213
EPOCH 650 >>> Loss : 0.53493
EPOCH 675 >>> Loss : 0.52826
EPOCH 700 >>> Loss : 0.52201
EPOCH 725 >>> Loss : 0.51606
EPOCH 750 >>> Loss : 0.51033
EPOCH 775 >>> Loss : 0.50475
EPOCH 800 >>> Loss : 0.49927
EPOCH 825 >>> Loss : 0.49388
EPOCH 850 >>> Loss : 0.48854
EPOCH 875 >>> Loss : 0.48325
EPOCH 900 >>> Loss : 0.47801
EPOCH 925 >>> Loss : 0.47280
EPOCH 950 >>> Loss : 0.46764
EPOCH 975 >>> Loss : 0.46251
EPOCH 1000 >>> Loss : 0.45743
Loss가 순차적으로 줄어든 것을 볼 수 있다.
성능 검증
# 성능 검증
# X, Y를 그대로 넣어서 제대로 분류하는 확인
def decision_boundary(output):
return (output >= torch.tensor([0.5])).float()
model.eval()
output = model(X)
output = decision_boundary(output)
print("모델이 예측한 값 :",output.view(-1))
print("실제 값 : ", Y.view(-1))
print("정확도 : {}%".format(((output == Y).view(-1).sum() / 5. * 100.).item()))
모델이 예측한 값 : tensor([0., 1., 0., 1., 1.])
실제 값 : tensor([0., 0., 0., 1., 1.])
정확도 : 80.0%
1000번을 학습하고 기존의 X,Y를 대입해보았다.
Train 데이터에 대해서 정확도는 80%(5개중 4개 맞았다.)
새로운 데이터가 추가 되었다.
데이터 정의
# 예제
x_data = [[0],[2],[1],[9],[10],[20],[5]]
y_data = [[0],[0],[0],[1],[1], [1], [0]]
X = torch.tensor(np.array(x_data)).float()
Y = torch.tensor(np.array(y_data)).float()
print(X)
print(Y)
tensor([[ 0.],
[ 2.],
[ 1.],
[ 9.],
[10.],
[20.],
[ 5.]])
tensor([[0.],
[0.],
[0.],
[1.],
[1.],
[1.],
[0.]])
모델 정의
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.fc1 = nn.Linear(1, 1)
self.act_fn = nn.Sigmoid()
def forward(self, input):
x = self.fc1(input)
x = self.act_fn(x)
return x
model = MyModel()
opt = optim.Adam(model.parameters())
loss_fn = nn.BCELoss()
print(model)
MyModel(
(fc1): Linear(in_features=1, out_features=1, bias=True)
(act_fn): Sigmoid()
)
학습
# 학습
model.train()
for epoch in range(1, 1001):
x, y = X, Y
opt.zero_grad()
output = model(x)
loss = loss_fn(output, y)
loss.backward()
opt.step()
if epoch % 25 == 0:
print("EPOCH {} >>> Loss : {:.5f}".format(epoch, loss))
EPOCH 25 >>> Loss : 0.87950
EPOCH 50 >>> Loss : 0.80764
EPOCH 75 >>> Loss : 0.74866
EPOCH 100 >>> Loss : 0.70152
EPOCH 125 >>> Loss : 0.66421
EPOCH 150 >>> Loss : 0.63451
EPOCH 175 >>> Loss : 0.61047
EPOCH 200 >>> Loss : 0.59060
EPOCH 225 >>> Loss : 0.57378
EPOCH 250 >>> Loss : 0.55923
EPOCH 275 >>> Loss : 0.54639
EPOCH 300 >>> Loss : 0.53487
EPOCH 325 >>> Loss : 0.52439
EPOCH 350 >>> Loss : 0.51474
EPOCH 375 >>> Loss : 0.50575
EPOCH 400 >>> Loss : 0.49733
EPOCH 425 >>> Loss : 0.48937
EPOCH 450 >>> Loss : 0.48181
EPOCH 475 >>> Loss : 0.47461
EPOCH 500 >>> Loss : 0.46770
EPOCH 525 >>> Loss : 0.46107
EPOCH 550 >>> Loss : 0.45468
EPOCH 575 >>> Loss : 0.44851
EPOCH 600 >>> Loss : 0.44254
EPOCH 625 >>> Loss : 0.43676
EPOCH 650 >>> Loss : 0.43114
EPOCH 675 >>> Loss : 0.42569
EPOCH 700 >>> Loss : 0.42038
EPOCH 725 >>> Loss : 0.41521
EPOCH 750 >>> Loss : 0.41017
EPOCH 775 >>> Loss : 0.40525
EPOCH 800 >>> Loss : 0.40046
EPOCH 825 >>> Loss : 0.39577
EPOCH 850 >>> Loss : 0.39119
EPOCH 875 >>> Loss : 0.38672
EPOCH 900 >>> Loss : 0.38234
EPOCH 925 >>> Loss : 0.37805
EPOCH 950 >>> Loss : 0.37385
EPOCH 975 >>> Loss : 0.36974
EPOCH 1000 >>> Loss : 0.36571
성능 검증
# 성능 검증
# X, Y를 그대로 넣어서 제대로 분류하는 확인
def decision_boundary(output):
return (output >= torch.tensor([0.5])).float()
model.eval()
output = model(X)
output = decision_boundary(output)
print("모델이 예측한 값 :",output.view(-1))
print("실제 값 : ", Y.view(-1))
print("정확도 : {:.2f}%".format(((output == Y).view(-1).sum() / 7. * 100.).item()))
모델이 예측한 값 : tensor([0., 0., 0., 1., 1., 1., 1.])
실제 값 : tensor([0., 0., 0., 1., 1., 1., 0.])
정확도 : 85.71%
다변수 회귀 분류
PPT 복습
학습 데이터 정의
# 예제
x_data = [[1.2, 3.4],[1.1, 3.2],[1.5, 3.7],
[5.2, 0.7],[4.7, 0.6],[5.6, 0.9],
[7.7, 6.6],[7.5, 7.2],[8.1, 6.2]]
y_data = [0,0,0,
1,1,1,
2,2,2]
X = torch.tensor(x_data)
Y = torch.tensor(y_data)
print(X)
print(Y)
tensor([[1.2000, 3.4000],
[1.1000, 3.2000],
[1.5000, 3.7000],
[5.2000, 0.7000],
[4.7000, 0.6000],
[5.6000, 0.9000],
[7.7000, 6.6000],
[7.5000, 7.2000],
[8.1000, 6.2000]])
tensor([0, 0, 0, 1, 1, 1, 2, 2, 2])
Feature는 2개이고 Label은 1이다.
Label : One-Hot Encoding
# Label을 3개의 클래스를 가지도록 one-hot encoding 해줌
Y = F.one_hot(Y, num_classes=3).float()
Y
tensor([[1., 0., 0.],
[1., 0., 0.],
[1., 0., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]])
3개의 Y값을 가지기 때문에, One-Hot Encoding을 통해 label값을 변경해준다.
모델 정의
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.fc1 = nn.Linear(2, 3)
self.act_fn = nn.Softmax(dim=1)
def forward(self, input):
x = self.fc1(input)
x = self.act_fn(x)
return x
model = MyModel()
opt = optim.Adam(model.parameters())
loss_fn = nn.CrossEntropyLoss()
print(model)
MyModel(
(fc1): Linear(in_features=2, out_features=3, bias=True)
(act_fn): Softmax(dim=1)
)
모델은 다음과 같다.
- input_Node : 2, output_Node 3을 가지는 Linear Layer를 정의한다.
- Linear Layer의 결과값을 softmax함수에 대입하여 확률값으로 변환한다.
- 각 노드의 값은 해당 input이 해당 Label일 확률을 의미한다.
- 최적화 알고리즘은 Adam을 사용했고, 오차함수는 Cross-Entropy이다.
학습
# 학습
model.train()
for epoch in range(1, 1501):
x, y = X, Y
opt.zero_grad()
output = model(x)
loss = loss_fn(output, y)
loss.backward()
opt.step()
if epoch % 25 == 0:
print("EPOCH {} >>> Loss : {:.5f}".format(epoch, loss))
EPOCH 25 >>> Loss : 1.02031
EPOCH 50 >>> Loss : 1.00895
EPOCH 75 >>> Loss : 0.99802
EPOCH 100 >>> Loss : 0.98769
EPOCH 125 >>> Loss : 0.97803
EPOCH 150 >>> Loss : 0.96896
EPOCH 175 >>> Loss : 0.96031
EPOCH 200 >>> Loss : 0.95159
EPOCH 225 >>> Loss : 0.94148
EPOCH 250 >>> Loss : 0.92642
EPOCH 275 >>> Loss : 0.90064
EPOCH 300 >>> Loss : 0.86479
EPOCH 325 >>> Loss : 0.82898
EPOCH 350 >>> Loss : 0.79900
EPOCH 375 >>> Loss : 0.77486
EPOCH 400 >>> Loss : 0.75522
EPOCH 425 >>> Loss : 0.73892
EPOCH 450 >>> Loss : 0.72510
EPOCH 475 >>> Loss : 0.71318
EPOCH 500 >>> Loss : 0.70275
EPOCH 525 >>> Loss : 0.69351
EPOCH 550 >>> Loss : 0.68525
EPOCH 575 >>> Loss : 0.67780
EPOCH 600 >>> Loss : 0.67103
EPOCH 625 >>> Loss : 0.66486
EPOCH 650 >>> Loss : 0.65920
EPOCH 675 >>> Loss : 0.65399
EPOCH 700 >>> Loss : 0.64917
EPOCH 725 >>> Loss : 0.64471
EPOCH 750 >>> Loss : 0.64056
EPOCH 775 >>> Loss : 0.63669
EPOCH 800 >>> Loss : 0.63309
EPOCH 825 >>> Loss : 0.62971
EPOCH 850 >>> Loss : 0.62654
EPOCH 875 >>> Loss : 0.62357
EPOCH 900 >>> Loss : 0.62078
EPOCH 925 >>> Loss : 0.61815
EPOCH 950 >>> Loss : 0.61567
EPOCH 975 >>> Loss : 0.61332
EPOCH 1000 >>> Loss : 0.61111
EPOCH 1025 >>> Loss : 0.60901
EPOCH 1050 >>> Loss : 0.60702
EPOCH 1075 >>> Loss : 0.60513
EPOCH 1100 >>> Loss : 0.60334
EPOCH 1125 >>> Loss : 0.60164
EPOCH 1150 >>> Loss : 0.60002
EPOCH 1175 >>> Loss : 0.59847
EPOCH 1200 >>> Loss : 0.59700
EPOCH 1225 >>> Loss : 0.59560
EPOCH 1250 >>> Loss : 0.59426
EPOCH 1275 >>> Loss : 0.59298
EPOCH 1300 >>> Loss : 0.59175
EPOCH 1325 >>> Loss : 0.59058
EPOCH 1350 >>> Loss : 0.58946
EPOCH 1375 >>> Loss : 0.58838
EPOCH 1400 >>> Loss : 0.58735
EPOCH 1425 >>> Loss : 0.58636
EPOCH 1450 >>> Loss : 0.58541
EPOCH 1475 >>> Loss : 0.58449
EPOCH 1500 >>> Loss : 0.58361
1500번 학습을 하였고, Loss는 순차적으로 잘 줄어든 것을 볼 수 있다.
성능 검증
# 성능 검증
# X, Y를 그대로 넣어서 제대로 분류하는 확인
def calc_acc(output, y):
p_m_val, p_m_idx = torch.max(output, dim=1)
y_m_val, y_m_idx = torch.max(y, dim=1)
return (p_m_idx == y_m_idx).sum()
model.eval()
output = model(X)
acc = calc_acc(output, Y)
print("모델이 예측한 값 :",output)
print("실제 값 : ", Y)
print("정확도 : {:.2f}%".format(acc / 9. * 100.))
모델이 예측한 값 : tensor([[9.4259e-01, 2.4447e-03, 5.4970e-02],
[9.4027e-01, 3.1480e-03, 5.6586e-02],
[9.3180e-01, 2.2921e-03, 6.5911e-02],
[9.0985e-05, 9.5731e-01, 4.2603e-02],
[2.1392e-04, 9.5028e-01, 4.9503e-02],
[6.0590e-05, 9.5549e-01, 4.4447e-02],
[1.0728e-02, 2.2483e-02, 9.6679e-01],
[2.6211e-02, 8.5016e-03, 9.6529e-01],
[3.7751e-03, 4.9346e-02, 9.4688e-01]], grad_fn=<SoftmaxBackward0>)
실제 값 : tensor([[1., 0., 0.],
[1., 0., 0.],
[1., 0., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]])
정확도 : 100.00%
학습했던 데이터에 대해서 정확도는 100%가 나왔다.
물론 과적합일 수도 있지만, 이는 코드 실습에 의의를 두고 싶다.
다음 포스팅에서는 흔한 IRIS 데이터를 통한 실습 프로젝트를 진행하고자 한다.
728x90