2025. 1. 8. 16:41ㆍLLM(Large Language Model)의 기초/데이터 분석
1. 논리 회귀(Logistic Regression)
* 논리 회귀(Logistic Regression)는 주어진 입력 데이터를 기반으로 두 가지 이상의 범주로 분류하는 지도 학습 알고리즘입니다.
* 주로 이진 분류 문제에 사용되며, 입력 변수의 선형 결합을 통해 특정 사건이 발생할 확률을 예측합니다.
* 이 알고리즘은 시그모이드(Sigmoid) 함수 또는 로지스틱 함수라는 비선형 함수를 사용하여 예측값을 0과 1 사이의 확률로 변환합니다.
* 모델의 결과는 일반적으로 특정 임계값(예: 0.5)을 기준으로 두 범주 중 하나로 분류됩니다.
* 예를 들어, 이메일이 스팸인지 아닌지를 판별하거나 환자의 병 진단 여부를 예측하는 데 사용될 수 있습니다.
* 논리 회귀는 계산이 비교적 간단하고 해석이 용이하여 머신러닝에서 널리 사용되는 알고리즘입니다.
2. 시그모이드 함수(Sigmoid Function)
* 시그모이드 함수(Sigmoid Function)는 입력 값을 받아서 이를 0과 1 사이의 값으로 변환하는 수학 함수입니다.
* 주로 확률을 예측해야 하는 문제에서 사용됩니다.
* 논리 회귀(Logistic Regression)와 인공신경망(Artificial Neural Network)에서 매우 중요한 역할을 합니다. (e: 자연 상수로, 약 2.718입니다.)
2. 단항 논리 회귀(Univariate Logistic Regression)
* 단항 논리 회귀 (Univariate Logistic Regression)는 하나의 독립 변수(입력 변수)를 사용하여 이진 분류 문제를 해결하는 논리 회귀(Logistic Regression)의 한 형태입니다.
* 예를 들어, 학생의 하루 공부 시간(독립 변수)에 따라 시험 합격 여부(종속 변수: 합격/불합격)를 예측하는 경우가 여기에 해당합니다.
* 단항 논리 회귀는 입력 변수의 값을 시그모이드(Sigmoid) 함수에 전달하여 해당 사건(예: 합격)이 발생할 확률(0과 1 사이의 값)을 계산합니다.
* 이후 이 확률 값이 특정 임계값(일반적으로 0.5)을 초과하면 한 클래스로, 그렇지 않으면 다른 클래스로 분류합니다.
* 단항 논리 회귀는 간단하면서도 직관적이어서 이진 분류 문제를 설명하고 해석하는 데 자주 사용됩니다.
1. 파이토치를 import 해줍니다.
예시 1)
import torch
import torch.nn as nn
x = torch.tensor([1.0, 2.0, 3.0])
w = torch.tensor([0.1, 0.2, 0.3])
b = torch.tensor(0.5)
# z = W1*x1 + W2*x2 + W3*x3 + b
# z = 0.1*1.0 + 0.2*2.0 + 0.3* 3.0 + 0.5
0.1*1.0 + 0.2*2.0 + 0.3* 3.0 + 0.5
-->
1.9
--->
# PyTorch 라이브러리를 임포트합니다.
# torch: PyTorch의 주요 모듈로 텐서를 다룰 수 있습니다.
# torch.nn: 신경망 모듈을 위한 PyTorch 서브모듈로, 다양한 레이어와 함수들을 제공합니다.
import torch
import torch.nn as nn
# 입력 데이터 x를 정의합니다.
# torch.tensor([1.0, 2.0, 3.0]):
# - [1.0, 2.0, 3.0] 값을 가지는 1D 텐서를 생성합니다.
# - 실수(float)형 데이터를 정의하기 위해 각 값 뒤에 ".0"을 붙였습니다.
x = torch.tensor([1.0, 2.0, 3.0])
# 가중치 w를 정의합니다.
# torch.tensor([0.1, 0.2, 0.3]):
# - [0.1, 0.2, 0.3] 값을 가지는 1D 텐서를 생성합니다.
# - 이 값들은 입력 데이터 x와 동일한 차원을 가져야 하며, 각 입력에 대한 가중치를 나타냅니다.
w = torch.tensor([0.1, 0.2, 0.3])
# 편향 b를 정의합니다.
# torch.tensor(0.5):
# - 스칼라 값(0.5)을 가지는 텐서를 생성합니다.
# - 편향은 입력 데이터와 독립적으로 적용되는 상수입니다.
b = torch.tensor(0.5)
예시 2)
z = torch.dot(w, x) + b
print(z)
---->
tensor(1.9000)
----------------------------------------------------------
# 입력 데이터와 가중치의 내적(dot product)을 계산하고, 편향을 더합니다.
# torch.dot(w, x):
# - w와 x의 내적(점곱)을 계산합니다.
# - 점곱은 같은 차원을 가진 두 벡터의 원소별 곱의 합을 계산하는 연산입니다.
# (w[0] * x[0] + w[1] * x[1] + w[2] * x[2])
# => (0.1 * 1.0) + (0.2 * 2.0) + (0.3 * 3.0) = 0.1 + 0.4 + 0.9 = 1.4
# + b:
# - 편향 b(0.5)를 내적 결과에 더합니다.
# - 결과: 1.4 + 0.5 = 1.9
z = torch.dot(w, x) + b
# 계산된 결과를 출력합니다.
# 출력값은 텐서 형식으로 나타나며, 값은 1.9입니다.
print(z) # 출력: tensor(1.9000)
예시 3)
sigmoid = nn.Sigmoid()
output = sigmoid(z)
output
--->
# PyTorch의 Sigmoid 활성화 함수를 생성합니다.
# nn.Sigmoid()는 입력값을 0과 1 사이로 변환하는 활성화 함수입니다.
# 활성화 함수는 신경망의 비선형성을 도입하는 역할을 합니다.
sigmoid = nn.Sigmoid()
# z 값을 Sigmoid 함수에 통과시켜 출력값을 계산합니다.
# sigmoid(z): Sigmoid 함수는 다음 수식을 사용합니다:
# sigmoid(z) = 1 / (1 + exp(-z))
# z = 1.9일 때:
# sigmoid(1.9) = 1 / (1 + exp(-1.9))
output = sigmoid(z)
# Sigmoid 함수의 결과(출력값)를 반환합니다.
# 출력값은 0과 1 사이의 값이며, 텐서 형식으로 반환됩니다.
output
--->
tensor(0.8699)
예시 4)
import torch.optim as optim
import matplotlib.pyplot as plt
torch.manual_seed(2025)
x_train = torch.FloatTensor([[0], [1], [3], [5], [8], [11], [15], [20]])
y_train = torch.FloatTensor([[0], [0], [0], [0], [1], [1], [1], [1]])
print(x_train.shape)
print(y_train.shape)
---->
# PyTorch의 옵티마이저 모듈과 Matplotlib 라이브러리를 임포트합니다.
# - torch.optim: PyTorch에서 모델 학습을 위한 다양한 최적화 알고리즘을 제공하는 모듈.
# - matplotlib.pyplot: 데이터 시각화를 위한 그래프 생성 라이브러리.
import torch.optim as optim
import matplotlib.pyplot as plt
# PyTorch의 랜덤 시드를 고정합니다.
# - torch.manual_seed(2025): 랜덤 시드 값을 2025로 고정하여 실행 결과의 재현성을 보장합니다.
torch.manual_seed(2025)
# 학습 데이터를 생성합니다.
# - x_train: 입력 데이터로, 1D 텐서 형태의 특성을 2D 텐서로 변환하여 저장합니다 (각 샘플의 특성 값이 하나씩 포함).
# - FloatTensor: 실수(float)형 데이터를 텐서로 변환합니다.
x_train = torch.FloatTensor([[0], [1], [3], [5], [8], [11], [15], [20]])
# 출력 데이터를 생성합니다.
# - y_train: 출력 데이터로, 입력 값에 따라 이진 값(0 또는 1)으로 구성됩니다.
y_train = torch.FloatTensor([[0], [0], [0], [0], [1], [1], [1], [1]])
# 학습 데이터와 출력 데이터의 텐서 모양(shape)을 출력합니다.
# - .shape: 텐서의 크기를 반환합니다.
# x_train.shape: (8, 1) - 8개의 샘플, 각 샘플에 하나의 특성 값.
# y_train.shape: (8, 1) - 8개의 샘플, 각 샘플에 하나의 출력 값.
print(x_train.shape)
print(y_train.shape)
--->
torch.Size([8, 1])
torch.Size([8, 1])
예시 5)
# 그래프의 크기를 설정합니다.
# figsize=(8, 5): 그래프의 가로 크기를 8인치, 세로 크기를 5인치로 설정합니다.
plt.figure(figsize=(8, 5))
# 입력 데이터(x_train)와 출력 데이터(y_train)를 산점도로 시각화합니다.
# plt.scatter(x_train, y_train):
# - x_train: x축에 표시될 입력 데이터.
# - y_train: y축에 표시될 출력 데이터.
# 산점도는 데이터의 분포를 점으로 나타내는 데 사용됩니다.
plt.scatter(x_train, y_train)
--->
<matplotlib.collections.PathCollection at 0x78e9b7b498a0>
--->
예시 6)
# 신경망 모델을 생성합니다.
# nn.Sequential(): 여러 레이어를 순차적으로 연결하여 신경망을 구성하는 PyTorch 클래스입니다.
model = nn.Sequential(
# nn.Linear(1, 1): 입력 크기 1, 출력 크기 1인 선형 계층(fully connected layer)을 추가합니다.
# - 입력 데이터의 특성 수는 1 (x_train은 1차원).
# - 출력 데이터의 크기는 1 (y_train은 1차원).
nn.Linear(1, 1),
# nn.Sigmoid(): 선형 계층의 출력을 Sigmoid 활성화 함수로 변환합니다.
# - Sigmoid 함수는 출력값을 0과 1 사이의 확률로 압축하는 비선형 활성화 함수입니다.
nn.Sigmoid()
)
# 생성된 모델 구조를 출력합니다.
model
--->
Sequential(
(0): Linear(in_features=1, out_features=1, bias=True)
(1): Sigmoid()
)
예시 7)
# 모델의 학습 가능한 파라미터(가중치와 편향)를 리스트로 확인합니다.
# model.parameters(): PyTorch 모델에서 학습 가능한 모든 파라미터(가중치와 편향)를 반환합니다.
# - nn.Linear 계층의 가중치(weight)와 편향(bias)가 포함됩니다.
# list(): 반환된 파라미터들을 리스트 형태로 변환하여 확인할 수 있습니다.
list(model.parameters())
--->
[Parameter containing:
tensor([[0.3699]], requires_grad=True),
Parameter containing:
tensor([0.8711], requires_grad=True)]
예시 8)
# 학습 데이터 x_train을 모델에 입력하여 예측값을 계산합니다.
# model(x_train):
# - 모델의 순전파(forward pass) 연산을 수행합니다.
# - 입력 데이터 x_train이 모델의 각 계층(nn.Linear, nn.Sigmoid)을 통과하며 출력값(y_pred)을 계산합니다.
y_pred = model(x_train)
# 모델의 예측값을 확인합니다.
# y_pred는 모델이 학습 데이터에 대해 계산한 예측 결과입니다.
# 출력은 텐서 형식이며, 각 값은 0과 1 사이의 실수로 나타납니다 (Sigmoid 함수의 결과).
y_pred
--->
tensor([[0.7050],
[0.7757],
[0.8788],
[0.9382],
[0.9788],
[0.9929],
[0.9984],
[0.9997]], grad_fn=<SigmoidBackward0>)
BCE 손실 함수(Binary Cross Entropy)
* Binary Cross Entropy (BCE)는 이진 분류 문제에서 모델이 예측한 확률 분포와 실제 정답 레이블 사이의 차이를 측정하는 손실 함수(Loss Function)입니다.
* BCE는 예측된 확률 값과 실제 값(0 또는 1) 사이의 차이를 로그 확률로 변환하여 손실을 계산합니다.
예시 1)
# 손실 함수로 이진 교차 엔트로피(Binary Cross Entropy) 손실을 계산합니다.
# nn.BCELoss(): PyTorch에서 제공하는 이진 교차 엔트로피 손실 함수.
# - BCELoss는 예측값(y_pred)과 실제값(y_train) 간의 차이를 계산합니다.
# - 입력값(y_pred)은 Sigmoid 활성화 함수의 출력을 받아야 합니다 (0~1 사이의 값).
# - 수식:
# 손실 = -[y_train * log(y_pred) + (1 - y_train) * log(1 - y_pred)]
# 이는 확률 기반의 분류 문제에서 일반적으로 사용됩니다.
# (y_pred, y_train):
# - y_pred: 모델이 예측한 확률 (0과 1 사이의 값).
# - y_train: 실제 정답값 (0 또는 1로 구성된 값).
loss = nn.BCELoss()(y_pred, y_train)
# 계산된 손실값을 출력합니다.
# - tensor(0.9551): 손실값으로, 모델의 예측이 얼마나 실제값과 다른지 나타냅니다.
# - grad_fn=<BinaryCrossEntropyBackward0>: 손실값이 역전파(backward pass)에 사용될 수 있음을 나타냅니다.
loss
--->
tensor(0.9551, grad_fn=<BinaryCrossEntropyBackward0>)
예시 2)
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}/{epochs} Loss: {loss:.6f}')
--->
# 모델 학습을 위한 최적화 알고리즘(optimizer)을 설정합니다.
# optim.SGD: 확률적 경사하강법(Stochastic Gradient Descent)을 사용합니다.
# model.parameters(): 모델의 학습 가능한 파라미터(가중치와 편향)를 최적화합니다.
# lr=0.01: 학습률(learning rate)을 0.01로 설정합니다.
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 학습을 반복할 횟수(epochs)를 설정합니다.
epochs = 1000
# 학습 루프를 실행합니다.
for epoch in range(epochs + 1): # 0부터 epochs(1000)까지 총 1001번 반복.
# 1. 모델의 예측값을 계산합니다 (순전파, forward pass).
# x_train을 모델에 입력하여 y_pred를 계산합니다.
y_pred = model(x_train)
# 2. 손실(loss)을 계산합니다.
# nn.BCELoss()(y_pred, y_train): 예측값(y_pred)과 실제값(y_train) 간의 이진 교차 엔트로피 손실을 계산합니다.
loss = nn.BCELoss()(y_pred, y_train)
# 3. 경사값(gradient)을 초기화합니다.
# optimizer.zero_grad(): 이전 반복(epoch)에서 계산된 경사를 초기화합니다.
optimizer.zero_grad()
# 4. 역전파(backward pass)를 수행합니다.
# loss.backward(): 손실(loss)에 대한 모델 파라미터의 경사를 계산합니다.
loss.backward()
# 5. 모델 파라미터를 업데이트합니다.
# optimizer.step(): 계산된 경사를 바탕으로 가중치와 편향을 업데이트합니다.
optimizer.step()
# 6. 매 100번째 epoch마다 학습 상태를 출력합니다.
# epoch % 100 == 0: 현재 epoch이 100으로 나누어떨어질 때마다 실행.
# f'Epoch: {epoch}/{epochs} Loss: {loss:.6f}': 현재 epoch과 손실 값을 출력합니다.
if epoch % 100 == 0:
print(f'Epoch: {epoch}/{epochs} Loss: {loss:.6f}')
---->
Epoch: 0/1000 Loss: 0.955088
Epoch: 100/1000 Loss: 0.656269
Epoch: 200/1000 Loss: 0.587461
Epoch: 300/1000 Loss: 0.529375
Epoch: 400/1000 Loss: 0.480471
Epoch: 500/1000 Loss: 0.439265
Epoch: 600/1000 Loss: 0.404423
Epoch: 700/1000 Loss: 0.374805
Epoch: 800/1000 Loss: 0.349462
Epoch: 900/1000 Loss: 0.327626
Epoch: 1000/1000 Loss: 0.308673
예시 3)
# 학습이 완료된 후 모델의 학습 가능한 파라미터(가중치와 편향)를 확인합니다.
# model.parameters(): 모델의 모든 학습 가능한 파라미터를 반환합니다.
# - nn.Linear 계층의 가중치(weight)와 편향(bias)가 포함됩니다.
# list(): 반환된 파라미터를 리스트 형태로 변환하여 확인할 수 있습니다.
list(model.parameters())
--->
[Parameter containing:
tensor([[0.2780]], requires_grad=True),
Parameter containing:
tensor([-1.1653], requires_grad=True)]
예시 4)
# 새로운 입력값 x_test를 생성합니다.
# torch.FloatTensor([[10]]):
# - 입력 데이터로 [10]을 가지는 2D 텐서를 생성합니다.
# - FloatTensor는 실수(float)형 텐서를 만듭니다.
x_test = torch.FloatTensor([[10]])
# 모델을 사용하여 x_test에 대한 예측값을 계산합니다.
# model(x_test):
# - x_test를 모델에 입력하여 순전파(forward pass)를 수행합니다.
# - 모델은 다음 연산을 수행합니다:
# 1. 선형 계층(nn.Linear): z = w * x + b
# 2. Sigmoid 활성화(nn.Sigmoid): y_pred = 1 / (1 + exp(-z))
y_pred = model(x_test)
# 예측값(y_pred)을 확인합니다.
# y_pred는 0과 1 사이의 값으로 출력되며, 로지스틱 회귀 모델의 확률 값처럼 해석할 수 있습니다.
y_pred
--->
tensor([[0.8341]], grad_fn=<SigmoidBackward0>)
예시 5)
# 임계치 설정하기
# 0.5 보다 크거나 같으면 1
# 0.5 보다 작으면 0
y_bool = (y_pred >= 0.5).float()
y_bool
--->
tensor([[1.]])
3.다항 논리 회귀(Multinomial Logistic Regression)
* 다항 논리 회귀(Multinomial Logistic Regression)는 종속 변수가 세 개 이상의 범주로 나뉘는 다중 클래스 분류 문제를 해결하는 알고리즘입니다.
* 예를 들어, 과일의 색깔이 빨강, 노랑, 초록 중 하나로 분류되는 문제에서 사용할 수 있습니다.
* 이 알고리즘은 각 클래스에 대한 확률을 예측하기 위해 소프트맥스(Softmax) 함수를 사용합니다.
* 소프트맥스 함수는 각 클래스에 속할 확률을 0과 1 사이의 값으로 변환하며, 모든 클래스의 확률 합이 1이 되도록 정규화합니다.
* 모델은 입력 데이터가 특정 클래스에 속할 가능성을 계산한 뒤, 가장 높은 확률을 가진 클래스를 최종 예측 값으로 선택합니다.
* 다항 논리 회귀는 자연어 처리, 이미지 분류, 그리고 다양한 다중 클래스 분류 문제에서 널리 사용됩니다.
예시 1)
# 학습 데이터 X_train을 리스트로 정의합니다.
# - 각 샘플은 4개의 특성(feature) 값을 가집니다.
# - 총 10개의 샘플로 구성되어 있습니다.
X_train = [[1, 2, 1, 1],
[2, 1, 3, 2],
[3, 1, 3, 4],
[4, 2, 5, 5],
[1, 6, 5, 5],
[1, 4, 5, 8],
[1, 7, 7, 7],
[2, 8, 7, 8],
[2, 7, 6, 7],
[2, 6, 6, 6]]
# 학습 데이터의 레이블 y_train을 리스트로 정의합니다.
# - 각 샘플의 레이블은 0, 1, 2 중 하나로 구성됩니다.
# - 총 10개의 샘플에 대해 각각 레이블이 지정되어 있습니다.
y_train = [0, 0, 0, 1, 1, 1, 2, 2, 2, 2] # 클래스가 3개 (0, 1, 2)
# X_train을 PyTorch의 FloatTensor로 변환합니다.
# - FloatTensor는 실수형 텐서를 생성합니다.
X_train = torch.FloatTensor(X_train)
# y_train을 PyTorch의 LongTensor로 변환합니다.
# - LongTensor는 정수형 텐서를 생성하며, 분류 문제에서 레이블로 사용됩니다.
y_train = torch.LongTensor(y_train)
# X_train의 텐서 크기를 출력합니다.
# - torch.Size([10, 4]): 10개의 샘플, 각 샘플에 4개의 특성이 포함되어 있음을 나타냅니다.
print(X_train.shape)
# y_train의 텐서 크기를 출력합니다.
# - torch.Size([10]): 10개의 샘플에 대해 하나의 레이블(정답값)이 지정되어 있음을 나타냅니다.
print(y_train.shape)
--->
torch.Size([10, 4])
torch.Size([10])
예시 2)
# 신경망 모델을 생성합니다.
# nn.Sequential(): 여러 레이어를 순차적으로 연결하여 신경망을 구성하는 PyTorch 클래스입니다.
model = nn.Sequential(
# nn.Linear(4, 3): 입력 크기 4, 출력 크기 3인 선형 계층(fully connected layer)을 추가합니다.
# - 입력 데이터의 특성 수는 4 (X_train은 4개의 특성으로 구성).
# - 출력 데이터의 크기는 3 (클래스가 3개: 0, 1, 2).
nn.Linear(4, 3)
)
# 생성된 모델 구조를 출력합니다.
model
---->
Sequential(
(0): Linear(in_features=4, out_features=3, bias=True)
)
예시 3)
# 모델의 학습 가능한 파라미터(가중치와 편향)를 확인합니다.
# model.parameters(): PyTorch 모델에서 학습 가능한 모든 파라미터를 반환합니다.
# list(): 반환된 파라미터를 리스트로 변환하여 가중치와 편향을 확인할 수 있습니다.
list(model.parameters())
--->
[Parameter containing:
tensor([[-0.2100, -0.1009, 0.2470, -0.4785],
[-0.4346, 0.2855, -0.1117, 0.1340],
[ 0.4447, -0.0227, -0.2139, -0.1113]], requires_grad=True),
Parameter containing:
tensor([-0.3901, -0.1394, 0.3450], requires_grad=True)]
예시 4)
# 학습 데이터 X_train을 모델에 입력하여 예측값을 계산합니다.
# model(X_train):
# - X_train 텐서를 모델에 입력하여 순전파(forward pass)를 수행합니다.
# - 모델은 다음 연산을 수행합니다:
# 1. 선형 계층(nn.Linear): z = X_train * weight^T + bias
# 2. 출력값(y_pred)은 클래스별 로짓(logits, 활성화 함수 적용 전 값)으로 계산됩니다.
y_pred = model(X_train)
# 모델의 예측값(y_pred)을 확인합니다.
# y_pred는 크기가 (10, 3)인 텐서로 반환됩니다:
# - 10: X_train의 샘플 수.
# - 3: 출력 클래스 수.
# 각 행은 하나의 샘플에 대해 3개의 클래스에 해당하는 로짓 값을 나타냅니다.
y_pred
--->
tensor([[-1.0333, 0.0193, 0.4191],
[-1.1269, -0.7901, 0.3474],
[-2.2939, -0.9565, 0.5696],
[-2.5892, -1.1950, 0.4525],
[-2.3629, 1.2506, -0.9725],
[-3.5968, 1.0818, -1.2609],
[-2.9268, 1.5807, -1.6456],
[-3.7163, 1.5657, -1.3349],
[-3.3839, 1.2579, -0.9870],
[-2.8044, 0.8384, -0.8530]], grad_fn=<AddmmBackward0>)
##CrossEntropyLoss
* CrossEntropyLoss는 다중 클래스 분류(Multiclass Classification) 문제에서 모델의 예측과 실제 정답 레이블 간의 차이를 측정하는 손실 함수(Loss Function)입니다.
* 이 함수는 모델이 예측한 확률 분포와 실제 레이블(정답) 간의 불확실성을 수치화합니다.
* CrossEntropyLoss는 주로 Softmax 함수와 함께 사용됩니다.
* Softmax는 각 클래스에 대한 확률 분포를 제공하며, CrossEntropyLoss는 이 확률 분포와 실제 레이블 간의 차이를 계산합니다.
* 예측이 실제 레이블과 가까울수록 손실 값이 작아지며, 예측이 틀릴수록 손실 값은 커집니다.
###Softmax
* Softmax 함수는 다중 클래스 분류(Multiclass Classification) 문제에서 사용되는 활성화 함수(Activation Function)입니다.
* 이 함수는 주어진 입력 벡터의 각 요소를 확률 분포(probability distribution)로 변환합니다.
* 즉, 각 클래스에 대한 예측값을 0과 1 사이의 값으로 변환하며, 모든 클래스의 확률 합이 항상 1이 되도록 정규화합니다.
예시 1)
# 손실 함수로 크로스 엔트로피 손실(Cross Entropy Loss)을 계산합니다.
# nn.CrossEntropyLoss():
# - PyTorch에서 제공하는 다중 클래스 분류 문제를 위한 손실 함수입니다.
# - 이 함수는 Softmax 활성화와 Negative Log Likelihood(NLL)를 결합한 형태로 동작합니다.
# - 입력값 y_pred는 클래스별 로짓(logits)이어야 하며, Softmax를 별도로 적용할 필요가 없습니다.
# (y_pred, y_train):
# - y_pred: 모델이 계산한 클래스별 로짓(logits). 크기: [10, 3] (10개 샘플, 3개 클래스).
# - y_train: 실제 정답 레이블(클래스 인덱스). 크기: [10]. 각 값은 0, 1, 2 중 하나.
loss = nn.CrossEntropyLoss()(y_pred, y_train)
# 계산된 손실값(loss)을 출력합니다.
# 출력값은 스칼라 값으로, 모델의 예측과 실제값 간의 평균 손실을 나타냅니다.
loss
--->
tensor(1.9676, grad_fn=<NllLossBackward0>)
예시 2)
optimizer = optim.SGD(model.parameters(), lr=0.01)
epochs = 10000
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}/{epochs} Loss: {loss: .6f}')
--->
Epoch: 0/10000 Loss: 1.967613
Epoch: 100/10000 Loss: 0.872644
Epoch: 200/10000 Loss: 0.762529
Epoch: 300/10000 Loss: 0.716454
Epoch: 400/10000 Loss: 0.686174
Epoch: 500/10000 Loss: 0.662485
Epoch: 600/10000 Loss: 0.642596
Epoch: 700/10000 Loss: 0.625351
Epoch: 800/10000 Loss: 0.610145
Epoch: 900/10000 Loss: 0.596596
Epoch: 1000/10000 Loss: 0.584434
Epoch: 1100/10000 Loss: 0.573449
Epoch: 1200/10000 Loss: 0.563474
Epoch: 1300/10000 Loss: 0.554368
Epoch: 1400/10000 Loss: 0.546018
Epoch: 1500/10000 Loss: 0.538325
Epoch: 1600/10000 Loss: 0.531208
Epoch: 1700/10000 Loss: 0.524595
Epoch: 1800/10000 Loss: 0.518427
Epoch: 1900/10000 Loss: 0.512655
Epoch: 2000/10000 Loss: 0.507233
Epoch: 2100/10000 Loss: 0.502124
Epoch: 2200/10000 Loss: 0.497295
Epoch: 2300/10000 Loss: 0.492719
Epoch: 2400/10000 Loss: 0.488371
Epoch: 2500/10000 Loss: 0.484229
Epoch: 2600/10000 Loss: 0.480275
Epoch: 2700/10000 Loss: 0.476492
Epoch: 2800/10000 Loss: 0.472865
Epoch: 2900/10000 Loss: 0.469381
Epoch: 3000/10000 Loss: 0.466029
Epoch: 3100/10000 Loss: 0.462799
Epoch: 3200/10000 Loss: 0.459681
Epoch: 3300/10000 Loss: 0.456667
Epoch: 3400/10000 Loss: 0.453751
Epoch: 3500/10000 Loss: 0.450924
Epoch: 3600/10000 Loss: 0.448181
Epoch: 3700/10000 Loss: 0.445516
Epoch: 3800/10000 Loss: 0.442925
Epoch: 3900/10000 Loss: 0.440403
Epoch: 4000/10000 Loss: 0.437946
Epoch: 4100/10000 Loss: 0.435550
Epoch: 4200/10000 Loss: 0.433211
Epoch: 4300/10000 Loss: 0.430927
Epoch: 4400/10000 Loss: 0.428694
Epoch: 4500/10000 Loss: 0.426510
Epoch: 4600/10000 Loss: 0.424373
Epoch: 4700/10000 Loss: 0.422279
Epoch: 4800/10000 Loss: 0.420227
Epoch: 4900/10000 Loss: 0.418214
Epoch: 5000/10000 Loss: 0.416240
Epoch: 5100/10000 Loss: 0.414302
Epoch: 5200/10000 Loss: 0.412398
Epoch: 5300/10000 Loss: 0.410528
Epoch: 5400/10000 Loss: 0.408689
Epoch: 5500/10000 Loss: 0.406881
Epoch: 5600/10000 Loss: 0.405102
Epoch: 5700/10000 Loss: 0.403351
Epoch: 5800/10000 Loss: 0.401627
Epoch: 5900/10000 Loss: 0.399929
Epoch: 6000/10000 Loss: 0.398256
Epoch: 6100/10000 Loss: 0.396608
Epoch: 6200/10000 Loss: 0.394982
Epoch: 6300/10000 Loss: 0.393379
Epoch: 6400/10000 Loss: 0.391798
Epoch: 6500/10000 Loss: 0.390237
Epoch: 6600/10000 Loss: 0.388697
Epoch: 6700/10000 Loss: 0.387177
Epoch: 6800/10000 Loss: 0.385676
Epoch: 6900/10000 Loss: 0.384193
Epoch: 7000/10000 Loss: 0.382728
Epoch: 7100/10000 Loss: 0.381281
Epoch: 7200/10000 Loss: 0.379851
Epoch: 7300/10000 Loss: 0.378437
Epoch: 7400/10000 Loss: 0.377039
Epoch: 7500/10000 Loss: 0.375657
Epoch: 7600/10000 Loss: 0.374290
Epoch: 7700/10000 Loss: 0.372938
Epoch: 7800/10000 Loss: 0.371600
Epoch: 7900/10000 Loss: 0.370276
Epoch: 8000/10000 Loss: 0.368966
Epoch: 8100/10000 Loss: 0.367670
Epoch: 8200/10000 Loss: 0.366386
Epoch: 8300/10000 Loss: 0.365115
Epoch: 8400/10000 Loss: 0.363857
Epoch: 8500/10000 Loss: 0.362611
Epoch: 8600/10000 Loss: 0.361376
Epoch: 8700/10000 Loss: 0.360154
Epoch: 8800/10000 Loss: 0.358943
Epoch: 8900/10000 Loss: 0.357743
Epoch: 9000/10000 Loss: 0.356554
Epoch: 9100/10000 Loss: 0.355375
Epoch: 9200/10000 Loss: 0.354208
Epoch: 9300/10000 Loss: 0.353050
Epoch: 9400/10000 Loss: 0.351903
Epoch: 9500/10000 Loss: 0.350765
Epoch: 9600/10000 Loss: 0.349638
Epoch: 9700/10000 Loss: 0.348519
Epoch: 9800/10000 Loss: 0.347411
Epoch: 9900/10000 Loss: 0.346311
Epoch: 10000/10000 Loss: 0.345220
----------------------------
--->
# 모델 학습을 위한 최적화 알고리즘(optimizer)을 설정합니다.
# optim.SGD: 확률적 경사하강법(Stochastic Gradient Descent)을 사용합니다.
# model.parameters(): 모델의 학습 가능한 모든 파라미터(가중치와 편향)를 최적화합니다.
# lr=0.01: 학습률(learning rate)을 0.01로 설정합니다.
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 학습 반복 횟수(epochs)를 10000으로 설정합니다.
epochs = 10000
# 학습 루프를 실행합니다.
for epoch in range(epochs + 1): # 0부터 10000까지 총 10001번 반복.
# 1. 모델의 예측값 계산 (순전파, forward pass).
# X_train 데이터를 모델에 입력하여 클래스별 로짓(logits)을 계산합니다.
y_pred = model(X_train)
# 2. 손실(loss) 계산.
# nn.CrossEntropyLoss()(y_pred, y_train):
# - 모델의 예측값(y_pred)과 실제값(y_train) 간의 크로스 엔트로피 손실을 계산합니다.
loss = nn.CrossEntropyLoss()(y_pred, y_train)
# 3. 경사값(gradient) 초기화.
# optimizer.zero_grad():
# - 이전 epoch에서 계산된 경사를 초기화합니다.
optimizer.zero_grad()
# 4. 역전파(backward pass) 수행.
# loss.backward():
# - 손실값(loss)을 기준으로 모델 파라미터에 대한 경사를 계산합니다.
loss.backward()
# 5. 모델 파라미터 업데이트.
# optimizer.step():
# - 계산된 경사를 바탕으로 가중치와 편향을 업데이트합니다.
optimizer.step()
# 6. 100번째 epoch마다 학습 상태 출력.
# epoch % 100 == 0: 현재 epoch이 100으로 나누어떨어질 때마다 실행됩니다.
# f'Epoch: {epoch}/{epochs} Loss: {loss: .6f}':
# - 현재 epoch 번호와 손실값을 출력합니다. 손실값은 소수점 6자리까지 표시됩니다.
if epoch % 100 == 0:
print(f'Epoch: {epoch}/{epochs} Loss: {loss: .6f}')
예시 3)
# 테스트 데이터를 생성합니다.
# torch.FloatTensor([[1, 9, 9, 8]]):
# - 입력 데이터로 [1, 9, 9, 8]을 가지는 2D 텐서를 생성합니다.
# - FloatTensor는 실수(float)형 데이터를 생성합니다.
# - 크기: [1, 4] (1개의 샘플, 4개의 특성).
x_test = torch.FloatTensor([[1, 9, 9, 8]])
# 모델을 사용하여 테스트 데이터(x_test)에 대한 예측값을 계산합니다.
# model(x_test):
# - x_test를 모델에 입력하여 순전파(forward pass)를 수행합니다.
# - 출력값은 각 클래스(0, 1, 2)에 대한 로짓(logits) 값으로 계산됩니다.
y_pred = model(x_test)
# 모델의 예측값(y_pred)을 확인합니다.
# - y_pred는 크기가 [1, 3]인 텐서로 반환됩니다:
# - 1: 입력 샘플 수.
# - 3: 출력 클래스 수(0, 1, 2).
# - 각 클래스에 대한 로짓 값을 포함합니다.
y_pred
--->
tensor([[-13.2952, 3.5899, 6.4243]], grad_fn=<AddmmBackward0>)
예제 4)
# dim=1, 두번째 차원(열 방향) 적용
#
--->
# Softmax 활성화 함수를 사용하여 예측값(y_pred)을 확률로 변환합니다.
# nn.Softmax(1):
# - PyTorch의 Softmax 함수로, 각 클래스에 대한 로짓 값을 확률로 변환합니다.
# - dim=1: Softmax를 두 번째 차원(열 방향)에 적용합니다.
# 즉, 각 샘플(행)에서 모든 클래스(열)의 값이 1로 정규화됩니다.
y_prob = nn.Softmax(1)(y_pred)
# Softmax 함수의 결과(y_prob)를 확인합니다.
# - y_prob의 크기: [1, 3].
# - 각 행은 입력 샘플에 대한 클래스별 확률을 나타냅니다.
# - 각 행의 값 합계는 1로 정규화됩니다.
y_prob
--->
tensor([[2.5770e-09, 5.5491e-02, 9.4451e-01]], grad_fn=<SoftmaxBackward0>)
예제 5)
#클래스별 확률을 출력하여 모델의 예측 결과를 해석할 수 있습니다.
#가장 높은 확률을 가진 클래스가 모델의 최종 예측으로 사용됩니다.
# 클래스 0에 속할 확률을 출력합니다.
# y_prob[0][0]: 첫 번째 샘플의 클래스 0에 대한 확률.
# :.2f: 소수점 둘째 자리까지 출력.
print(f'0일 확률: {y_prob[0][0]:.2f}')
# 클래스 1에 속할 확률을 출력합니다.
# y_prob[0][1]: 첫 번째 샘플의 클래스 1에 대한 확률.
# :.2f: 소수점 둘째 자리까지 출력.
print(f'1일 확률: {y_prob[0][1]:.2f}')
# 클래스 2에 속할 확률을 출력합니다.
# y_prob[0][2]: 첫 번째 샘플의 클래스 2에 대한 확률.
# :.2f: 소수점 둘째 자리까지 출력.
print(f'2일 확률: {y_prob[0][2]:.2f}')
--->
0일 확률: 0.00
1일 확률: 0.06
2일 확률: 0.94
예제 6)
# y_prob에서 가장 높은 확률을 가지는 클래스의 인덱스를 반환합니다.
# torch.argmax(y_prob, axis=1):
# - y_prob: 각 클래스에 대한 확률 값을 포함하는 텐서. 크기: [n_samples, n_classes].
# - axis=1: 각 샘플(row)에서 열 방향으로 최대값을 가진 클래스의 인덱스를 찾습니다.
# - 반환값은 각 샘플에 대해 가장 높은 확률을 가진 클래스의 인덱스로 구성된 1D 텐서입니다.
torch.argmax(y_prob, axis=1)
--->
tensor([2])
### 과제
* 와인 품종 예측하기
* load_wine : 이탈리아의 같은 지역에서 재배된 세가지 다른 품종으로 만든 와인을 화학적으로 분석한 결과에 대한 데이터셋
* 13개의 성분을 분석해서 어떤 와인인지 구별하는 모델을 만듦
* 테스트 데이터의 0번 인덱스가 어떤 와인인지 클래스를 출력(7:3) - 130 40
링크 : https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_wine.html#sklearn.datasets.load_wine
'LLM(Large Language Model)의 기초 > 데이터 분석' 카테고리의 다른 글
16. 슈퍼스토어 마케팅 캠페인 데이터셋 (2) | 2025.01.10 |
---|---|
15. 호텔 예약 수요 데이터셋 (2) | 2025.01.09 |
13. 서울 자전거 공유 수요 예측 데이터셋 (0) | 2025.01.08 |
12. 주택 임대료 예측 데이터셋 (0) | 2025.01.07 |
11. 사이킷런 (0) | 2025.01.07 |