| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- UMAP
- RDBMS
- Python
- 데이터엔지니어
- 트랜스포머
- Transformer
- CNN
- python기초
- 생성형 인공지능
- dementional reduction
- CLIP
- 딥러닝
- LangGraph
- 랭그래프
- 힙정렬
- 캐글
- RNN
- TTS
- 객체지향
- 정보처리기사
- SQL
- 머신러닝
- 자연어처리
- python 기초
- 기초
- 소프트웨어 개발
- 데이터 시각화
- ASR
- 알고리즘
- 에이전트
- Today
- Total
수달이네 기술 블로그
3. 파이토치 논리회귀(단항, 다중 논리회귀) 본문
논리회귀
입력 데이터를 기반으로 두가지 이상 범주로 분류하는 지도 학습 알고리즘
- 이진 분류 문제 등 사건 발생 확률 예측
- sigmoid, logistic function등 비선형 함수를 사용하여 0~1사이의 값으로 변환
- 0.5를 기준으로 두 범주 중 하나로 분류한다.(반올림?)
sigmoid
입력값을 받아 0~1사이의 값으로 분류하는 방법 중 하나.

$$ \sigma (x)=\frac{1}{1+e^{-x}} $$
위 수식에 넣으면 어떤 값이 들어와도 0~1사이가 된다.
- 0.5보다 아래면 0 / 0.5보다 위면 1로 분류한다.(이진 분류)
- 매우 큰 양수일수록 1에 가까워짐, 반대면 0에 가까워짐, 0은 0.5
단항 논리 회귀
독립변수 하나로 이진 분류 문제를 해결
x = torch.tensor([1.0,2.0,3.0])
w = torch.tensor([0.1,0.2,0.3])
b = torch.tensor(0.5)
- x값과 기울기 편향이 위와 같을때, 계산은 내적(행렬곱)으로 한다.
- $y = x1 * w1 + x2 * w2 … xn * wn + b$
z = torch.dot(w,x) + b
z
# tensor(1.9000)
sigmoid = nn.Sigmoid()
output = sigmoid(z)
output
# tensor(0.8699)
- 위와 같이 내적을 구하고 sigmoid함수에 넣어주는 방식을 통해 분류한다.
- 위값은 0.8699이므로 1로 판단.
적용
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)
# torch.Size([8, 1])
# torch.Size([8, 1])
plt.figure(figsize=(8, 5))
plt.scatter(x_train, y_train)

