|
|
[딥러닝] Vision Transformer (ViT)
— 패치 임베딩, CLS 토큰, 인코더 내부, 하이브리드, 해상도 파인튜닝
1장. 사전 지식 — CNN, LLM, ViT의 벡터화는 어떻게 다른가
■ 왜 이 비교부터 하는가
ViT는 "이미지를 문장처럼 다루는 모델"이다. 이미지를 조각내고, 그 조각을 단어처럼 취급해 트랜스포머에 넣는다. 그런데 이 한 문장을 제대로 이해하려면 CNN이 이미지를 다루는 방식, 그리고 언어 트랜스포머가 단어를 다루는 방식과 각각 무엇이 같고 무엇이 다른지를 먼저 구분해야 한다.
■ CNN — 위치 정보가 구조에 내장되어 있다
CNN은 슬라이딩 커널로 이미지를 훑어 특징을 추출하고, 그 결과를 2D 특징맵(H×W×C)으로 유지한다. 특징맵의 형태 자체가 원본 이미지의 공간 배치를 그대로 반영하므로, 위치 정보를 따로 주입할 필요가 없다.
더 중요한 것은 CNN이 두 가지 가정을 구조에 하드코딩하고 있다는 점이다. 첫째는 지역성(locality)으로, 커널이 정해진 크기의 이웃 픽셀만 보므로 "가까운 픽셀끼리 관련이 있다"는 전제가 연산 자체에 박혀 있다. 둘째는 이동 등변성(translation equivariance)으로, 같은 커널을 이미지 전역에 반복 적용하므로 "같은 패턴이면 어디에 있든 같은 특징"이라는 전제가 성립한다. 이 두 가정을 귀납적 편향(inductive bias)이라고 부른다.
■ 언어 트랜스포머 — 어휘사전에서 벡터를 검색한다
언어 모델은 미리 정해진 유한한 어휘사전(vocabulary)을 갖는다. 각 단어(또는 서브워드)에는 고유 ID가 부여되고, 그 ID로 임베딩 테이블에서 정확히 하나의 벡터를 찾아온다. 검색(lookup) 방식이며, 이산적이다. 같은 단어는 문맥과 무관하게 항상 같은 초기 벡터를 받는다.
그리고 토큰화하는 순간 원래의 순서 정보가 사라진 "순서 없는 집합"이 되므로, 위치 인코딩을 명시적으로 더해 순서를 다시 주입한다.
■ ViT — 픽셀 값을 실시간으로 행렬 변환한다
ViT에는 어휘사전이 없다. 이미지를 16×16 같은 고정 크기로 기계적·균등하게 쪼갠 뒤, 각 패치의 실제 픽셀 값(RGB)을 학습 가능한 선형 변환(행렬 곱)에 통과시켜 그 자리에서 벡터를 계산한다. 정해진 의미 단위를 찾아오는 것이 아니라, 그 조각의 실제 내용을 그대로 계산해 벡터화한다.
논문은 ViT가 이미지 특유의 귀납적 편향을 거의 갖지 않는다고 명시한다. 원문에 따르면 ViT에서 지역성과 이동 등변성을 갖는 것은 MLP 계층뿐이고, 셀프 어텐션 계층은 전역적이다. 2차원 이웃 구조가 사용되는 지점은 딱 두 곳 — 모델 초입에서 이미지를 패치로 자를 때, 그리고 파인튜닝 시 해상도가 달라져 위치 임베딩을 조정할 때뿐이다. 그 외에는 패치 간의 모든 공간적 관계를 처음부터 학습해야 한다.
■ 세 방식의 정리
• CNN — 커널이 이웃 픽셀만 보고, 특징맵 구조가 위치를 자동 보존. 지역성·이동 등변성이 구조에 내장
• 언어 트랜스포머 — 어휘사전에서 ID로 벡터 검색(이산적), 위치 인코딩을 더해 순서 재주입
• ViT — 어휘사전 없음. 패치의 픽셀 값을 행렬 곱으로 실시간 변환, 위치 임베딩을 더해 위치 재주입
"토큰 시퀀스를 만들고 위치 정보를 더한다"는 큰 틀은 ViT와 언어 트랜스포머가 동일하다. 그러나 토큰을 만드는 방법(사전 검색 vs 픽셀 실시간 변환)은 근본적으로 다르다.
【쉽게 다시 말하면】
CNN은 "가까운 것끼리 관련 있다"는 규칙을 처음부터 알고 시작하는 모델이다. ViT는 그 규칙조차 모른 채 시작해서, 데이터를 보며 스스로 알아내야 하는 모델이다. 대신 그 규칙에 얽매이지 않으므로 더 자유롭게 관계를 찾을 수 있다.
[그림 1] 세 방식의 벡터화 비교 — CNN(커널 슬라이딩 → 2D 특징맵), 언어(어휘사전 검색), ViT(패치 픽셀 → 행렬 곱).
▶ 핵심 한 줄 : ViT는 CNN이 공짜로 갖는 "가까운 것이 관련 있다"는 전제를 버리고, 그 관계를 데이터로부터 처음부터 학습한다.
2장. 패치 분할과 임베딩
■ 블록도 상 위치
파이프라인 최전방. 원본 이미지가 들어와 트랜스포머 인코더가 처리할 수 있는 벡터 시퀀스로 변환되는 구간이다.
■ 기능 — 이미지를 토큰 시퀀스로 만든다
표준 트랜스포머는 1차원 토큰 임베딩 시퀀스를 입력으로 받는다. 2차원 이미지를 그대로 넣을 수 없으므로, 이미지를 고정 크기 패치로 나눠 1차원 시퀀스로 재배열해야 한다.
■ 구현 — 분할, flatten, 선형 projection
원본 이미지의 형태를 H×W×C라 하고, 패치 하나의 크기를 P×P라 하면, 패치 개수는 다음과 같다.
N = HW / P²
예를 들어 224×224 이미지를 16×16 패치로 자르면 가로세로 각각 224÷16 = 14개씩, 총 N = 14×14 = 196개가 나온다. 이 N이 곧 트랜스포머의 실효 입력 시퀀스 길이다.
패치 하나는 P²·C개의 숫자 뭉치다. 16×16×3 = 768개의 RGB 값이다. 이를 한 줄로 편(flatten) 뒤, 학습 가능한 선형 projection 행렬 E에 통과시켜 D차원 벡터로 만든다. 논문에서 이 결과를 패치 임베딩(patch embedding)이라 부른다.
E ∈ ℝ^((P²·C) × D)
여기서 D는 트랜스포머가 모든 계층에서 일정하게 유지하는 잠재 벡터 크기다. ViT-Base 기준 D = 768이다.
패치 크기 선택은 트레이드오프다. 논문이 지적하듯 시퀀스 길이는 패치 크기의 제곱에 반비례하므로, 패치를 작게 할수록 계산 비용이 급격히 늘어난다. 반대로 패치를 크게 하면 한 조각이 담는 디테일이 뭉개진다.
■ 이 단계에서 아직 "의미 파악"은 일어나지 않는다
주의할 점은 선형 projection이 그 자체로 의미를 아는 연산이 아니라는 것이다. 행렬 E는 처음에 무작위 값으로 초기화되며, 단지 숫자를 다른 숫자로 바꾸는 계산일 뿐이다. 학습이 진행되면서 비슷한 내용의 패치가 비슷한 벡터로 변환되도록 E의 값이 조정될 뿐이고, 패치들 사이의 관계를 따지는 일은 이 단계가 아니라 뒤의 셀프 어텐션에서 일어난다.
실제로 논문은 학습된 임베딩 필터의 주성분을 분석한 결과, 그 성분들이 패치 내부의 미세 구조를 저차원으로 표현하는 기저 함수와 유사한 형태를 띤다고 보고했다.
【쉽게 다시 말하면】
케이크를 자를 때 "여기가 딸기니까 여기서 잘라야지" 하고 의미 단위로 자르는 게 아니라, 자를 대고 똑같은 크기로 격자를 그어 자르는 것과 같다. 조각 안에 뭐가 들어있는지는 자르는 시점에 고려하지 않는다.
[그림 2] 224×224 이미지가 16×16 패치 196개로 분할되고, 각 패치가 flatten → 선형 projection을 거쳐 D차원 벡터가 되는 과정. 논문 Figure 1 왼쪽 부분 참고
▶ 핵심 한 줄 : 의미 단위가 아니라 고정 크기로 기계적으로 자른 뒤, 픽셀 값을 학습되는 행렬에 통과시켜 벡터로 만든다.
3장. CLS 토큰과 위치 임베딩
■ 블록도 상 위치
패치 임베딩 직후, 트랜스포머 인코더에 들어가기 직전.
■ BERT란 무엇이었나
CLS 토큰을 이해하려면 BERT를 먼저 짚어야 한다. BERT(Bidirectional Encoder Representations from Transformers, Devlin et al., 2019)는 원조 트랜스포머에서 인코더만 떼어 쓰는 모델이다. 번역처럼 시퀀스를 생성하는 것이 목적이 아니라 언어 표현을 학습하는 것이 목적이므로 디코더가 필요 없다.
BERT의 사전학습 과제는 두 가지다. 하나는 Masked Language Modeling으로, 입력 토큰의 15%를 무작위 선택해 그중 80%는 [MASK]로 가리고 10%는 다른 무작위 토큰으로 바꾸고 10%는 그대로 둔 뒤 원래 토큰을 맞히게 한다. 80/10/10으로 나누는 이유는, 항상 [MASK]만 보여주면 실제 사용 시점에는 [MASK]가 등장하지 않아 학습과 실전 사이에 괴리가 생기기 때문이다. 다른 하나는 Next Sentence Prediction으로, 두 문장이 실제로 이어지는지를 판단한다.
BERT의 입력 표현은 세 가지 임베딩의 합이다. 토큰 임베딩(WordPiece 서브워드 단위), 세그먼트 임베딩(문장 A/B 구분), 위치 임베딩을 각 토큰마다 더한다. 그리고 시퀀스 맨 앞에는 항상 [CLS] 토큰을, 문장 경계에는 [SEP] 토큰을 붙인다. 분류 과제에서는 [CLS] 위치의 최종 은닉 상태만 뽑아 분류기에 넣는다.
BERT-base는 12개 레이어, hidden size 768, 헤드 12개로 110M 파라미터이며, BERT-large는 24개 레이어, hidden size 1024, 헤드 16개로 340M 파라미터다.
한 가지 구분해둘 것은, BERT는 양방향으로 문맥을 보며 빈칸을 채우는 인코더 전용 "이해" 모델이고, GPT 계열은 왼쪽에서 오른쪽으로만 보며 다음 토큰을 생성하는 디코더 전용 "생성" 모델이라는 점이다. 두 계열은 근본적으로 다르다.
■ ViT의 CLS 토큰 — 기능
논문은 BERT의 [class] 토큰과 유사하게, 패치 임베딩 시퀀스 맨 앞에 학습 가능한 임베딩 하나를 prepend한다고 명시한다. 이 토큰이 트랜스포머 인코더를 통과한 뒤의 상태가 이미지 전체를 대표하는 표현이 된다.
■ 구현
CLS 토큰은 어떤 실제 패치와도 대응되지 않는 가상의 자리다. 다른 학습 가능한 임베딩들과 동일하게 작은 무작위 값으로 초기화되며, 0벡터로 두지 않는다. 0벡터로 시작하면 그 벡터에서 만들어지는 q·k·v가 모두 0이 되어 학습 초기에 다른 패치들에게 아무 특징도 제공하지 못하는 상태로 출발하기 때문이다.
인코더를 L번 통과한 뒤, CLS 위치의 최종 출력만 분류에 사용한다. 나머지 패치 토큰의 최종 출력은 분류에 쓰이지 않는다.
논문 부록 D.3에는 CLS 토큰 대신 모든 패치 출력을 global average pooling하는 방식에 대한 실험도 있다. 결론은 두 방식 모두 잘 작동하되 학습률 설정을 적절히 맞춰야 한다는 것이었다. CLS 토큰은 유일한 정답이라기보다 BERT와의 설계 일관성을 위한 선택에 가깝다.
■ CLS만 쓰면 나머지 패치는 덜 중요한가
그렇지 않다. CLS가 좋은 표현을 만들려면 끌어모을 정보 자체가 좋아야 한다. 또한 셀프 어텐션에서는 CLS만 패치를 보는 것이 아니라 모든 패치가 서로를 본다. 패치들은 층을 거듭하며 서로 정보를 주고받아 점점 풍부한 표현이 되고, CLS는 그 과정에 참여하다 마지막에 결과를 대표로 내보낼 뿐이다. 학습 관점에서도 패치의 k와 v를 만드는 변환식은 CLS의 최종 출력에 기여한 만큼 오차 신호를 그대로 받는다.
■ 위치 임베딩 — 기능과 구현
패치로 자르는 순간 순서 정보가 사라지므로, 위치 정보를 명시적으로 더해준다. 논문은 학습 가능한 1차원 위치 임베딩을 표준으로 채택했다. 더 정교한 2D-aware 위치 임베딩도 실험했으나 유의미한 성능 향상이 관찰되지 않았기 때문이다.
E_pos ∈ ℝ^((N+1) × D)
N+1인 이유는 패치 N개에 CLS 토큰 1개가 추가되기 때문이다. 결합 방식은 원소별 덧셈이며, 이는 언어 트랜스포머와 동일하다. 다만 언어 트랜스포머 원본은 고정된 sin/cos 함수를 쓰고 ViT는 학습되는 벡터를 쓴다는 차이가 있다.
여기까지를 식으로 정리하면 다음과 같다.
z₀ = [x_class ; x¹ₚE ; x²ₚE ; ⋯ ; x^Nₚ E] + E_pos
흥미로운 점은 초기화 시점의 위치 임베딩이 2차원 위치에 대한 정보를 전혀 담고 있지 않다는 것이다. 그럼에도 학습이 끝난 뒤 분석해보면, 가까운 패치들끼리 위치 임베딩의 유사도가 높아지고 행·열 구조가 나타난다. 즉 이미지의 2D 위상을 스스로 학습해낸다. 논문은 이것이 수작업으로 만든 2D-aware 변형이 성능 향상을 주지 못한 이유라고 설명한다.
【쉽게 다시 말하면】
CLS는 "이 이미지 전체를 대표할 자리"로 미리 비워둔 좌석이다. 처음엔 아무 내용도 없지만, 어텐션을 거치며 다른 패치들의 정보를 끌어모으도록 학습된다.
[그림 3] CLS 토큰이 패치 시퀀스 앞에 붙고 위치 임베딩이 더해지는 구조. 논문 Figure 1 중앙 부분 참고
▶ 핵심 한 줄 : CLS는 BERT에서 가져온 "전체를 대표하는 빈 좌석"이고, 위치 임베딩은 학습되는 벡터를 원소별로 더해 사라진 위치 정보를 되돌린다.
4장. 트랜스포머 인코더 내부
■ 블록도 상 위치
파이프라인의 심장부. 위치 임베딩까지 더해진 벡터 시퀀스가 들어와, 동일한 구조의 블록을 L번 반복 통과한다.
■ 전체 구조 — 두 개의 덩어리, 두 개의 잔차연결
논문은 인코더가 멀티헤드 셀프 어텐션(MSA)과 MLP 블록이 교대로 배치된 구조이며, LayerNorm은 모든 블록 앞에, 잔차연결은 모든 블록 뒤에 적용된다고 명시한다. 식으로 쓰면 다음과 같다.
z'ℓ = MSA(LN(z_{ℓ-1})) + z_{ℓ-1}
zℓ = MLP(LN(z'ℓ)) + z'ℓ (ℓ = 1 … L)
한 블록 안에 계산 덩어리가 둘(MSA, MLP)이고, 각 덩어리마다 LN이 앞에, 잔차연결이 뒤에 붙는 구조다.
여기서 짚어둘 것은 LayerNorm의 위치다. 원조 트랜스포머(Attention Is All You Need)는 연산 후에 LN을 적용하는 Post-LN 구조였으나, ViT는 연산 전에 LN을 적용하는 Pre-LN 구조를 채택했다. 학습 안정성 때문이다.
■ 4-1. Q, K, V 생성
기능 — 각 토큰 벡터로부터 어텐션 계산에 쓸 세 가지 역할의 벡터를 만든다.
구현 — 세 벡터 모두 같은 입력에서 만들어진다. 논문 부록 A의 식은 다음과 같다.
[q, k, v] = z · U_qkv , U_qkv ∈ ℝ^(D × 3Dₕ)
구현상으로는 하나의 큰 행렬로 묶어 한 번에 계산하지만, 개념적으로는 서로 다른 세 개의 변환에 해당한다. 여기서 중요한 것은 v 역시 "날것의 입력"이 아니라 q, k와 똑같이 학습되는 변환을 거친 가공물이라는 점이다. 셋의 차이는 재료가 아니라 역할이다.
• q(query) — 이 토큰이 무엇을 찾고 있는지를 표현
• k(key) — 이 토큰이 무엇을 갖고 있는지를 다른 토큰이 알아볼 수 있게 표현
• v(value) — 실제로 전달되어 결과에 섞이는 알맹이 정보
q와 k는 점수를 매기는 데만 쓰이고 결과물에 직접 들어가지 않는다. 결과물에 들어가는 것은 v다.
■ 4-2. q와 k가 달라야 하는 이유 — 방향성
만약 q와 k를 같은 변환으로 만든다면, 선형대수적으로 "A가 B를 보는 점수"와 "B가 A를 보는 점수"가 항상 같아진다. 같은 행렬로 만들어진 벡터들 사이의 내적 행렬은 대칭이기 때문이다.
그러나 실제 관계에는 방향이 있다. 어떤 토큰이 다른 토큰을 강하게 참조해야 하지만 그 역은 성립하지 않는 경우가 흔하다. q와 k를 별개의 변환으로 두면 이 대칭성이 깨지고, A→B와 B→A가 서로 다른 값을 가질 수 있게 된다. 즉 같은 두 토큰의 관계를 관점에 따라 다르게 측정할 수 있다.
이것은 "같으면 표현할 수 없는 패턴이 생긴다"는 구조적 필연성에 해당한다.
■ 4-3. k와 v가 달라야 하는 이유 — 자유도
k와 v의 분리는 q≠k만큼의 수학적 필연성은 없다. k = v로 두어도 어텐션 계산 자체는 성립한다.
분리의 이유는 학습 자유도에 있다. 매칭에 유리한 표현과 실제 전달에 유리한 표현이 항상 일치하지는 않는다. 두 역할을 하나의 파라미터에 묶으면 한쪽을 최적화할 때 다른 쪽이 손해를 보는 트레이드오프가 발생한다. 별개의 변환으로 두면 각자 자기 목적에 맞게 독립적으로 조정될 수 있다.
즉 q≠k는 "같으면 안 되는 것"이고, k≠v는 "같아도 되지만 나누는 편이 나은 것"이다. 이유의 강도가 다르다.
【쉽게 다시 말하면】
도서관 책에 비유하면 k는 책을 찾을 때 쓰는 분류 라벨이고, v는 실제로 대출해서 얻어가는 책 내용이다. 둘 다 같은 책에 대한 정보지만, 하나는 검색에 최적화된 요약이고 하나는 전달에 최적화된 알맹이다. 다만 라벨을 먼저 알아야 내용을 아는 계층 관계는 아니고, 같은 원본에서 동시에 따로 만들어진다.
■ 4-4. 관련도 계산과 softmax
기능 — 토큰 간 관련도를 계산해 합이 1인 비율로 정규화한다.
구현 — 논문 부록 A의 식 (6), (7)은 다음과 같다.
A = softmax(q kᵀ / √Dₕ) , A ∈ ℝ^(N × N)
SA(z) = A v
q와 k의 내적으로 점수를 구한 뒤, √Dₕ로 나누고, softmax로 비율화한다. √Dₕ로 나누는 것은 차원이 커질수록 내적 값의 분산이 커져 softmax가 지나치게 뾰족해지는 것을 막기 위한 스케일링이다.
여기서 관련도의 기준은 공간적 거리가 아니라 벡터 내용의 부합도다. 바로 옆 패치든 이미지 반대편 패치든 계산 방식은 동일하다. 어텐션 행렬 A의 크기가 N×N이라는 점에서 계산량이 토큰 수의 제곱에 비례한다는 것도 확인할 수 있다.
정규화된 비율이 나오면, 그 비율대로 각 토큰의 v를 가중합해 새 벡터를 만든다. 이 비율은 고정된 규칙표가 아니라 입력이 바뀔 때마다 그 자리에서 새로 계산되는 값이다.
■ 4-5. 멀티헤드 셀프 어텐션
기능 — 위 과정을 서로 다른 k개의 헤드에서 병렬로 수행하고 결과를 종합한다.
구현 — 논문 부록 A의 식 (8)은 다음과 같다.
MSA(z) = [SA₁(z) ; SA₂(z) ; ⋯ ; SA_k(z)] · U_msa
각 헤드는 자기만의 q·k·v 변환을 갖고 독립적으로 어텐션을 수행한다. 헤드 수 k를 바꿔도 전체 계산량과 파라미터 수가 일정하게 유지되도록, 헤드당 차원 Dₕ는 보통 D/k로 설정한다. ViT-Base 기준 D = 768, 헤드 12개이므로 Dₕ = 64다.
k개 헤드의 출력을 이어붙인(concat) 뒤 U_msa로 한 번 더 투영해 종합한다.
■ 4-6. 헤드의 역할 분담은 설계된 것이 아니다
헤드마다 다른 관점을 갖게 되는 것은 누가 역할을 지정해줘서가 아니다. 실제로 작동하는 메커니즘은 "오차를 줄이는 방향으로 파라미터를 조정한다" 하나뿐이며, 다양성을 추구하라는 별도의 목적함수는 존재하지 않는다.
각 헤드는 서로 다른 무작위 값으로 초기화된다. 같은 오차 신호를 받아도 현재 파라미터 값이 다르면 계산되는 조정 방향도 달라지므로, 반복될수록 헤드들이 서로 다른 방향으로 벌어진다. 그리고 그렇게 벌어진 상태가 결과적으로 오차를 더 잘 줄이므로 그 상태가 유지·강화된다.
다만 이것이 수학적으로 보장된 결과는 아니다. 헤드 프루닝 연구들은 학습이 끝난 뒤 일부 헤드가 서로 유사한 기능을 수행하고 있어 제거해도 성능 저하가 크지 않은 경우가 있음을 보였다. 다양화는 자주 관찰되는 경향이지 필연은 아니다.
【쉽게 다시 말하면】
누가 "너는 1장, 너는 2장 맡아라"라고 지시하지 않았는데도 스터디 그룹이 자연스럽게 분담하게 되는 것과 비슷하다. 다들 같은 챕터만 파면 그룹 전체 성적에 손해이므로, 성적을 올리는 방향으로 각자 움직이다 보면 갈라지는 쪽이 유리해진다. 의도된 설계가 아니라 결과가 유리해서 굳어진 상태다.
■ 4-7. 잔차연결
기능 — 각 계산 덩어리의 출력에 그 덩어리의 입력을 그대로 더한다.
구현 — 앞의 식 z'ℓ = MSA(LN(z_{ℓ-1})) + z_{ℓ-1}에서 마지막에 더해지는 z_{ℓ-1}이 잔차 경로다. 여기서 더해지는 값은 LN을 거치기 전, 계산에 들어가기 직전의 입력이다. 최초 입력이 아니라 각 단계 직전의 값이라는 점에 주의해야 한다.
잔차연결이 한 블록에 두 번 등장하는 이유는, 블록 안에 성격이 다른 계산 덩어리가 둘 있기 때문이다. MSA는 토큰끼리 정보를 섞고, MLP는 각 토큰을 독립적으로 가공한다. 서로 다른 일을 하는 두 덩어리이므로 각각 자기만의 우회 경로가 필요하다. 한쪽에만 두면 다른 덩어리를 통과할 때의 정보 손실과 학습 불안정 문제가 그대로 남는다.
효과는 두 방향 모두에 나타난다. 순전파에서는 각 블록이 원본을 완전히 대체하는 새 값을 만드는 대신 "원본 + 보정값"을 만드는 구조가 되어, 층이 깊어져도 정보가 급격히 변형되지 않는다. 역전파에서는 오차 신호가 복잡한 계산을 거치지 않고 우회 경로를 통해 곧장 이전 층까지 전달될 수 있어, 층이 깊어져도 그래디언트가 소실되지 않는다. 하나의 구조가 양방향 모두에서 이득을 준다.
■ 4-8. LayerNorm
기능 — 벡터 내부 숫자들의 분포를 정리해 다음 계산이 안정적으로 이뤄지게 한다.
구현 — 두 부분으로 구성된다. 먼저 한 벡터 안의 숫자들의 평균과 분산을 계산해 평균 0, 분산 1이 되도록 정규화한다. 그다음 학습되는 두 파라미터(스케일 γ, 이동 β)를 곱하고 더해 표현 범위를 되돌릴 여지를 남긴다.
주의할 것은 LayerNorm이 단순한 선형변환이 아니라는 점이다. 정규화 부분은 입력 벡터 자체의 통계값(평균·분산)에 따라 매번 다르게 계산되므로, 고정된 행렬 곱과는 성격이 다르다. 뒤의 스케일·이동만 떼어 보면 선형이지만, 전체를 선형변환이라고 부를 수는 없다.
■ 4-9. MLP와 GELU
기능 — 어텐션으로 섞인 각 토큰 벡터를, 다른 토큰을 참조하지 않고 독립적으로 한 번 더 가공한다.
구현 — 논문에 따르면 MLP는 GELU 비선형성을 가진 두 개의 층으로 구성된다. 구조는 다음과 같다.
선형변환(D → MLP size) → GELU → 선형변환(MLP size → D)
ViT-Base 기준 D = 768, MLP size = 3072이므로 4배로 부풀렸다가 되돌린다.
GELU(Gaussian Error Linear Unit, Hendrycks & Gimpel, 2016)의 정의는 다음과 같다.
GELU(x) = x · Φ(x)
Φ는 표준정규분포의 누적분포함수다. ReLU가 부호를 기준으로 통과 여부를 딱 잘라 결정(gating)하는 것과 달리, GELU는 입력값의 크기에 비례해 얼마나 통과시킬지를 부드럽게 조절(weighting)한다. 계산 비용 때문에 다음 근사식이 자주 쓰인다.
GELU(x) ≈ 0.5x(1 + tanh(√(2/π)(x + 0.044715x³)))
부드러운 곡선이므로 모든 지점에서 미분 가능하고, ReLU처럼 음수 구간을 완전히 0으로 죽이지 않으므로 뉴런이 학습을 멈추는 문제를 피할 수 있다. 그래디언트 흐름이 매끄러워져 깊은 네트워크에 유리하며, BERT와 GPT 계열에서도 표준으로 쓰인다.
■ 4-10. 최종 출력과 분류 헤드
블록을 L번 통과한 뒤, CLS 위치의 최종 상태에 LayerNorm을 한 번 더 적용한 것이 이미지 표현이 된다.
y = LN(z_L⁰)
이 y가 분류 헤드로 들어간다. 논문에 따르면 분류 헤드는 사전학습 시에는 은닉층 하나를 가진 MLP로, 파인튜닝 시에는 단일 선형 계층으로 구현된다.
■ 4-11. CLS는 중간에 있는데 어떻게 직접 학습되는가
역전파는 계산 그래프상 연결된 모든 지점에 예외 없이 도달하므로, 위치가 앞이든 뒤든 기여한 만큼의 신호를 받는다.
구체적으로는 이렇게 흐른다. 최종 예측은 CLS의 마지막 출력에서만 나오므로 오차가 먼저 그 지점에 꽂힌다. 이 오차가 마지막 블록을 거꾸로 통과할 때, 그 출력이 CLS의 q와 다른 패치들의 k·v가 섞여 만들어진 것이므로 셋 모두에 신호가 나뉘어 전달된다. 이 과정이 첫 블록까지 이어지고, 최종적으로는 최초에 무작위로 초기화된 CLS 임베딩 자체에도 조정 신호가 도달한다.
즉 CLS 초기 임베딩, CLS가 각 층에서 만드는 q, 그리고 다른 패치들의 k·v가 모두 하나의 최종 오차로부터 동시에 각자의 몫만큼 조정된다.
■ 모델 변형별 제원
논문의 ViT 구성은 BERT를 기반으로 정해졌다.
• ViT-Base — 12 layers, D=768, MLP size 3072, 헤드 12개, 86M 파라미터
• ViT-Large — 24 layers, D=1024, MLP size 4096, 헤드 16개, 307M 파라미터
• ViT-Huge — 32 layers, D=1280, MLP size 5120, 헤드 16개, 632M 파라미터
표기법은 ViT-L/16처럼 쓰며, 뒤의 숫자가 입력 패치 크기다.
[그림 4] 인코더 블록 한 개의 내부 구조 — LN → MSA → 잔차연결 → LN → MLP → 잔차연결, 그리고 ×L 반복 표시.
[그림 5] q·k·v 생성부터 softmax, v 가중합까지의 어텐션 계산 흐름.
▶ 핵심 한 줄 : q·k·v는 같은 입력에서 만들어진 세 가지 역할의 가공물이고, 잔차연결과 LayerNorm은 이 계산이 깊게 쌓여도 정보와 그래디언트가 무너지지 않게 지탱하는 장치다.
5장. 하이브리드, 해상도 파인튜닝, 어텐션 분석
이 장의 세 항목은 순서대로 적용하는 절차가 아니라 서로 독립적인 별개의 것들이다. ①은 모델을 만들 때의 설계 선택지, ②는 학습된 모델을 재학습시킬 때의 절차, ③은 다 만들어진 모델을 들여다보는 분석 도구다.
■ 5-1. 하이브리드 아키텍처
블록도 상 위치 — 파이프라인 최전방(1~2장 구간)을 교체한다. CLS 추가 이후는 순수 ViT와 동일하다.
기능 — 원본 이미지 패치 대신 CNN이 뽑아낸 특징맵을 입력 시퀀스로 사용한다.
구현 — 논문에 따르면 패치 임베딩 projection E가 원본 패치가 아니라 CNN 특징맵에서 추출한 패치에 적용된다. 특수한 경우로 패치의 공간 크기를 1×1로 두면, 특징맵의 공간 차원을 단순히 flatten해 트랜스포머 차원으로 투영하는 것과 같아진다. 실험에서는 ResNet50의 stage 4 출력을 쓰거나, stage 4를 제거하고 그 층수를 stage 3에 몰아넣어 4배 긴 시퀀스를 얻는 방식을 사용했다.
의도 — 순수 ViT는 지역성 가정이 없어 공간 관계를 처음부터 학습해야 한다. CNN을 앞단에 두면 이웃 픽셀 정보가 이미 의미 있게 뭉쳐진 특징이 입력으로 들어오므로, 어텐션이 발견해야 할 몫이 줄어든다. CNN이 지역적 특징 추출을, 트랜스포머가 전역적 관계 학습을 맡는 역할 분담이다.
한계 — 논문의 스케일링 실험 결과, 하이브리드는 계산 예산이 작을 때는 순수 ViT를 약간 앞서지만 모델이 커지면 그 차이가 사라진다. 논문은 이를 다소 의외의 결과로 언급하는데, 합성곱의 지역 특징 처리가 모든 규모에서 도움이 될 것이라 예상할 수 있었기 때문이다.
주의 — 하이브리드는 아래 5-2의 해상도 문제를 해결해주지 않는다. CNN은 고정된 개수로 압축하는 장치가 아니라 고정된 비율로 축소하는 장치이므로, 입력 해상도가 커지면 특징맵도 비례해서 커지고 토큰 개수도 똑같이 늘어난다.
■ 5-2. 파인튜닝과 고해상도, 위치 임베딩 보간
블록도 상 위치 — 위치 임베딩 단계(3장 구간)의 내용물을 조정한다. 구조 자체는 변하지 않는다.
배경 — 논문은 사전학습보다 높은 해상도로 파인튜닝하는 것이 유리하다고 밝힌다. 패치 크기를 유지한 채 해상도를 올리면 같은 물리적 디테일이 더 잘게 쪼개진 여러 패치에 나뉘어 담기므로 세밀한 정보를 볼 수 있게 된다. 실제 실험에서 사전학습은 224 해상도로, 파인튜닝은 기본 384 해상도로 수행했고, ImageNet 최종 결과는 ViT-L/16을 512, ViT-H/14를 518 해상도로 파인튜닝해 얻었다.
문제 — 패치 크기를 유지하므로 실효 시퀀스 길이가 늘어난다. 224×224에서 196개였던 패치가 640×640에서는 1600개가 된다. 논문에 따르면 ViT 자체는 메모리 한계 내에서 임의의 시퀀스 길이를 처리할 수 있으나, 사전학습된 위치 임베딩이 더 이상 의미를 갖지 못하게 된다. 사전학습 때 만든 위치 임베딩 표에는 196개 항목뿐이므로 나머지 자리를 채울 값이 없다.
해결 — 사전학습된 위치 임베딩을 원본 이미지상의 위치에 따라 2D 보간한다. 196개 위치 임베딩을 14×14 격자로 놓고, 이를 40×40 격자로 리사이즈하는 것이다. 작은 이미지를 확대할 때 픽셀 사이를 주변 값 기반으로 메우는 것과 동일한 원리다. 번호를 뒤에 이어붙이는 것이 아니라 격자 전체를 통째로 늘리는 것이며, 원래 있던 값들은 새 격자의 대응 위치에 남고 새로 생긴 자리만 보간으로 채워진다.
논문은 이 해상도 조정과 패치 추출이 ViT에 2D 구조에 대한 귀납적 편향이 수동으로 주입되는 유일한 두 지점이라고 명시한다.
파인튜닝 시 헤드 처리도 함께 언급해둘 필요가 있다. 사전학습된 예측 헤드를 제거하고 0으로 초기화된 D×K 피드포워드 계층을 새로 붙인다(K는 목표 클래스 수). 논문 부록에 따르면 마지막 층만 재초기화하는 것보다 헤드 전체(두 개의 선형 계층)를 교체하는 편이 더 안정적이었다.
【쉽게 다시 말하면】
온도계에 0도, 10도, 20도 눈금만 있는데 5도를 알아야 한다면 그 사이 값으로 추정한다. 위치 임베딩 보간도 같다. 기존에 학습된 값들 사이를 수학적으로 메워 없는 자리를 채운다.
주의 — 해상도를 올리는 것이 공짜는 아니다. 어텐션 행렬 크기가 N×N이므로 토큰 수가 8배 늘면 계산량은 대략 64배가 된다.
■ 5-3. 어텐션 거리 분석
블록도 상 위치 — 인코더(4장 구간)를 학습이 끝난 뒤 사후 관찰한다. 구조를 바꾸는 기법이 아니다.
측정 방법 — 어텐션 가중치를 근거로, 정보가 통합되는 이미지 공간상 평균 거리를 계산한다. 논문은 이 "어텐션 거리"가 CNN의 수용영역(receptive field) 크기에 대응하는 개념이라고 설명한다.
발견 — 일부 헤드는 가장 낮은 층에서부터 이미 이미지 대부분을 주목하고 있었다. 전역적으로 정보를 통합하는 능력이 실제로 사용되고 있다는 뜻이다. 반면 다른 헤드들은 낮은 층에서 일관되게 좁은 어텐션 거리를 유지했다. 그리고 층이 깊어질수록 어텐션 거리는 전반적으로 증가한다.
이것이 의미하는 바는, CNN처럼 "낮은 층은 좁게, 높은 층은 넓게"가 구조적으로 강제되는 것이 아니라 헤드마다 자유롭게 학습된다는 점이다. 일부 헤드는 스스로 CNN과 유사한 지역적 처리로 수렴했고, 일부는 처음부터 전역적으로 보는 쪽으로 수렴했다.
하이브리드와의 비교 — ResNet을 앞단에 둔 하이브리드 모델에서는 이 고도로 지역화된 어텐션이 덜 두드러졌다. 논문은 이것이 CNN의 초기 합성곱 계층과 유사한 기능을 수행하는 것일 수 있다고 해석한다. 즉 순수 ViT에서 일부 헤드가 스스로 담당하던 지역적 처리를, 하이브리드에서는 CNN이 대신 맡아준 것으로 볼 수 있다.
[그림 6 위치] 층 깊이별 헤드의 평균 어텐션 거리 분포 산점도. 논문 Figure 7 오른쪽 인용
▶ 핵심 한 줄 : 하이브리드는 만들 때의 선택, 해상도 파인튜닝은 재학습할 때의 절차, 어텐션 거리는 다 만든 뒤의 관찰 도구로 서로 독립적이다.
[부록] 데이터 규모와 귀납적 편향
본문에서 반복해 등장한 "ViT는 CNN의 가정을 갖지 않는다"는 명제가 실제 성능에 어떻게 나타나는지 정리한다. 이것이 ViT 논문의 핵심 실증 결과다.
■ 중간 규모 데이터에서는 CNN에 밀린다
논문에 따르면 강한 정규화 없이 ImageNet 정도의 중간 규모 데이터셋으로 학습하면, ViT는 비슷한 크기의 ResNet보다 몇 퍼센트포인트 낮은 정확도를 보인다. 저자들은 이것이 예상 가능한 결과라고 말한다. 트랜스포머에는 CNN이 갖는 이동 등변성과 지역성 같은 귀납적 편향이 없으므로, 데이터가 충분치 않으면 일반화가 잘 되지 않기 때문이다.
■ 대규모 데이터에서는 역전된다
그러나 14M~300M 규모로 올라가면 상황이 바뀐다. 논문의 표현을 빌리면, 대규모 학습이 귀납적 편향을 압도한다. 공개 데이터셋 ImageNet-21k(21k 클래스, 14M 이미지)나 자체 데이터셋 JFT-300M(18k 클래스, 303M 이미지)으로 사전학습하면 여러 벤치마크에서 최신 CNN에 근접하거나 능가한다.
최고 성능 모델의 수치는 ImageNet 88.55%, ImageNet-ReaL 90.72%, CIFAR-100 94.55%, VTAB 19개 과제 77.63%다.
■ 데이터 규모별 교차점
JFT의 부분집합(9M, 30M, 90M)으로 실험한 결과, 계산 비용이 비슷한 조건에서 ViT가 ResNet보다 작은 데이터셋에서 더 심하게 과적합했다. ViT-B/32는 ResNet50보다 약간 빠르지만 9M 부분집합에서는 훨씬 나쁘고 90M 이상에서는 더 낫다. ResNet152x2와 ViT-L/16 사이에도 같은 양상이 나타난다.
논문은 이를 두고, 합성곱의 귀납적 편향은 작은 데이터셋에서 유용하지만 큰 데이터셋에서는 관련 패턴을 데이터로부터 직접 학습하는 것으로 충분하며 오히려 유익하다고 정리한다.
■ 계산 효율
동일한 계산 예산에서 ViT는 대체로 ResNet을 앞선다. 논문은 같은 성능에 도달하는 데 ViT가 약 2~4배 적은 계산을 쓴다고 보고한다(5개 데이터셋 평균). 사전학습 비용을 TPUv3-core-days로 비교하면 ViT-H/14가 2.5k, ViT-L/16이 0.68k인 반면 BiT-L은 9.9k, Noisy Student는 12.3k다.
■ 자기지도 학습 실험
논문은 BERT의 마스크 언어 모델링을 모방한 마스크 패치 예측(masked patch prediction)도 예비 실험했다. 패치 임베딩의 50%를 손상시키되, 그중 80%는 학습 가능한 [mask] 임베딩으로 교체, 10%는 다른 무작위 패치 임베딩으로 교체, 10%는 그대로 두는 방식이다. BERT의 구성과 매우 유사하다. 예측 대상은 손상된 패치의 3비트 평균 색상(총 512색)이었다.
결과는 ViT-B/16이 ImageNet 79.9%로, 처음부터 학습하는 것보다 2% 향상됐으나 지도 사전학습에는 여전히 4% 뒤졌다. 자기지도 ViT는 가능성을 보이지만 이 시점에서는 대규모 지도 사전학습이 더 강력하다는 결론이다.
▶ 핵심 한 줄 : ViT의 가정 없음은 작은 데이터에서는 약점이지만 큰 데이터에서는 강점으로 뒤집힌다.
마무리
전체를 한 문장으로 정리하면 이렇다. ViT는 표준 트랜스포머 인코더를 거의 손대지 않고 그대로 둔 채, 이미지를 패치 시퀀스로 바꾸는 앞단과 CLS 출력만 뽑아 쓰는 뒷단을 붙인 구조다.
논문 스스로도 결론에서 같은 취지를 밝힌다. 기존의 비전 셀프 어텐션 연구들과 달리 초기 패치 추출 단계를 제외하면 이미지 특유의 귀납적 편향을 아키텍처에 넣지 않았고, 이미지를 패치의 시퀀스로 해석해 NLP에서 쓰던 표준 트랜스포머 인코더로 처리했을 뿐이라는 것이다. 이 단순하면서 확장 가능한 전략이 대규모 사전학습과 결합됐을 때 예상 밖으로 잘 작동했다.
남은 과제로 논문이 꼽은 것은 세 가지다. 검출·분할 같은 다른 비전 과제로의 확장, 자기지도 사전학습 방법의 개선, 그리고 추가적인 규모 확장이다.
다음 글에서는 GPT 계열 디코더 전용 구조를 다룰 예정이다. 인코더만 쓰는 ViT·BERT와 달리 causal mask로 미래를 가린 채 토큰을 하나씩 생성하는 방식이며, 이후 VLM과 VLA로 이어지는 갈래다.
참고자료: Dosovitskiy et al., An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale (ICLR 2021)
|
|
