특정 파이썬 버전으로 생성
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 .
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 이후 모델이면 정상적으로 동작한다.
논문에서는 개념적으로 두 벡터 z와 h 사이의 유클리드 거리(L2 거리)를 최소화한다고 설명하지만, 실제 구현에서는 학습 안정성을 위해 Smooth L1 Loss를 사용하는 경우가 많습니다.
L2 Loss (MSE) vs. Smooth L1 Loss
두 함수의 가장 큰 차이점은 오차가 클 때 나타납니다.
모멘텀은 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이 미리 계산되어 모델 내에 저장된다.
context encoder와 target encoder에서는 입력으로 이미지를 패치로 잘라서 들어가는데, 이 패치에 위치 임베딩을 더해준다.
predictor에서는 context를 보고 target을 예측하는데 이때 위치 정보를 더 정교하게 사용해야한다.
패치 개수에 상관없이 단 하나의 공유된 mask token을 만든다. target 블록들의 위치에 해당하는 predictor의 positional embedding을 가져와서 복제된 mask token들에 각각 더해준다. 이러면 mask token 자체는 하나였지만 값들은 모두 다르게 된다.
이 둘을 더한 는 트랜스포머 입장에서는 다음과 같은 의미를 가진 단일 입력값이 됩니다.
"여기($P_i$)에 있는 빈칸($M$)을 채워봐."
이 값이 트랜스포머의 Predictor로 들어가면, Predictor 내부의 가중치들은 이 벡터를 보고 "아, 성분이 있으니 예측을 해야겠군.
그런데 성분이 섞여 있으니 그 위치는 바로 거기구나!"라고 인지하게 됩니다.
"좌표 을 채워야 할 때는 좌표 과 에 있는 정보를 중점적으로 봐야 하는구나!"라는 관계성(Relationship)을 Predictor의 가중치들이 학습하는 것입니다.
방법 1: 벡터 덧셈 (Element-wise Addition)
방법 2: 시퀀스 연결 (Concatenation)
target_encoder (가장 간단한 경우)
encoder
predictor (가장 복잡한 경우)
encoder가 만든 Context 표현 + (B) 위치 정보가 주입된 Mask 토큰들.