- 제출기한 : 6월 8일 월요일 11:59pm
- 주의: 채점은 스크립트로 자동으로 이루어지기에 폴더 이름이 잘못되면 0점을 받게 됩니다.
제출 방법
아래 두 가지를 하나의 압축 파일(학번_hw6.zip)에 담아 Uclass 과제 게시판에 업로드해주세요.
- 프로젝트 디렉토리 — 학번을 이름으로 하는 프로젝트 디렉토리 (예:
202448015/) - 실행 화면 캡처 —
dune test실행 결과 화면,hw6_screenshot.png- 캡처 화면에는 모든 테스트 케이스의 통과 결과가 모두 보여야 합니다.
코드 파일만 제출하거나 실행 화면이 누락된 경우 감점될 수 있습니다.
- 캡처 화면에는 모든 테스트 케이스의 통과 결과가 모두 보여야 합니다.
과제 진행 시 어려운 점이 있으면 온라인 강의실 게시판을 이용해 질문하세요. 게시판을 통해 하기 어려운 질문이라면 아래 TA 이메일을 통해 문의하시기 바랍니다.
- TA 이메일: seongminkim16@gmail.com
과제 소개
마지막 관문입니다! 우리는 앞선 과제들을 통해 수학 엔진(HW4), 파서(HW3), 차원 검사기(HW5)를 모두 구축했습니다. 그러나 이 코드 트리(AST)들은 어떻게 평가되고 실행되어 훈련되는 것일까요?
이번 최종 과제에서는 AST 노드들을 순회하며 실제 텐서 값을 넣고 연산을 수행하는 명령어 처리기(Interpreter)와 기울기를 타고 내려와 파라미터를 업데이트하는 역전파(Autograd/Backward) 코어를 스스로 100% 통합 및 완성합니다.
평가 코어 (Evaluation in Interpreter)
우리가 파싱한 노드 하나를 볼 때마다 실제로 무언가 액션을 실행해서 OCaml 상의 값(Value)을 만들어 내야 합니다.
eval env expr 시스템은 주어진 expr트리 형태를 따라 밑바닥부터 파고 들어간 뒤 연산들을 돌려줍니다.
예를 들어 Forward (m, x) AST 노드를 만났다면?
- 내부에 있는 모델 트리
m을 먼저 평가해 실제 행렬 세트 값 (VModel)을 뽑아냅니다. - 텐서 트리
x를 평가해 입력 텐서 값 (VTensor)을 뽑아냅니다. - 두 스칼라 덩어리를
forward_model이라는 순전파 함수에 태워 최종 예측값 벡터를 도출합니다!
순전파 레이어 (Forward Pass)
코드 안에 존재하는 forward_model (m: model_val) (x: vec) 함수를 구현해야 합니다.
m이 선형 회귀(MLinear (w, b)) 일 때는 HW4에서 구현한 mat_vec_mul과 벡터 덧셈 연산을 이용해 $W \times x + b$ 수식을 OCaml로 표현하세요.
이 과정이 곧 딥러닝 1사이클에서의 예측값 추론 과정입니다.
역전파 최적화 루프 (Backward Pass & SGD)
오차를 계산했다면 이젠 가중치들을 역추적하여 깎아내야(Gradient Descent, SGD) 합니다!
backward_model m x dy lr 함수에 출력부에서의 오차 미분값(dy)이 첫 인자로 진입합니다.
A. 연쇄 법칙 (Chain Rule for Linear Layer)
MLinear 층을 지날 때:
- 입력 기울기(Input gradient)인 $dx$ 는 수식 $dx = W^T \cdot dy$에 의해 계산되어 이전 층으로 반환(Return)해줘야 합니다.
- 가중치 기울기(Weight gradient)인 $dW$ 는 $dy \cdot x^T$(외적)에 의해 도출됩니다.
- 편향 기울기는 그대로 $db = dy$ 입니다.
B. 파라미터 업데이트의 불변성 딜레마
OCaml은 순수 함수 기반이라 MLinear 안의 행렬 데이터를 덧씌울 수 없습니다.
따라서 가중치를 빼기 연산한 새로운 $\text{new_W} = W - lr \cdot dW$ 모델 노드 자체를 아예 새롭게 통보하여 반환하는 형식으로 뼈대를 개조해야 합니다. (이 함수는 dx와 새로 업데이트된 Model 쌍을 반환해야 합니다!)
예제 프로그램
아래의 TensorLang 코드는 간단한 모델의 학습 전후 예측값을 비교하는 프로그램입니다.
let m = seq (linear 2 4) (linear 4 1) in
let x = tensor [1.0; 0.5] in
let y = tensor [1.0] in
let pred_before = forward m x in
let m2 = train m x y 100 0.01 in
let pred_after = forward m2 x in
(pred_before, pred_after)
모든 구현이 완벽하게 끝났다면 제공된 필기체(MNIST) 훈련 데이터셋과 테스트 셋을 돌려 정확도 테스트를 실행해 보실 수 있습니다!
let x_train = load_x "train_digits.csv" in
let y_train = load_y "train_digits.csv" in
let x_test = load_x "test_digits.csv" in
let y_test = load_y "test_digits.csv" in
let m = seq (linear 64 32) (seq relu (linear 32 10)) in
let trained_m = train m x_train y_train 50 0.1 in
accuracy trained_m x_test y_test
이 과제에서 만든 신경망 엔진은 생각보다 정교해서 간단한 인식 작업을 훌륭히 수행합니다.
테스트 및 실행
구현을 마쳤다면, 터미널(Terminal)에서 아래 커맨드를 입력하여 코드의 정합성을 확인합니다.
dune test