확률과 분류 기준을 구분하기

본인 사본을 만들어 실행·수정·기록하세요.

1. CSV의 입력 확인

CSV의 앞 8열은 입력 특징, 마지막 열은 0·1 Label입니다. x=(x_raw-mean)/scale은 특징마다 평균을 빼고 표준편차로 나누는 Standardization입니다. 특징들의 수치 규모를 맞추며, 새 입력에도 이 mean과 scale을 그대로 사용합니다.

A. 기준 예제 · 먼저 읽고 실행

import sys, numpy as np, matplotlib.pyplot as plt
import torch
from torch import nn
import torch.nn.functional as F
torch.manual_seed(42)
torch.set_num_threads(2)
print('Python:', sys.version.split()[0], '| PyTorch:', torch.__version__)
from pathlib import Path
from urllib.request import urlretrieve
p=Path('data_logistic_regression.csv')
if not p.exists():
    urlretrieve('https://nii-lab.github.io/assets/courses/ai-applications/logistic-regression/data_logistic_regression.csv',p)
a=np.loadtxt(p,delimiter=',',dtype=np.float32)
x_raw=torch.tensor(a[:,:8]); labels=torch.tensor(a[:,-1],dtype=torch.long)
classes=torch.unique(labels);print('data:',a.shape,'classes:',classes)
mean=x_raw.mean(0);scale=x_raw.std(0).clamp_min(1e-6)
x=(x_raw-mean)/scale
y=labels.float().reshape(-1,1)
print(x.shape,y.shape)

B. 직접 수행

  1. 데이터를 읽는 셀을 실행하세요. x_raw와 x의 shape·dtype, 처음 다섯 행을 각각 출력하세요. 두 출력에 전처리 전·후라고 표시하세요.
  2. 같은 셀의 labels와 y에서 shape·dtype·처음 다섯 값을 출력하세요. Label을 Loss에 전달할 형태로 바꾼 부분을 찾으세요.
  3. 새 표본을 예측할 때 왜 학습 데이터의 mean·scale을 그대로 써야 하는지, 각 Feature가 모델에 입력되는 척도와 연결해 설명하세요.

예상은 정확한 수치 대신 shape나 증가·감소 방향으로 적어도 됩니다. 코드는 위 예제를 참고해 작성하고, 설명만 묻는 항목은 아래 Text Cell에 답하세요.

# ✍ 직접 작성: 이 셀 아래에 본인의 코드를 추가하세요.
# 코드가 길어지면 Code Cell을 추가해도 됩니다.

C. 직접 기록 · 이 Text Cell을 더블클릭해서 수정

2. 기준 학습 실행

BCEWithLogitsLoss는 Sigmoid와 Binary Cross Entropy를 함께 계산합니다. 학습할 때 Sigmoid를 중복 적용하지 않고, 확률 표시와 Threshold 판정에서만 사용하세요. 비교할 때 train_classifier(lr=…, epochs=1000)처럼 epoch 수를 명시합니다.

A. 기준 예제 · 먼저 읽고 실행

def train_classifier(lr=0.1,epochs=2000):
    torch.manual_seed(42);m=nn.Linear(8,1);opt=torch.optim.SGD(m.parameters(),lr=lr)
    criterion=nn.BCEWithLogitsLoss();losses=[];accuracies=[]
    for _ in range(epochs):
        m.train();logits=m(x);loss=criterion(logits,y)
        opt.zero_grad();loss.backward();opt.step()
        with torch.no_grad():
            logits=m(x);prediction=(torch.sigmoid(logits)>=0.5).long().reshape(-1)
            losses.append(criterion(logits,y).item());accuracies.append((prediction==labels).float().mean().item())
    return m,losses,accuracies
model,losses,accuracies=train_classifier()
print('Training accuracy:',accuracies[-1])
fig,axes=plt.subplots(1,2,figsize=(10,3));axes[0].plot(losses);axes[1].plot(accuracies)
for ax,yl in zip(axes,['Training loss','Training accuracy']):ax.set(xlabel='Epoch',ylabel=yl);ax.grid()
plt.show()

B. 직접 수행

  1. train_classifier를 Learning Rate η∈{0.001,0.01,0.1}\eta\in\{0.001,0.01,0.1\}, 각각 1000 epoch로 호출하세요. 함수 안의 Seed와 모델 초기화를 유지하세요.
  2. 세 Loss 곡선을 한 그래프에 그리고, 마지막 Training Loss·Training Accuracy를 Learning Rate별 표로 적으세요.
  3. Loss가 줄어드는 속도가 어떻게 다른지 곡선의 구간을 짚어 설명하세요.