위와 같은 데이터셋을 구성했다.
model = nn.Sequential(
nn.Linear(1,1),
nn.Sigmoid()
)
list(model.parameters())
# W : [-0.4199]
# B : [-0.2018]
- 위와 같이 랜덤 파라미터가 적용된 모델이 있을 때
y_pred = model(x_train)
y_pred
# tensor([[4.4972e-01],
# [3.4939e-01],
# [1.8823e-01],
# [9.1004e-02],
# [2.7620e-02],
# [7.9943e-03],
# [1.5001e-03],
# [1.8401e-04]], grad_fn=<SigmoidBackward0>)
- 단순 예측하면 의미 없는 값이 나온다.
- 여기서 손실함수를 통해 모델을 학습해 주어야 하는데
BCE(Binary Cross Entropy) 손실함수
이진 분류 문제에서 모델이 예측한 확률 분포와 실제 레이블 사이의 차이를 측정하는 손실 함수
$$ L = -\frac{1}{N} \sum_{i=1}^{N} [y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i)] $$
- 실제 값이 1일때 예측 확률이 1에 가까우면 손실이 작아지고, 실제 값이 0일때 예측 확률이 0에 가까우면 손실이 작아진다.
- $L: Loss$
- $N: 전체 데이터$
- $y_i: 실제 정답(0 or 1)$
- $\hat{y}_i: 모델이 예측한 확률 (0~1 사이의 값)$
loss = nn.BCELoss()(y_pred, y_train)
loss
# tensor(0.4471, grad_fn=<BinaryCrossEntropyBackward0>)
- 위와 같이 정의하고 구현할 수 있다.
이제 실제로 모델을 학습하자면
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}')
# epoch: 0/1000 Loss: 0.447143
# epoch: 100/1000 Loss: 0.313473
# epoch: 200/1000 Loss: 0.296310
# epoch: 300/1000 Loss: 0.281232
# epoch: 400/1000 Loss: 0.267894
# epoch: 500/1000 Loss: 0.256020
# epoch: 600/1000 Loss: 0.245387
# epoch: 700/1000 Loss: 0.235812
# epoch: 800/1000 Loss: 0.227145
# epoch: 900/1000 Loss: 0.219263
# epoch: 1000/1000 Loss: 0.212061
- 위와 같이 손실값이 줄어드는 것을 볼 수 있다.
list(model.parameters())
# 초기값
# W : [-0.4199]
# B : [-0.2018]
# 학습이후 값
# W: [0.3921]
# B: [-2.0678]
- 위와 같이 기울기와 편향이 나타난다. 이전의 값에서 변한 것을 볼 수 있다.
x_test = torch.FloatTensor([[10]])
y_pred = model(x_test)
y_pred
# tensor([[0.8645]], grad_fn=<SigmoidBackward0>)
y_bool = (y_pred >= 0.5).float()
y_bool
# tensor([[1.]])
- 만약 y의 값이 임계값 0.5 보다 크거나 같으면 1이 아니면 0이 출력된다.
다항 논리 회귀
다항 논리 회귀는 n : 1로 예측하는 다중 클래스 분류 문제를 해결하는 알고리즘이다.
- 소프트맥스(Softmax)함수(0~1사이로 정규화)
- 특정 클래스가 속할 가능성을 계산, 가장 높은 확률의 클래스를 최정 예측 값으로 선택한다.
- 자연어 처리, 이미지 분류, 다양한 다중 클래스 분류 문제등에 사용
아래와 같이 데이터 셋을 구성했다.
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, 0, 0, 1, 1, 1, 2, 2, 2, 2]
x_train = torch.FloatTensor(x_train)
y_train = torch.LongTensor(y_train)
print(x_train.shape)
print(y_train.shape)
# torch.Size([10, 4])
# torch.Size([10])
model = nn.Sequential(
nn.Linear(4, 3)
)
model
- 독립변수가 4종으로 구성되어있고, 종속변수는 0,1,2 총 3개의 클래스로 나뉘므로 Linear(4,3)으로 초기화 해준다.
$$ Y = XW + b $$
- $X : 입력벡터(위에선 x1,x2,x3,x4, 1 × 4크기)$
- $W: 가중치 행렬(4 × 3)$
- $b: 편향 벡터 (1 × 3)$
- $Y: 출력 벡터 (1 × 3)$
위와 같이 구성되며
$$ y_1=(x_1\cdot w_{11})+(x_2\cdot w_{21})+(x_3\cdot w_{31})+(x_4\cdot w_{41})+b_1\\ y_2=(x_1\cdot w_{12})+(x_2\cdot w_{22})+(x_3\cdot w_{32})+(x_4\cdot w_{42})+b_2\\ y_3=(x_1\cdot w_{13})+(x_2\cdot w_{23})+(x_3\cdot w_{33})+(x_4\cdot w_{43})+b_3 $$
- 계산하면 위와 같이 계산한다.(행렬곱)
list(model.parameters())
# [Parameter containing:
# tensor([[-0.4346, 0.2855, -0.1117, 0.1340],
# [ 0.4447, -0.0227, -0.2139, -0.1113],
# [-0.3901, -0.1394, 0.3450, 0.3059]], requires_grad=True),
# Parameter containing:
# tensor([-0.4480, -0.1562, 0.0326], requires_grad=True)]
- 구성된 가중치 행렬과 편향은 랜덤으로 위와 같이 구성되었고
y_pred = model(x_train)
y_pred
# tensor([[-0.2892, -0.0821, 0.0146],
# [-1.0986, -0.1538, 0.7598],
# [-1.2651, 0.0684, 0.9815],
# [-1.5035, -0.0487, 1.4479],
# [ 0.9420, -1.4737, 2.0605],
# [ 0.7732, -1.7621, 3.2569],
# [ 1.2722, -2.1468, 3.2229],
# [ 1.2571, -1.8361, 2.9992],
# [ 0.9493, -1.4882, 2.4878],
# [ 0.5298, -1.3542, 2.3213]], grad_fn=<AddmmBackward0>)
- 예측값은 위와 같이 의미 없는 값으로 구해진다.
CrossEntropyLoss 손실함수
다중 클래스 분류 문제에서 모델의 예측과 실제 정답의 차이를 측정하는 손실함수.
모델이 예측한 확률 분포와 실제 레이블 간의 불확실성을 수치화 한다.
$$ L = -\sum^{C}_{c=1}y_c\cdot log(\hat{y}_c) $$
- $L: Loss$
- $C: 클래스 수$
- $y_c: 실제 레이블$
- $\hat{y}_c: 모델이 예측한 클래스 c에 대한 확률$
- $ex) y_c: [1,0,0] , \hat{y}_c: [0.7,0.2,0.1] 일때$
$$ L=-(1\cdot log(0.7)+0 \cdot log(0.2) + 0\cdot log(0.1)) \\ L = -log(0.7) $$
- 위와 같이 계산되어 손실은 약 0.3567으로 출력된다.
loss = nn.CrossEntropyLoss()(y_pred, y_train)
loss
# tensor(1.7610, grad_fn=<NllLossBackward0>)
현재 내 모델에서 CE를 계산하면 위와 같이 나온다.
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: 9700 / 10000, loss: 0.347429
# epoch: 9800 / 10000, loss: 0.346335
# epoch: 9900 / 10000, loss: 0.345250
# epoch: 10000 / 10000, loss: 0.344174
CE를 통해 학습시킨 결과는 위와 같으며
x_test = torch.FloatTensor([[1,9,9,8]])
y_pred = model(x_test)
y_pred
# tensor([[-11.2851, 5.6718, 8.5757]], grad_fn=<AddmmBackward0>)
해당 모델을 통해 예측하면 위와 같다.
Softmax
위에서 예측한 값을 0~1사이의 값으로 정규화 시키기 위해서 다중 클래스 분류 문제에서는 softmax 활성화 함수를 사용한다.

$$ \mathrm{Softmax}(z_i)=\frac{e^{z_i}}{\sum _{j=1}^Ke^{z_j}} $$
- 위에서 예측한 값을 이용해 softmax함수를 적용한다.
y_prob = nn.Softmax(1)(y_pred)
y_prob
# tensor([[2.2459e-09, 5.1957e-02, 9.4804e-01]], grad_fn=<SoftmaxBackward0>)
- 위와 같이 적용 했다면
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)
# 0일 확률: 0.00
# 1일 확률: 0.05
# 2일 확률: 0.95
# tensor([2])
- 총합 1로 확률을 만들어 주고, 그 결과에서 가장 큰 값으로 예측한다.
위와 같이 논리 회귀를 구현 가능하다.
'AI공부 > 딥러닝' 카테고리의 다른 글
| 5. ANN과 퍼셉트론 (0) | 2026.01.31 |
|---|---|
| 4. 손글씨 숫자 데이터셋 처리 (0) | 2026.01.30 |
| 2. 다중선형회귀 (0) | 2026.01.28 |
| 1. 단순 선형 회귀(손실함수, 최적화, 경사하강법, 학습률) (0) | 2026.01.27 |
| 딥러닝. Alexnet (0) | 2026.01.15 |