과제 2: 텐서 기본 연산 (Tensor Math Engine)

과제 2: 텐서 기본 연산 (Tensor Math Engine)

환영합니다! 이번 주차에는 딥러닝 프레임워크의 가장 뼈대가 되는 선형 대수와 텐서 수학 연산을 구현합니다. 파이토치(PyTorch)나 텐서플로우(TensorFlow) 같은 거대한 라이브러리들도 내부적으로는 행렬을 더하고 곱하는 아주 작은 연산들의 모음에 불과합니다.

이번 과제의 목표는 범용 프로그래밍 언어의 기본기인 불변성(Immutability)고차 함수(Higher-order functions)를 익히는 동시에, 딥러닝에서 가장 중요한 역전파(Backpropagation) 기울기 연산 수식을 OCaml로 직접 짜보는 것입니다.


1. 함수형 프로그래밍과 불변성 (Immutability)

딥러닝 프레임워크를 개발할 때, 값이 마음대로 중간에 변해버리는 부작용(Side-effect)은 디버깅을 극도로 어렵게 만듭니다. OCaml은 기본적으로 모든 리스트와 변수가 불변(Immutable)입니다.

즉, 우리가 파이썬이나 C에서 하던 것처럼 list[i] = new_value 형태로 배열 값을 덮어쓰는 것이 불가능합니다. 텐서나 벡터에 어떤 연산을 가하고 싶다면, 파괴적 수정(Destructive update) 대신 입력 리스트를 참조하여 새로운 결과를 담은 리스트를 만들어 반환해야 합니다.

고차 함수 (Higher-Order Functions) 가이드

OCaml에서는 forwhile 루프 대신, 강력한 리스트 조작 함수인 List.mapList.fold를 애용합니다.

  • List.map f lst: 리스트의 모든 원소에 f를 적용하여 새로운 리스트를 만듭니다.
  • List.map2 f lst1 lst2: 두 리스트의 같은 위치에 있는 원소들끼리 묶어서 f를 적용합니다.
  • List.fold_left2 f acc lst1 lst2: 두 리스트를 쭉 훑으며 누적값(acc)을 업데이트합니다. (내적을 구할 때 핵심입니다!)

2. 딥러닝의 핵심 수학: 구현해야 할 이론들

src/tensor.ml 파일 내부의 TODO를 구현하셔야 합니다. 아래의 수식과 설명을 참고하세요.

A. 내적 (Dot Product)

두 벡터 $u$와 $v$가 있을 때, 내적은 같은 인덱스끼리 곱한 뒤 모두 더한 하나의 스칼라 값(Float)입니다. \(u \cdot v = \sum_{i} u_i imes v_i\) 힌트: List.fold_left2를 사용하면 초기 누적값 0.0에서 시작하여 요소끼리의 곱을 더해나갈 수 있습니다.

B. 행렬-벡터 곱 (Matrix-Vector Multiplication)

신경망의 선형 레이어(Linear Layer)는 기본적으로 가중치 행렬 $W$와 입력 벡터 $x$의 곱인 $W imes x$ 연산을 수행합니다. 가중치 행렬 $W$의 각 행(row) 벡터를 빼내어, 입력 벡터 $x$와 내적(dot)한 결과들을 새로운 벡터로 만들면 됩니다. 힌트: List.map을 사용해 $W$의 각 행 벡터에 접근하세요.

C. 전치 (Transpose) 및 외적 (Outer Product)

  • 전치 (Transpose): 행과 열을 맞바꾸는 연산($W^T$)입니다. 역전파 과정에서 역방향 기울기(Gradient)를 입력 쪽으로 흘려보낼 때 파라미터 행렬을 뒤집기 위해 필수적입니다.
  • 외적 (Outer Product): $\text{dy}$ 에 해당하는 출력 기울기 벡터와 입력 $x$ (전환된 형태)를 결합하여 행렬($dW$)을 만들어냅니다. dW = dy * x^T

D. 평균 제곱 오차 (MSE) 및 오차 미분

머신러닝이 정답을 배우기 위해서는, “자신의 예측값이 정답에서 얼마나 벗어났는가”에 대한 함수(Cost Function)가 필요합니다.

  • $\text{MSE}$: $\frac{1}{N} \sum_{i=1}^{N} (p_i - y_i)^2$ (여기서 $p$는 예측 모델 결괏값 벡터, $y$는 실제 정답 원핫 벡터)
  • $\frac{\partial}{\partial p}\text{MSE}$ (d_mse): 비용 함수를 $p$로 편미분한 값으로 역전파의 첫 진입점이 되는 그라디언트 $\text{dy}$ 입니다! \(\frac{2}{N}(p - y)\)

3. 테스트 및 실행 과제

구현을 마쳤다면, 터미널(Terminal)에서 아래 커맨드를 입력하여 코드의 정합성을 확인합니다. (처음 받았을 때는 TODO 예외가 뜨면서 빨간 줄이 표시될 것입니다!)

dune test

제출 안내

과제 폴더(전체 프로젝트)를 zip 파일로 압축하여 제출해 주시기 바랍니다. 또한, 터미널에서 dune test를 실행하여 모든 테스트가 통과(HW2 Tests Passed!)한 결과 화면을 캡쳐하여 함께 첨부해 주세요.