예상은 정확한 수치 대신 shape나 증가·감소 방향으로 적어도 됩니다. 코드는 위 예제를 참고해 작성하고, 설명만 묻는 항목은 아래 Text Cell에 답하세요.

# ✍ 직접 작성: 이 셀 아래에 본인의 코드를 추가하세요.
# 코드가 길어지면 Code Cell을 추가해도 됩니다.

C. 직접 기록 · 이 Text Cell을 더블클릭해서 수정

3. 출력을 해석하기

확률은 각 Class를 얼마나 그럴듯하게 예측했는지 나타내고, 최종 Class는 그중 선택한 답 하나입니다. 확률과 선택 결과를 나란히 출력해 확인합니다.

A. 기준 예제 · 먼저 읽고 실행

with torch.no_grad():
    probability=torch.sigmoid(model(x)).reshape(-1)
for threshold in [0.3,0.5]:
    prediction=(probability>=threshold).long()
    print(threshold,(prediction==labels).float().mean().item())
print(torch.stack([probability[:5],(probability[:5]>=.5).float(),labels[:5].float()],1))

B. 직접 수행

  1. 앞 활동에서 학습한 모델 하나를 골라 Probability를 한 번 구하세요. 선택한 Learning Rate를 기록하세요. 같은 Probability에 Threshold θ∈{0.3,0.5,0.7}\theta\in\{0.3,0.5,0.7\}을 각각 적용하세요.
  2. Threshold·Accuracy·Positive 예측 개수를 세 행의 표로 기록하세요.
  3. Threshold에 따라 판정이 바뀐 표본을 최대 3개 고르세요. 표본 번호·Probability·정답·세 Threshold의 판정을 표로 적으세요. 판정이 바뀐 표본이 없으면 없다고 적으세요.

예상은 정확한 수치 대신 shape나 증가·감소 방향으로 적어도 됩니다. 코드는 위 예제를 참고해 작성하고, 설명만 묻는 항목은 아래 Text Cell에 답하세요.

# ✍ 직접 작성: 이 셀 아래에 본인의 코드를 추가하세요.
# 코드가 길어지면 Code Cell을 추가해도 됩니다.

C. 직접 기록 · 이 Text Cell을 더블클릭해서 수정

반복 숙달 · 실행 전에 판단하기

앞의 직접 수행에서 비교한 조건 세 가지를 이 표에 정리하세요. 이미 수행한 실험을 다시 추가할 필요는 없습니다. 비교가 부족하면 한 조건만 바꾸어 보충하세요.

변경 조건 예상 shape/수치/결과 실제 결과 오류가 있었다면 원인
⟦직접 입력 1⟧ ⟦직접 입력⟧ ⟦직접 입력⟧ ⟦직접 입력⟧
⟦직접 입력 2⟧ ⟦직접 입력⟧ ⟦직접 입력⟧ ⟦직접 입력⟧
⟦직접 입력 3⟧ ⟦직접 입력⟧ ⟦직접 입력⟧ ⟦직접 입력⟧
# ✍ 반복 실험 코드

선택 실습 · 오류의 원인을 찾아 코드 고치기

BCE Target의 shape가 다른 경우

  1. 모델 학습까지 마친 뒤, 노트북 맨 아래에 Code Cell을 추가하고 다음 코드를 실행하세요.

    with torch.no_grad():
        debug_logits = model(x)
    print("Logits:", debug_logits.shape)
    for debug_target in [y.squeeze(1), y]:
        print("Target:", debug_target.shape)
        try:
            print("Loss:", F.binary_cross_entropy_with_logits(
                debug_logits, debug_target).item())
        except (RuntimeError, ValueError) as error:
            print(type(error).__name__, str(error))
  2. Text Cell에 Logits shape, 각 Target shape, 실행 성공 여부를 표로 적으세요. squeeze(1)로 어느 축이 사라졌으며, 이 Loss에서 Logits와 Target의 shape가 어떻게 맞아야 하는지 설명하세요.

저장 전 확인

  1. 작성란과 출력·그래프를 확인하고 새 런타임에서 전체 셀을 순서대로 실행하세요.
  2. 본인 Drive에 저장한 뒤 .ipynb로 내려받으세요.

코드, 실제 Output·그래프, 직접 작성한 해석을 포함하세요. 제출은 KLAS를 이용하며 기한은 학기 일정과 최신 공지를 확인합니다.

파일명: 이름_학번_7주차.ipynb.