I-JEPA

전찬욱·2026년 2월 25일

uv로 venv 만들기

특정 파이썬 버전으로 생성

uv venv --python 3.8

uv 자체를 업데이트

uv self update

uv로 pip를 업데이트

uv pip install --upgrade pip

파이썬 라이브러리 의존성 갖추기

별도의 환경파일이 없으므로 직접 하면 되고 python 3.8 기준으로는 설치할 수 있는 pytorch 버전에 제약이 있다.
PyTorch 2.5.0 버전부터는 Python 3.8 지원이 중단되었다.

pip install torch==2.4.1 torchvision==0.19.1 torchaudio==2.4.1 --index-url https://download.pytorch.org/whl/cu124

토치 이외에는 토치비전(이건 토치랑 같이 깔릴거임. 또는 토치에 맞춰서 설치하며 ㄴ된다.)
pyyaml, numpy, opencv, submitit 이 필요하다.

pip install PyYAML

pip install numpy

pip install opencv-python

pip install submitit

데이터 갖추기

imagenet 1k도 있고 imagenet 22k도 있다.

hf download ILSVRC/imagenet-1k --repo-type=dataset

심볼릭 링크 생성하려면 경로옵션 주면 된다.

hf download ILSVRC/imagenet-1k --repo-type dataset --local-dir .

구현 특징

bfloat16 (BF16)

  • float32 (FP32): 부호(1) + 지수(8) + 가수(23) = 32비트
  • float16 (FP16): 부호(1) + 지수(5) + 가수(10) = 16비트
  • bfloat16 (BF16): 부호(1) + 지수(8) + 가수(7) = 16비트

속도 향상: 최신 GPU 하드웨어는 16비트 연산을 더 빠르게 처리할 수 있는 특수 코어(예: NVIDIA의 Tensor Core)를 탑재하고 있어 학습 속도가 크게 향상됩니다.

자동으로 bfloat16으로 수행되어 속도와 메모리 이점을 얻고, 필요한 경우 PyTorch가 자동으로 float32로 변환하여 안정성을 유지합니다.

BF16은 Ampere 아키텍처부터 공식적으로 지원하므로 A100, 3090 이후 모델이면 정상적으로 동작한다.

Loss

논문에서는 개념적으로 두 벡터 z와 h 사이의 유클리드 거리(L2 거리)를 최소화한다고 설명하지만, 실제 구현에서는 학습 안정성을 위해 Smooth L1 Loss를 사용하는 경우가 많습니다.

L2 Loss (MSE) vs. Smooth L1 Loss

두 함수의 가장 큰 차이점은 오차가 클 때 나타납니다.

  1. L2 Loss (Mean Squared Error, MSE)
  • 수식: (예측값 - 정답값)²
  • 특징: 오차를 제곱하기 때문에, 예측이 정답과 매우 다를 경우(outlier) 손실(loss) 값이 기하급수적으로 커집니다.
  • 단점: 이 폭발적인 손실 값은 그래디언트(gradient) 또한 매우 커지게 만들어, 학습 과정에서 가중치가 비정상적으로 튀는 '그래디언트 폭발(exploding gradients)' 현상을 일으킬 수 있습니다. 이는 학습을 불안정하게 만듭니다.
  1. Smooth L1 Loss
  • 특징: 이 함수는 L1 Loss와 L2 Loss를 현명하게 결합한 하이브리드 형태입니다. (Fast R-CNN 논문에서 처음 제안되었습니다.)
  • 오차가 작을 때 (e.g., |오차| < 1): L2 Loss처럼 오차를 제곱하여 계산합니다. (0.5 * 오차²)
    • 장점: 최적점에 가까워졌을 때, 그래디언트가 점차 작아져 부드럽고 안정적으로 수렴하도록 돕습니다.
  • 오차가 클 때 (e.g., |오차| ≥ 1): L1 Loss처럼 오차의 절댓값에 비례하여 계산합니다. (|오차| - 0.5)
    • 장점: 오차가 아무리 커져도 손실 값이 선형적으로만 증가하므로, 그래디언트가 폭발하지 않고 일정하게 유지됩니다. 이는 L2 Loss의 가장 큰 단점인 'outlier에 대한 민감성'을 해결해 줍니다.

EMA

모멘텀은 EMA 공식을 제어하는 핵심 파라미터로, SGD나 Adam 옵티마이저랑 다른 개념이다.
"모멘텀(m)은 EMA 계산에서 과거 값(target_encoder의 이전 가중치)에 얼마나 큰 가중치를 부여할지를 결정하는 계수(coefficient)입니다."

target_encoder를 업데이트 할 때는 가중치를 업데이트하는 식으로 되어있다.

param_k_new = (m * param_k_old) + ((1 - m) * param_q)

m 값이 0.99라는 것은, 새로운 target_encoder 가중치의 99%는 기존 자신의 가중치에서 가져오고, 단 1%만 새로운 encoder의 가중치에서 가져와 섞는다는 의미입니다.

이 때문에 target_encoder는 encoder의 변화를 매우 느리게, 부드럽게 따라가는 "느리게 움직이는 평균(slow-moving average)"이 될 수 있습니다. 그리고 momentum_scheduler가 m 값을 1.0에 가깝게 점진적으로 증가시키므로, 학습이 진행될수록 target_encoder는 점점 더 느리게 업데이트되어 더욱 안정적인 '정답'을 제공하는 역할을 하게 됩니다.

Positional Embedding

