B+ 최단 코스
시간이 없을 때 이것만 하세요. 교수님이 말한 시험 유형(개념 설명 · 코드 빈칸 채우기 · 실행 결과 예측)에 나오는 것만 골랐어요. 전부 해도 약 2시간이고, 위에서부터 순서대로 하면 돼요.
시험은 코드를 주고 결과를 고르는 5지선다가 중심이에요. 외우기보다 코드를 한 줄씩 손으로 따라가서 shape과 숫자를 직접 계산하는 연습이 점수를 좌우해요. 아래 "시험 단골 코드 유형 8개"를 눈으로만 읽지 말고 가리고 풀어 보세요.
① 큰 그림 한 줄 외우기 10분
시험지를 받으면 여백에 이 두 줄부터 써 두세요. 문제 절반이 여기서 나와요.
교수님 설명을 요약하면 — 데이터를 넣어 예측하고, 정답과의 차이(loss)를 보고, weight를 loss가 줄어드는 쪽으로 고치는 일을 계속 반복한다.
② 핵심 카드만 읽기 40분
장마다 첫 카드부터 읽으세요. 각 카드의 "시험엔 이렇게 써요" 칸을 꼭 소리 내어 읽고, 코드 아래의 "한 줄씩 읽기" 표를 눈으로 따라가세요.
- 왕초보 코드 읽기 — 리스트 번호 · 슬라이싱 · 함수 · f-string · range 코드가 낯설면 먼저
- 딥러닝 큰 그림 — 학습 한 바퀴 · weight 개수 · 업데이트 식 · epoch 1순위
- Tensor — shape 읽기 · 슬라이싱 · 브로드캐스팅 · reshape/squeeze/cat/stack 단골
- GPU와 Colab — device 규칙 두 가지 · is_available
- 클래스와 상속 — self · __init__ · super() · 오버라이딩 · __call__ 단골
- nn.Module — 모델 틀 · model(x)가 forward를 부르는 과정 · Linear의 shape 1순위
- Autograd — backward · gradient 값 · 누적과 zero_grad · leaf · no_grad 단골
- 손실·옵티마이저 — MSE · shape 함정 · SGD · step 단골
- Dataset·DataLoader — __len__/__getitem__ · batch 수 · drop_last · shuffle 단골
- 학습 루프·검증 — 5단계 반복 · epoch 평균 loss · 검증은 업데이트 안 함
시간이 모자라면 표시가 있는 1순위와 단골 장(2·3·5·6·7·8·9번)부터 읽으세요.
③ 꼭 외울 것 15분
숫자와 문장은 이 표대로만 알면 돼요. 코드 문제의 답을 계산할 때 그대로 써요.
| 항목 | 외울 내용 |
|---|---|
| nn.Linear(in, out) | weight는 (out, in), bias는 (out,). 파라미터 수 = in×out + out. 계산은 x @ W.T + b. 입력 (N, in) → 출력 (N, out) |
| 파라미터 수 예 | Linear(3,2) = 8 · Linear(5,3) = 18 · TinyMLP(4,8,2) = 58 (ReLU는 0개) |
| 인덱스 | 0부터 센다. a[1:4]는 1~3번(끝 번호 제외) |
| 브로드캐스팅 | 오른쪽 끝부터 비교해 같거나 · 하나가 1이거나 · 한쪽에 없으면 가능. (2,3)+(3,) 가능 / (2,3)+(2,) 불가 / (4,1)+(1,5) = (4,5) |
| cat · stack | cat은 기존 차원에 이어 붙임(차원 수 그대로), stack은 새 차원을 만듦(차원 수 +1) |
| device | 모델과 데이터는 같은 device. x = x.to(device)처럼 다시 저장. device는 "cuda" if torch.cuda.is_available() else "cpu" |
| 상속 | 자식이 __init__을 다시 쓰면 부모 __init__은 자동으로 안 불린다 → super().__init__(...) |
| model(x) | 부모 nn.Module의 __call__이 처리한 뒤 forward 실행. forward를 직접 부르지 않는다 |
| backward · step | backward = grad 계산·저장(누적), step = 값 갱신. grad는 누적되므로 매번 zero_grad |
| grad 규칙 | backward는 숫자 하나(scalar)에만 · .grad는 leaf에만 · 한 번 쓴 그래프는 재사용 불가 · 값 수정은 torch.no_grad() 안에서 |
| SGD 식 | w ← w − lr × grad. 예: w=0.7, grad=−2, lr=1 → 2.7. 학습률은 보통 아주 작게 |
| 외울 grad 값 | w=3, L=w² → 6 · w=2, (wx−t)², x=3, t=10 → −24 · w=2 누적 4 → 16 → 32 · W=[1,2,3], X=[2,1,4], L=(W@X)² → W.grad=[64,32,128] |
| batch 수 | len(loader) = 올림(샘플 수 ÷ batch). 10개, batch 4 → 3개 [4,4,2] / drop_last=True면 [4,4] |
| epoch · step | epoch = 데이터 전체 한 번. 전체 step = epoch 수 × batch 개수 (90개, batch 20, 30 epoch → 150) |
| Dataset | __len__(개수)과 __getitem__(번호로 꺼내기)을 만든다 |
| shuffle | 학습 True, 검증 False |
④ 시험 단골 코드 유형 8개 40분
각 유형을 코드 → 결과 → 왜 순서로 풀어 놨어요. 코드만 보고 먼저 결과를 예상한 다음에 아래를 보세요.
유형 1. 슬라이싱과 shape (문제샘플 1번)
결과 — (3,) 그리고 (3, 1) (선택지 "(3,) → (3, 1)")
왜 — x는 3행 4열이에요. 숫자 하나(1)로 뽑은 차원은 사라지고, 범위(1:2)로 뽑은 차원은 크기 1로 남아요. 행은 :로 다 가져왔으니 3이 그대로예요. 열 개수 4를 고르면 틀려요.
"숫자로 뽑으면 차원이 사라지고, 범위로 뽑으면 차원이 남는다"만 적용하면 돼요. 남은 차원의 길이는 가져온 개수예요.
유형 2. 브로드캐스팅과 합 (sum의 dim)
결과 — (4, 5) 그리고 [5, 7, 9] [6, 15]
왜 — (4,1)과 (1,5)는 1인 쪽이 늘어나 (4,5)가 돼요. dim=0은 위아래로 합쳐 열마다(1+4, 2+5, 3+6), dim=1은 좌우로 합쳐 행마다(6, 15) 합해요. (2,3)+(2,)처럼 오른쪽 끝 3과 2가 다르고 1도 아니면 에러예요.
shape은 맨 오른쪽부터 짝을 지어 보고, dim은 "그 번호의 차원이 사라진다"고 생각하세요. dim=0이면 앞 차원이 사라져요.
유형 3. 상속·super·오버라이딩 출력 (문제샘플 2번)
결과 — Bori가 멍멍 짖습니다. 한 줄만 나와요.
왜 — super().__init__(name)이 부모 초기화를 직접 불러 name이 생겨요. speak는 Dog가 다시 써서(오버라이딩) 자식 것만 실행되고 부모 것은 같이 실행되지 않아요. 만약 super().__init__(name) 줄이 없으면 dog.name을 읽을 때 AttributeError가 나요.
"자식이 __init__을 쓰면 부모 __init__은 자동 실행"이라는 보기는 항상 틀려요. "부모와 자식이 차례로 실행"도 틀려요.
유형 4. 모델 만들기와 호출 과정 (문제샘플 3번)
결과 — (A) nn.Linear(3, 2), (B) self.fc(x). 호출 과정은 "상속받은 __call__()의 호출 처리를 거쳐 forward() 실행"이에요.
왜 — Linear는 (입력 개수, 출력 개수) 순서로 써요. (B)에 self.fc만 쓰면 층 자체를 돌려줄 뿐 계산이 안 돼요. model(x)가 __init__을 다시 실행한다는 보기는 틀려요. __init__은 모델을 만들 때 한 번만 돌아요. 참고로 Linear(3,2)의 파라미터는 3×2+2 = 8개예요.
① Linear(입력, 출력) 순서 확인 ② 호출은 self.fc(x)처럼 괄호가 있는 보기 ③ 호출 과정은 "__call__ → forward"인 보기를 고르세요.
유형 5. gradient 값 손계산
결과 — 6.0 16.0 -24.0 그리고 4.0 → 16.0 → 32.0
왜 — pred = 2×3 = 6, loss = (6−10)² = 16이에요. loss를 w로 미분하면 2(wx−t)·x = 2×(−4)×3 = −24예요. 방법은 chain rule든 한 번에 미분이든 값만 맞으면 돼요. 누적은 "덮어쓰기"가 아니라 "더하기"라서 4 + 12 = 16이고, zero_()로 지운 뒤 w⁴의 미분 4w³ = 32만 남아요.
미분은 x²→2x, x³→3x², x⁴→4x³만 알면 돼요. zero_grad가 없으면 "더해진다"가 정답이에요. backward 직후에 w 값은 그대로예요.
유형 6. DataLoader의 배치 수와 크기 (문제샘플 4번)
결과 — 10 3 / [4, 4, 2] / [53.0, 59.0]
왜 — 샘플 10개를 4개씩 자르면 4, 4, 2라서 batch가 3개예요. for가 끝난 뒤의 batch_y는 마지막 batch의 정답이에요. 마지막은 8번·9번 샘플이고 y = x₀ + 2x₁ + 3이니 (16,17) → 53, (18,19) → 59예요.
① len(dataset)은 샘플 수 ② len(loader)는 올림(샘플÷batch) ③ batch_x·batch_y가 마지막 값이면 마지막 묶음의 값, 이 세 가지만 확인하면 보기가 거의 한 개로 줄어요.
유형 7. 학습 함수의 역할 (문제샘플 5번)
결과 — "optimizer.step()은 저장된 기울기를 이용해 optimizer에 전달된 파라미터를 갱신한다"가 정답이에요.
왜 — 역할이 서로 섞이지 않게 기억하세요. zero_grad는 기울기를 지우고(파라미터 값은 그대로), criterion은 loss만 계산하고, backward는 기울기를 만들어 저장만 하고, step은 그 기울기로 값을 고쳐요. 순서가 backward → zero_grad → step이면 기울기가 지워져서 값이 안 바뀌어요.
"~까지 한다"가 붙은 보기(backward가 값까지 갱신, step이 기울기까지 계산)는 역할을 섞은 오답이에요.
유형 8. loss의 shape 함정과 epoch 평균
결과 — 6.0 2.0 그리고 3.6
왜 — (3,1)과 (3,)을 그대로 빼면 에러가 아니라 3×3으로 브로드캐스팅되어 틀린 값(6.0)이 나와요. 맞춰서 (3,1)끼리 빼면 (1+1+4)/3 = 2예요. epoch 평균은 batch loss에 샘플 수를 곱해 더한 뒤 전체 샘플 수(10)로 나눠요. 그냥 평균 4.0은 작은 마지막 batch를 부풀려요.
prediction과 target의 shape이 다르면 "경고만 나오고 값이 틀려진다"가 정답이에요. 에러가 난다는 보기는 함정이에요.
⑤ 서술형처럼 묻는다면 — 3줄 답 10분
객관식이 중심이지만 개념 설명 문제는 이 문장들을 고르면 돼요.
1. model(x)가 forward를 실행하는 이유는?
2. backward()와 step()의 차이, zero_grad가 필요한 이유는?
backward()는 gradient를 계산해 .grad에 저장(누적)할 뿐 값은 바꾸지 않고, step()은 저장된 gradient로 파라미터를 갱신한다. gradient는 더해지며 쌓이므로 매 step 시작에 zero_grad()로 초기화한다.
3. nn.Parameter와 일반 텐서의 차이는?
nn.Parameter는 모델에 자동 등록되어 parameters()에 나오고 optimizer로 업데이트된다. 일반 텐서는 requires_grad=True여도 등록되지 않아 gradient는 계산되어도 업데이트되지 않는다.
4. epoch와 batch, DataLoader의 관계는?
DataLoader는 Dataset의 샘플을 batch_size개씩 묶어 내주고, batch 하나로 weight를 한 번 업데이트(step)한다. 모든 batch를 한 번 쓰면 학습 데이터 전체를 한 번 사용한 것이므로 1 epoch이다.
안 봐도 되는 것 (시간 아끼기)
- 주피터랩 설정·단축키, Kernel Interrupt/Restart (교수님 — 시험은 개념 위주)
- Colab 클릭 순서의 세부, GPU 종류(A100 등)
- chain rule 수식의 증명, 복잡한 미분 (값만 맞게 구하면 된다고 함)
- "no_grad 없이 제자리 수정하면 왜 에러인지" 내부 이유 (교수님도 따로 알아보겠다고 한 부분)
- Adam 같은 다른 optimizer의 내부 식, CrossEntropyLoss의 식 (이름만)
- Week05 뒤쪽의 FashionMNIST · transform · train_one_epoch/evaluate 함수 · accuracy (PPT가 아직 반만 준비됨. 범위는 DataLoader 학습 예제까지)
- 과제1의 세부 숫자(loss 174.11 → 96.75 등), hook·상태 관리의 내부 동작
시험 날 아침 30분
- 퀴즈 → "틀린 문제만 다시" (10분)
- 위 ① 두 줄(학습 5단계, 모델 틀)을 종이에 한 번 써 보기 (5분)
- ③ "꼭 외울 것" 표를 훑기 (10분)
- ④ 코드 유형 8개의 "이렇게 고르세요" 상자만 읽기 (5분)
코드 문제는 여백에 shape과 숫자를 한 줄씩 적으며 따라가세요. 눈으로만 풀면 틀려요. 보기 중 "항상 · 자동으로 · 아무것도 안 한다" 같은 극단적인 말이 들어간 건 대부분 오답이에요. 모르면 소거법으로 두 개까지 줄여 찍어요.
위 내용을 다 봤으면 마지막으로 핵심 문제 47개를 풀어요. 틀린 건 해설만 읽고 넘어가면 돼요.
핵심 문제 풀기