1. 단항 논리회귀(Logistic Regression)
- 분류를 할 때 사용하며, 선형 회귀 공식으로부터 나왔기 때문에 논리회귀라는 이름이 붙여짐
- 직선 하나(선형 회귀)를 사용해서 분류를 예측한다면 제대로 예측하지 못할 경우가 많음
2. 시그모이드(Sigmoid) 함수
- 예측값을 0에서 1사이의 값이 되도록 만듦
- 0에서 1사이의 연속된 값을 출력으로 하기 때문에 보통 0.5(임계값)를 기준으로 구분
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
torch.manual_seed(2024)
x_train = torch.FloatTensor([[0], [1], [3], [5], [8], [11], [15], [20]])
y_train = torch.FloatTensor([[0], [0], [0], [0], [0], [1], [1], [1]])
print(x_train.shape)
print(y_train.shape)
plt.figure(figsize=(8, 5))
plt.scatter(x_train, y_train)
# Sequential(): Pytorch에서 머신러닝/딥러닝 모델을 만들때
# 여러가지 레이어를 합칠 때 사용하는 메서드
model = nn.Sequential(
nn.Linear(1, 1), # 선형회귀
nn.Sigmoid() # 시그모이드 함수를 거쳐서
)
print(model)
print(list(model.parameters())) # 임의의 값(학습 전)
3. 비용함수
- 논리 회귀에서는 nn.BCELoss() 함수를 사용하여 Loss를 계산
- Binary Cross Entropy
y_pred = model(x_train)
y_pred
loss = nn.BCELoss()(y_pred, y_train)
loss
optimizer = optim.SGD(model.parameters(), lr=0.01)
epochs = 1000
for epoch in range(epochs + 1):
y_pred = model(x_train)
loss = nn.BCELoss()(y_pred, y_train)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 100 == 0:
print(f'Epoch {epoch}/{epoch} Loss: {loss:.6f}')
print(list(model.parameters()))
x_test = torch.FloatTensor([[12]])
y_pred = model(x_test)
print(y_pred)
# 임계치 설정하기
# 0.5보다 크거나 같으면 1
# 0.5보다 작으면 0
y_bool = (y_pred >= 0.5).float()
print(y_bool)
4. 다항 논리회기 실습
x_train = [[1, 2, 1, 1],
[2, 1, 3, 2],
[3, 1, 3, 4],
[4, 1, 5, 5],
[1, 7, 5, 5],
[1, 2, 5, 6],
[1, 6, 6, 6],
[1, 7, 7, 7]]
y_train = [0, 0, 0, 1, 1, 1, 2, 2]
x_train = torch.FloatTensor(x_train)
y_train = torch.LongTensor(y_train)
print(x_train.shape)
print(y_train.shape)
model = nn.Sequential(
nn.Linear(4, 3)
)
print(model)
y_pred = model(x_train)
print(y_pred)
4-1. CrossEntropyLoss
- 교차 엔트로피 손실 함수는 PyTorch에서 제공되는 손실 함수 중 하나로 다중 클래스 분류 문제에서 사용
- 소프트맥스 함수와 교차 엔트로피 손실 함수를 결합한 형태
- 소프트맥스 함수를 적용하여 각 클래스에 대한 확률 분포를 얻음
- 각 클래스에 대한 로그 확률을 계산
- 실제 라벨과 예측 확률의 로그값 간의 차이를 계산
- 계산된 차이의 평균을 계산하여 최종 손실 값을 얻음
4-2. SoftMax
- 다중 클래스 분류 문제에서 사용되는 함수로 주어진 입력 벡터의 값을 확률 분포로 변환
- 각 클래스에 속할 확률을 계산할 수 있으며 각 요소를 0과 1사이의 값으로 변환하여 이 값들의 합은 항상 1이 되도록 함
- 각 입력 값에 대해 지수함수를 적용
- 지수 함수를 적용한 모든 값의 합을 계산한 후, 각 지수 합으로 나누어 정규화를 함
- 정규화를 통해 각 값은 0과 1사이의 확률 값으로 출력
# 다항 논리 회귀에서는 BCELoss() 대신 CrossEntropyLoss()를 사용
# softmax 함수: 클래스의 개수만큼 확률을 반환(0일 확률, 1일 확률, 2일 확률)
loss = nn.CrossEntropyLoss()(y_pred, y_train)
print(loss)
optimizer = optim.SGD(model.parameters(), lr=0.01)
epochs = 1000
for epoch in range(epochs + 1):
y_pred = model(x_train)
loss = nn.CrossEntropyLoss()(y_pred, y_train)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 100 == 0:
print(f'Epoch {epoch}/{epoch} Loss: {loss:.6f}')
x_test = torch.FloatTensor([[1, 7, 8, 7]])
y_pred = model(x_test)
print(y_pred)
# 예측값과 확률 구하기
y_prob = nn.Softmax(1)(y_pred)
y_prob
print(f'0일 확률: {y_prob[0][0]:.2f}')
print(f'1일 확률: {y_prob[0][1]:.2f}')
print(f'2일 확률: {y_prob[0][2]:.2f}')
torch.argmax(y_prob, axis=1)
5. 경사 하강법(Gradient Descent)
5-1. 배치 경사 하강법
- 가장 기본적인 경사 하강법(Vanilla Gradient Descent)
- 데이터셋 전체를 고려하여 손실함수를 계산
- 한 번의 Epoch에 모든 파라미터 업데이트를 단 한번만 수행
- Batch의 개수와 Iteration은 1이고, Batch Size는 전체 데이터의 갯수
- 파라미터 업데이트할 때 한 번에 전체 데이터셋을 고려하기 때문에 모델 학습 시 많은 시간과 메모리가 필요하다는 단점
5-2. 학률적 경사 하강법
- 확률적 경사 하강법(Stochastic Gradient Descent)은 배치 경사 하강법이 모델 학습시 많은 시간과 메모리가 필요하다는 단점을 개선하기 위해 제안된 기법
- Batch Size를 1로 설정하여 파라미터를 업데이트 하기 때문에 배치 경사 하강법보다 훨씬 빠르고 적은 메무리로 학습이 진행
- 파라미터 값의 업데이트 폭이 불안정하기 때문에 정확도가 낮은 경우가 생길 수 있음
5-3. 미니 배치 경사 하강법
- 미니 배치 경사 하강법(Mini-Batch Gradient Descent)은 Batch Size를 설정한 size로 사용하는게 보편적
- 배치 경사 하강법보다 모델 학습 속도가 빠르고, 확률적 경사 하강법보다 안정적인 장점이 있음
- 딥러닝 분야에서 가장 많이 활용되는 경사 하강법
- 일반적으로 Batch size를 32, 64, 128과 같이 2의 n제곱에 해당하는 값을 사용하는게 보편적
6. 경사 하강법의 여러가지 알고리즘
6-1. SGD(확률적 경사 하강법)
- 매개변수 값을 조정 시 전체 데이터가 아니라 랜덤으로 선택한 하나의 데이터에 대해서만 계산하는 방법
6-2. 모멘텀(Momentum)
- 관성이라는 물리학의 법칙을 응용한 방법
- 경사 하강법에 관성을 더 해줌
- 접선의 기울기에 한 시점 이전의 접선의 기울기값을 일정한 비율만큼 반영
6-3. 아다그라드(Adagrad)
- 모든 매개변수에 동일한 학습률(Learning rate)을 적용하는 것은 비효율적이라는 생각에서 만들어진 학습 방법
- 처음에는 크게 학습하다가 조금씩 작게 학습시킴
6-4. SGD(확률적 경사 하강법)
- 모멘텀 + 아다그라드
6-5. SGD(확률적 경사 하강법)
- Adam optimizer의 변형
- Adam의 일부 약점(가중치 감소)과 성능 향상을 위해 고안
7. 와인 품종 예측해보기
- sklearn.datasets.load_wine : 이탈리아의 같은 지역에서 재배된 세가지 다른 품종으로 만든 와인을 화학적으로 분석한 결과에 대한 데이터셋
- 13개의 성분을 분석하여 어떤 와인인지 구별하는 모델을 구축
- 데이터를 섞은 후 train 데이터를 80%, test 데이터를 20%로 하여 사용
- Adam을 사용
- 테스트 데이터의 0번 인덱스가 어떤 와인인지 출력. 정확도를 출력
컬럼명 한글
-------------------------------- -------------------------------------
alcohol 알코올
malic_acid 말산
ash 잔류 성분의 총
alcalinity_of_ash 잔류 성분의
magnesium 마그네슘
total_phenols 총 페놀
flavanoids 플라보노이드
nonflavanoid_phenols 비플라보노이드 페놀
proanthocyanins 프로안토시아닌
color_intensity 색상의
hue 색상의
od280/od315_of_diluted_wines 희석 와인의 OD280/OD315
proline 프롤린
target 와인의 종류를 나타내는 타겟 변수 (0, 1, 2 중 하나의 값)
from sklearn.datasets import load_wine
import pandas as pd
x_data, y_data = load_wine(return_X_y=True, as_frame=True)
x_data
y_data
x_data = torch.FloatTensor(x_data.values)
y_data = torch.LongTensor(y_data.values)
print(x_data.shape)
print(y_data.shape)
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.2, random_state=2024)
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)
model = nn.Sequential(
nn.Linear(13, 3)
)
optimizer = optim.Adam(model.parameters(), lr=0.01)
epochs = 1000
for epoch in range(epochs + 1):
y_pred = model(x_train)
loss = nn.CrossEntropyLoss()(y_pred, y_train)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 100 == 0:
y_prob = nn.Softmax(1)(y_pred)
y_pred_index = torch.argmax(y_prob, axis=1)
y_train_index = y_train
accuracy = (y_train_index == y_pred_index).float().sum() / len(y_train) * 100
print(f'Epoch {epoch:4d}/{epoch} Loss: {loss:.6f} Accuracy: {accuracy:.2f}%')
y_pred = model(x_test)
y_pred[:5]
y_prob = nn.Softmax(1)(y_pred)
y_prob[:5]
print(f'0번 품종일 확률 : {y_prob[0][0]:.2f}')
print(f'1번 품종일 확률 : {y_prob[0][1]:.2f}')
print(f'2번 품종일 확률 : {y_prob[0][2]:.2f}')
Y_pred_index = torch.argmax(y_prob, axis=1)
accuracy = (y_test == y_pred_index).float().sum() / len(y_test) * 100
print(f'테스트 정확도는: {accuracy:.2f}% 입니다')
'머신러닝 & 딥러닝' 카테고리의 다른 글
17. 딥러닝 (0) | 2024.06.13 |
---|---|
16. 데이터 로더 (0) | 2024.06.13 |
14. 파이토치로 구현한 선형회귀 (0) | 2024.06.13 |
13. 파이토치(Pytorch) (0) | 2024.06.13 |
12. KMeans (0) | 2024.06.13 |