이미지는 패치(patch)의 격자입니다. 문장은 토큰(token)의 격자입니다. 같은 트랜스포머(Transformer)가 둘 모두를 처리합니다.
유형: Build
언어: Python
선수 지식: Phase 7 · 05 (Full Transformer), Phase 4 · 03 (CNNs), Phase 4 · 14 (Vision Transformers intro)
예상 시간: 약 45분
문제
2020년 이전까지 컴퓨터 비전(computer vision)은 곧 합성곱(convolution)이었습니다. ImageNet, COCO, 검출 벤치마크에서 최고 성능(SOTA)을 기록한 모든 모델은 합성곱 신경망(Convolutional Neural Network; CNN) 백본(backbone)을 사용했고, 트랜스포머는 언어 처리 영역의 도구였습니다.
도소비츠키 외(Dosovitskiy et al., 2020)의 논문 "An Image is Worth 16x16 Words"는 합성곱을 완전히 걷어낼 수 있음을 보였습니다. 이미지를 고정 크기 패치로 자르고, 각 패치를 선형 사영(linear projection)으로 임베딩(embedding)한 뒤, 평범한 트랜스포머 인코더(transformer encoder)에 시퀀스(sequence)로 넣어주면 됩니다. 충분한 규모(ImageNet-21k 사전학습 이상)에서는 ViT가 ResNet 기반 모델과 대등하거나 이를 앞섭니다.
ViT는 2026년의 더 넓은 흐름, 즉 "하나의 아키텍처(One architecture)로 여러 모달리티(many modalities)를 다루는" 패러다임의 시작점이기도 합니다. Whisper는 오디오를 토큰으로 만들고, ViT는 이미지를 토큰으로 만들며, 로보틱스(robotics)에는 액션 토큰(action token)이, 비디오에는 픽셀 토큰(pixel token)이 쓰입니다. 트랜스포머는 모달리티를 가리지 않습니다. 시퀀스만 넣어주면 그 안에서 학습합니다.
2026년 시점에는 ViT와 그 후속 모델들(DeiT, Swin, DINOv2, ViT-22B, SAM 3)이 비전 영역의 대부분을 차지하고 있습니다. 합성곱 신경망은 엣지 디바이스(edge device)나 지연 시간이 중요한 과제에서는 여전히 우위를 보이지만, 그 외 대부분의 스택(stack)에는 어딘가에 반드시 ViT가 들어 있습니다.
사전 테스트
2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요
1.ViT가 ImageNet에서 CNN과 비슷한 정확도에 도달하려면 훨씬 더 많은 학습 데이터가 필요한 이유는 무엇인가요?
2.224x224 RGB 이미지를 겹치지 않는 16x16 패치(patch)로 나눕니다. [CLS] 토큰을 포함하여 트랜스포머 인코더(transformer encoder)가 받는 토큰 수는 몇 개인가요?
0/2 답변 완료
개념
Step 1 — patchify
H × W × C 이미지를 N × (P·P·C) 형태의 평탄화된 패치(flat patch) 시퀀스로 자릅니다. 대표적인 설정은 224 × 224 이미지에 16 × 16 패치를 적용하는 것으로, 이 경우 768개의 값을 가진 패치가 196개 만들어집니다.
image (224, 224, 3) → 14 × 14 grid of 16x16x3 patches → 196 vectors of length 768
패치 크기(patch size)는 핵심 조절 손잡이입니다. 패치를 작게 잡으면 토큰 수가 늘어 해상도는 좋아지지만, 어텐션(attention) 비용이 이차적으로 커집니다. 반대로 패치를 크게 잡으면 더 거칠어지지만 비용은 저렴해집니다.
Step 2 — 선형 임베딩(linear embedding)
학습된 하나의 행렬이 평탄화된 각 패치를 d_model 차원으로 사영합니다. 이는 커널 크기와 스트라이드(stride)가 모두 P인 합성곱과 정확히 같은 연산입니다. 파이토치(PyTorch)에서는 말 그대로 nn.Conv2d(C, d_model, kernel_size=P, stride=P) 한 줄로 구현되며, 두 줄이면 충분합니다.
Step 3 — [CLS] 토큰을 앞에 붙이고 위치 임베딩(positional embedding) 더하기
학습 가능한 [CLS] 토큰을 시퀀스 맨 앞에 붙입니다. 이 토큰의 최종 은닉 상태(hidden state)가 분류(classification)에 사용되는 이미지 표현(image representation)이 됩니다.
위치 정보로는 학습 가능한 위치 임베딩(ViT 원본)이나, 후속 변형에서 채택된 2차원 사인파(2D sinusoidal) 임베딩을 더합니다.
2024년 이후로는 별도의 위치 임베딩 없이 회전 위치 임베딩(Rotary Position Embedding; RoPE)을 2차원으로 확장해 위치를 다루기도 합니다.
Step 4 — 표준 트랜스포머 인코더
LayerNorm → Self-Attention → + → LayerNorm → MLP → + 블록을 L개 쌓습니다. 구조 자체는 BERT와 동일하며, 비전 전용 계층은 어디에도 없습니다. 이 점이 ViT 논문이 전달하는 가장 핵심적인 교육적 메시지입니다.
Step 5 — 분류 헤드(head)
분류 과제에서는 [CLS] 토큰의 은닉 상태를 가져와 선형층(linear) → 소프트맥스(softmax)에 통과시킵니다. DINOv2나 SAM에서는 [CLS]를 버리고 패치 임베딩 자체를 그대로 사용합니다.
의미가 컸던 변형들(Variants that mattered)
모델(Model)
연도(Year)
변화(Change)
ViT
2020
원본. 고정 패치 크기, 전 영역(full global) 어텐션.
DeiT
2021
증류(distillation) 기법으로 ImageNet-1k만으로 학습 가능.
Swin
2021
이동 윈도우(shifted windows)를 사용한 계층적(hierarchical) 구조. 어텐션 비용을 준이차(sub-quadratic)로 낮춤.
DINOv2
2023
라벨 없는 자기지도 학습(self-supervised). 가장 범용적인 비전 특징.
ViT-22B
2023
22B 파라미터; 스케일링 법칙(scaling laws)이 그대로 적용됨.
SigLIP
2023
ViT와 언어 모델을 짝지어 시그모이드 대조 손실(sigmoid contrastive loss)로 학습.
ViT는 CNN이 갖고 있던 귀납 편향(inductive bias), 즉 평행이동 불변성(translation invariance)과 지역성(locality)이 거의 없습니다. 그래서 CNN 수준의 성능에 도달하려면 훨씬 많은 데이터가 필요합니다. 1억 장 이상의 라벨이 달린 이미지나 강력한 자기지도 사전학습(self-supervised pretraining)이 없으면, 같은 계산량(matched compute) 조건에서는 여전히 CNN이 앞섭니다. DeiT는 2021년 증류 기법으로 이 격차를 메웠고, DINOv2는 2023년 자기지도 학습을 통해 사실상 이 문제를 영구적으로 해결했습니다.
직접 만들기(Build It)
code/main.py를 참고하세요. 표준 라이브러리만 사용한 patchify + 선형 임베딩 + 정합성 점검(sanity check)으로 구성되어 있습니다. 학습은 포함하지 않습니다. 현실적인 규모의 ViT는 PyTorch와 수 시간 이상의 GPU 시간이 필요하기 때문입니다.
Step 1: 가짜 이미지(fake image)
24 × 24 크기의 RGB 이미지를 (R, G, B) 튜플(tuple)이 늘어선 행(row) 리스트로 만듭니다. 6×6 패치를 사용하면 16개의 패치가 생기고, 각 임베딩 벡터의 길이는 108이 됩니다.
Step 2: patchify
defpatchify(image, P):
H = len(image)
W = len(image[0])
patches = []
for i inrange(0, H, P):
for j inrange(0, W, P):
patch = []
for di inrange(P):
for dj inrange(P):
patch.extend(image[i + di][j + dj])
patches.append(patch)
return patches
격자를 가로 방향으로 먼저 훑는 래스터 순서(raster order), 즉 행 우선(row-major) 순서를 사용합니다. 모든 ViT가 동일한 순서를 사용합니다.
Step 3: 선형 임베딩(linear embed)
평탄화된 각 패치에 무작위로 초기화한 (patch_flat_size, d_model) 행렬을 곱합니다. [CLS] 토큰을 맨 앞에 붙인 뒤 출력 형태가 (N_patches + 1, d_model)이 되는지 확인합니다.
Step 4: 현실적인 ViT의 파라미터 수 세기
ViT-Base의 파라미터 수를 출력해봅니다. 설정은 12개 층(layer), 12개 헤드(head), d=768, 패치 크기 16입니다. 비교를 위한 기준은 ResNet-50(약 25M)이고, ViT-Base는 약 86M, ViT-Large는 약 307M, ViT-Huge는 약 632M 파라미터입니다.
DINOv2 임베딩은 2026년 시점 이미지 특징(image feature)의 사실상 기본값입니다. 백본을 동결(freeze)하고 그 위에 작은 헤드만 학습하는 방식으로 분류, 검색(retrieval), 검출(detection), 캡셔닝(captioning) 모두에 잘 작동합니다. 메타(Meta)가 공개한 DINOv2 체크포인트(checkpoint)는 비텍스트 비전 과제 전반에서 CLIP을 능가합니다.
패치 크기 고르기(Patch-size picking). 작은 모델은 16×16(ViT-B/16)을 사용합니다. 분할(segmentation)처럼 밀집 예측(dense prediction)이 필요한 경우에는 8×8 또는 14×14(SAM, DINOv2)를 사용합니다. 매우 큰 모델은 14×14를 주로 사용합니다.
산출물 만들기(Ship It)
outputs/skill-vit-configurator.md를 참고하세요. 이 스킬(skill)은 데이터셋 크기, 해상도, 컴퓨트 예산(compute budget)에 따라 새로운 비전 과제에 어울리는 ViT 변형과 패치 크기를 골라줍니다.
중간. 2차원 사인파 위치 임베딩(2D sinusoidal positional embedding)을 구현합니다. 각 패치의 row와 col에 대해 독립적인 사인파 코드를 만들고 둘을 연결(concatenate)해 사용합니다. 작은 규모의 PyTorch ViT에 적용해 CIFAR-10에서 학습 가능한(learnable) 위치 임베딩과 정확도를 비교합니다.
어려움. PyTorch로 3개 층짜리 ViT를 만들어 4×4 패치를 사용해 MNIST 이미지 1,000장으로 학습합니다. 테스트 정확도를 측정한 뒤, 같은 1,000장에 대해 DINOv2식 사전학습을 단순화한 버전(인코더가 마스킹된 패치의 임베딩을 예측하도록 학습)을 추가해 정확도가 개선되는지 확인합니다.
핵심 용어
용어
흔한 설명
실제 의미
패치(Patch)
"비전 트랜스포머의 토큰"
이미지의 P × P × C 영역에 해당하는 픽셀 값을 평탄화한 벡터다.
Patchify
"자르고 평탄화하기"
이미지를 겹치지 않는 패치로 나누고, 각 패치를 벡터로 평탄화한다.
[CLS] 토큰
"이미지 요약 토큰"
시퀀스 맨 앞에 붙이는 학습 가능한 토큰이며, 그 최종 임베딩이 이미지 표현으로 사용된다.
귀납 편향(Inductive bias)
"모델이 미리 가정하는 것"
ViT는 CNN보다 사전 가정이 적기 때문에 그 공백을 메우려면 더 많은 데이터가 필요하다.
DINOv2
"자기지도 ViT"
이미지 증강(augmentation)과 모멘텀 교사(momentum teacher)를 사용해 라벨 없이 학습한 모델. 2026년 시점 가장 범용적인 이미지 특징이다.
SigLIP
"CLIP의 후속"
ViT와 텍스트 인코더를 시그모이드 대조 손실(sigmoid contrastive loss)로 함께 학습하며, 같은 컴퓨트 조건에서 CLIP보다 강하다.
Swin
"윈도우 기반 ViT"
지역 어텐션(local attention)과 이동 윈도우(shifted windows)를 결합한 계층적 ViT로, 어텐션 비용이 준이차(sub-quadratic)다.
레지스터 토큰(Register tokens)
"2023년의 트릭"
어텐션 싱크(attention sink)를 흡수해주는 몇 개의 추가 학습 가능 토큰. DINOv2 특징을 개선한다.