Multiclass Classification과 Logits
본인 사본을 만들어 실행·수정·기록하세요.
- 이름: ⟦여기에 직접 입력⟧
- 학번: ⟦여기에 직접 입력⟧
- Code Cell 실행: ▶ 또는
Shift+Enter, 위에서부터 순서대로. - Text Cell 작성: 더블클릭 →
직접 입력작성 →Shift+Enter. - 직접 작성 셀: 본인 코드 입력.
- 값 변경 후: 해당 셀과 뒤의 관련 셀 다시 실행.
1. CSV의 입력 확인
CSV의 앞 16열이 특징, 마지막 열이 Class Index입니다. Label은 0부터 C−1까지의 정수여야 합니다. 각 특징을 (값−평균)/표준편차로 바꾸어 규모를 맞추며, 새 데이터에도 같은 평균과 표준편차를 사용합니다.
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_multinomial_classification.csv')
if not p.exists():
urlretrieve('https://nii-lab.github.io/assets/courses/ai-applications/multiclass/data_multinomial_classification.csv',p)
a=np.loadtxt(p,delimiter=',',dtype=np.float32)
x_raw=torch.tensor(a[:,:16]); 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
assert torch.equal(classes,torch.arange(len(classes)))
print(x.shape,y.shape,y.dtype)
B. 직접 수행
- 데이터를 읽는 셀을 실행하세요.
x_raw와x의 shape·dtype, 처음 다섯 행을 각각 출력하세요. 두 출력에 전처리 전·후라고 표시하세요. - 같은 셀의
labels와y에서 shape·dtype·처음 다섯 값을 출력하세요. Label을 Loss에 전달할 형태로 바꾼 부분을 찾으세요. - 새 표본을 예측할 때 왜 학습 데이터의
mean·scale을 그대로 써야 하는지, 각 Feature가 모델에 입력되는 척도와 연결해 설명하세요.
예상은 정확한 수치 대신 shape나 증가·감소 방향으로 적어도 됩니다. 코드는 위 예제를 참고해 작성하고, 설명만 묻는 항목은 아래 Text Cell에 답하세요.
# ✍ 직접 작성: 이 셀 아래에 본인의 코드를 추가하세요.
# 코드가 길어지면 Code Cell을 추가해도 됩니다.
C. 직접 기록 · 이 Text Cell을 더블클릭해서 수정
- 확인하거나 바꾼 조건: ⟦직접 입력⟧
- 실행 전 예상: ⟦직접 입력⟧
- 실제 출력/그래프에서 확인한 값: ⟦직접 입력⟧
- 예상과 차이 및 설명: ⟦직접 입력⟧
2. 기준 학습 실행
Linear의 출력 개수는 Class 수입니다. CrossEntropyLoss는 이 Logit과 정답 Index를 받습니다. 비교할 때 train_classifier(lr=…, epochs=1000)처럼 epoch 수를 고정하세요.
A. 기준 예제 · 먼저 읽고 실행
def train_classifier(lr=0.1,epochs=2000):
torch.manual_seed(42);m=nn.Linear(16,len(classes));opt=torch.optim.SGD(m.parameters(),lr=lr)
criterion=nn.CrossEntropyLoss();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=logits.argmax(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. 직접 수행
train_classifier를 Learning Rate , 각각 1000 epoch로 호출하세요. 함수 안의 Seed와 모델 초기화를 유지하세요.- 각 호출이 반환한 마지막 Loss·Training Accuracy를 Learning Rate별 표로 적으세요. Loss와 Accuracy의 변화는 반환한 두 기록을 같은 epoch에서 대조하세요.
- Loss는 줄지만 Accuracy는 그대로인 구간이 있다면 한 곳을 골라 표시하세요. 정답 Class의 Probability와 최종 Class 판정의 차이로 설명하세요. 해당 구간이 없으면 없다고 적으세요.
예상은 정확한 수치 대신 shape나 증가·감소 방향으로 적어도 됩니다. 코드는 위 예제를 참고해 작성하고, 설명만 묻는 항목은 아래 Text Cell에 답하세요.
# ✍ 직접 작성: 이 셀 아래에 본인의 코드를 추가하세요.
# 코드가 길어지면 Code Cell을 추가해도 됩니다.
C. 직접 기록 · 이 Text Cell을 더블클릭해서 수정
- 확인하거나 바꾼 조건: ⟦직접 입력⟧
- 실행 전 예상: ⟦직접 입력⟧
- 실제 출력/그래프에서 확인한 값: ⟦직접 입력⟧
- 예상과 차이 및 설명: ⟦직접 입력⟧
3. 출력을 해석하기
확률은 각 Class를 얼마나 그럴듯하게 예측했는지 나타내고, 최종 Class는 그중 선택한 답 하나입니다. 확률과 선택 결과를 나란히 출력해 확인합니다.
A. 기준 예제 · 먼저 읽고 실행
with torch.no_grad():
logits=model(x);probability=logits.softmax(1);prediction=logits.argmax(1)
print('first predictions:',prediction[:10]);print('labels:',labels[:10]);print(probability[:10])
wrong=(prediction!=labels).nonzero().flatten()[:3]
print('wrong indices:',wrong)
for i in wrong:print(i.item(),prediction[i].item(),labels[i].item(),probability[i])
assert torch.allclose(probability.sum(1),torch.ones(len(x)),atol=1e-5)
B. 직접 수행
- 실습용 Notebook에서
logits=model(x)계산이 포함된 예측 결과 코드 셀을 찾으세요. 앞 활동에서 학습한model을 그대로 사용합니다. - 표본 index 0–9를 10행으로, Logit·Probability·예측 Label·정답 Label을 네 열로 기록하세요. 값은 각각
logits[:10],probability[:10],prediction[:10],labels[:10]에서 확인합니다. - 제공된
assert안의torch.allclose호출을 별도 셀에서 출력하고, 전체 표본의 Probability 합 검사 결과를 참/거짓으로 기록하세요. 이어서logits.argmax(1)와probability.argmax(1)를 원소별로 대조해 일치 여부를 기록하세요. - 오분류를 최대 3개 골라 표본 index·실제 Label·예측 Label을 적으세요. 없으면 ‘없음’으로 기록하세요.
예상은 정확한 수치 대신 shape나 증가·감소 방향으로 적어도 됩니다. 코드는 위 예제를 참고해 작성하고, 설명만 묻는 항목은 아래 Text Cell에 답하세요.
# ✍ 직접 작성: 이 셀 아래에 본인의 코드를 추가하세요.
# 코드가 길어지면 Code Cell을 추가해도 됩니다.
C. 직접 기록 · 이 Text Cell을 더블클릭해서 수정
- 확인하거나 바꾼 조건: ⟦직접 입력⟧
- 실행 전 예상: ⟦직접 입력⟧
- 실제 출력/그래프에서 확인한 값: ⟦직접 입력⟧
- 예상과 차이 및 설명: ⟦직접 입력⟧
반복 숙달 · 실행 전에 판단하기
앞의 직접 수행에서 비교한 조건 세 가지를 이 표에 정리하세요. 이미 수행한 실험을 다시 추가할 필요는 없습니다. 비교가 부족하면 한 조건만 바꾸어 보충하세요.
| 변경 조건 | 예상 shape/수치/결과 | 실제 결과 | 오류가 있었다면 원인 |
|---|---|---|---|
| ⟦직접 입력 1⟧ | ⟦직접 입력⟧ | ⟦직접 입력⟧ | ⟦직접 입력⟧ |
| ⟦직접 입력 2⟧ | ⟦직접 입력⟧ | ⟦직접 입력⟧ | ⟦직접 입력⟧ |
| ⟦직접 입력 3⟧ | ⟦직접 입력⟧ | ⟦직접 입력⟧ | ⟦직접 입력⟧ |
# ✍ 반복 실험 코드
선택 실습 · 오류의 원인을 찾아 코드 고치기
Class 번호를 Float Tensor로 전달한 경우
모델 학습까지 마친 뒤, 노트북 맨 아래에 Code Cell을 추가하고 다음 코드를 실행하세요.
with torch.no_grad(): debug_logits = model(x) debug_target = y.float() print("original Target:", y.shape, y.dtype) print("Float Target:", debug_target.shape, debug_target.dtype) try: F.cross_entropy(debug_logits, debug_target) except (RuntimeError, ValueError) as error: print(type(error).__name__, str(error)) print("integer Target Loss:", F.cross_entropy(debug_logits, y).item())출력 아래에 Text Cell을 추가해 다음 두 가지를 적으세요.
- 두 Target의 shape와 dtype, 오류 메시지에서 요구하는 dtype.
- 각 샘플의 Class 번호 하나를 담은 Target에서, 같은 번호라도 Float Tensor로 전달하면 Loss를 계산할 수 없는 이유.
y.float()는 새 Tensor를 만듭니다. 원래y는 그대로이므로 마지막 줄에서는 정수형 Target으로 Loss를 계산합니다.
저장 전 확인
- 작성란과 출력·그래프를 확인하고 새 런타임에서 전체 셀을 순서대로 실행하세요.
- 본인 Drive에 저장한 뒤
.ipynb로 내려받으세요.
코드, 실제 Output·그래프, 직접 작성한 해석을 포함하세요. 제출은 KLAS를 이용하며 기한은 학기 일정과 최신 공지를 확인합니다.
파일명: 이름_학번_8주차.ipynb.