학습 루프가 시작되지 전 모델이 처음 생성될 때 필요한 모든 positional embedding이 미리 계산되어 모델 내에 저장된다.

context encoder와 target encoder에서는 입력으로 이미지를 패치로 잘라서 들어가는데, 이 패치에 위치 임베딩을 더해준다.

predictor에서는 context를 보고 target을 예측하는데 이때 위치 정보를 더 정교하게 사용해야한다.
패치 개수에 상관없이 단 하나의 공유된 mask token을 만든다. target 블록들의 위치에 해당하는 predictor의 positional embedding을 가져와서 복제된 mask token들에 각각 더해준다. 이러면 mask token 자체는 하나였지만 값들은 모두 다르게 된다.

  1. 왜 '더하기'가 위치 정보의 전달인가?
    우리가 벡터 AA와 벡터 BB를 더해 새로운 벡터 CC를 만들면(A+B=CA + B = C), 결과물인 CC 안에는 AA의 성분과 BB의 성분이 모두 섞여 있습니다.
  • Mask Token (MM): "여기는 빈칸이야"라는 의미를 담은 768차원(예시) 벡터입니다.
  • Positional Embedding (PiP_i): "ii번째 좌표"라는 고유한 기하학적 의미를 담은 768차원 벡터입니다.

이 둘을 더한 M+PiM + P_i는 트랜스포머 입장에서는 다음과 같은 의미를 가진 단일 입력값이 됩니다.

"여기($P_i$)에 있는 빈칸($M$)을 채워봐."

이 값이 트랜스포머의 Predictor로 들어가면, Predictor 내부의 가중치들은 이 벡터를 보고 "아, MM 성분이 있으니 예측을 해야겠군.
그런데 PiP_i 성분이 섞여 있으니 그 위치는 바로 거기구나!"라고 인지하게 됩니다.

  1. '학습'과 '사전 계산'의 정교한 조화질문하신 내용 중 "사전 계산된 값이 더해지는 게 어떻게 학습인가?"에 대한 핵심 답변입니다.
  • 위치 정보(PP): 보통 Sinusoidal(사인/코사인) 함수로 미리 계산된 고정값을 씁니다. 이건 모델에게 "지도의 위도와 경도 체계"를 미리 알려주는 것과 같습니다. 지도는 변하지 않습니다.
  • 학습 내용: 모델은 지도를 만드는 법을 배우는 게 아니라, "그 지도 위에서 길을 찾는 법"을 배웁니다.

"좌표 (10,10)(10, 10)을 채워야 할 때는 좌표 (9,10)(9, 10)(11,10)(11, 10)에 있는 정보를 중점적으로 봐야 하는구나!"라는 관계성(Relationship)을 Predictor의 가중치들이 학습하는 것입니다.

  1. 정리하자면패치마다 다른 정보를 전달하는 메커니즘은 다음과 같습니다.
    a. 입력 단계: shared_mask_token이라는 똑같은 재료에, 위치마다 다른 position_embedding을 더해서(Element-wise Sum) 각기 다른 벡터를 만듭니다.
    b. 전달 단계: 이 벡터들이 Predictor에 들어가면, Predictor는 각 벡터에 섞인 '고유한 위치 성분'을 읽어냅니다.
    c. 추론 단계: Predictor는 "위치 AA의 마스크"와 "위치 BB의 마스크"를 서로 다른 개체로 인식하고, 주변 패치들과의 상대적 거리를 계산하여 정답을 예측합니다.

토큰 추가 방식

  • 방법 1: 벡터 덧셈 (Element-wise Addition)

    • 대상: 패치 임베딩 (내용) + 위치 임베딩 (좌표)
    • 결과: 내용과 위치 정보가 하나로 합쳐진, 의미가 더 풍부해진 단일 토큰 벡터가 생성됩니다.
  • 방법 2: 시퀀스 연결 (Concatenation)

    • 대상: Context 토큰 리스트 와 Positional Mask 토큰 리스트
    • 결과: predictor의 셀프 어텐션이 한 번에 처리할 수 있는, Context와 Mask 정보가 모두 포함된 단일 시퀀스가 생성됩니다.

모델의 동작

  • target_encoder (가장 간단한 경우)

    • 입력: 이미지 전체를 나눈 모든 패치 토큰들.
    • 셀프 어텐션의 역할: "이미지 전체를 구성하는 모든 패치들이 서로 어떻게 연관되어 있는가?"를 파악하여, 이미지 전체에 대한 가장 풍부하고 이상적인
      표현(h)을 생성합니다.
  • encoder

    • 입력: 이미지의 일부인 Context 블록에 해당하는 패치 토큰들만 입력받습니다.
    • 셀프 어텐션의 역할: "주어진 이 제한된 Context 정보(보이는 패치들)만으로, 이 부분에 대한 가장 의미 있는 표현을 만들려면 보이는 패치들끼리 어떻게
      연관시켜야 하는가?"를 학습합니다.
  • predictor (가장 복잡한 경우)

    • 입력: (A) encoder가 만든 Context 표현 + (B) 위치 정보가 주입된 Mask 토큰들.
    • 셀프 어텐션의 역할: "주어진 Context 정보와, 예측해야 할 빈칸들의 위치 정보를 모두 활용하여, 이 빈칸들에 들어갈 내용을 추론하려면 모든 정보를 어떻게
      조합하고 연관시켜야 하는가?"를 학습합니다.

0개의 댓글