Skip to content
Published on

멀티모달 토크나이제이션과 융합 — 이미지·오디오를 토큰으로

Authors

들어가며: 토큰이 모든 것의 입구다

LLM은 토큰을 먹고 토큰을 뱉습니다. 텍스트만 다룰 때는 토크나이저가 문자열을 서브워드 토큰으로 쪼개면 끝이었습니다. 그런데 이미지를 이해하는 모델, 음성을 듣는 모델, 영상을 보는 모델을 만들려면 질문이 하나 생깁니다. "이미지를, 오디오를, 비디오를 어떻게 토큰으로 바꿔서 같은 시퀀스에 넣을 것인가?"

이 질문이 멀티모달 LLM 설계의 핵심입니다. 멀티모달 모델의 백본은 대개 Transformer이고, Transformer는 토큰(임베딩 벡터)의 시퀀스를 입력으로 받습니다. 그러니 모든 모달리티를 결국 "토큰 시퀀스"로 변환해야 합니다. 변환 방식에 따라 모델의 능력, 비용, 정확도가 달라집니다.

이 글에서는 이미지·오디오·비디오를 토큰으로 바꾸는 방법, 그것들을 텍스트와 하나의 시퀀스로 인터리빙하는 방법, 그리고 토큰 수가 폭증할 때의 압축 전략까지 다룹니다. 앞선 글에서 정렬과 융합의 원리를 봤다면, 이번 글은 그 융합이 실제 입력 수준에서 어떻게 구현되는지에 대한 이야기입니다.

이미지 토큰화: 패치와 VQ

이미지를 토큰으로 바꾸는 길은 크게 두 갈래입니다.

패치 임베딩 방식

ViT(Vision Transformer)가 대표합니다. 이미지를 고정 크기 패치(예: 14x14 픽셀)로 격자 분할하고, 각 패치를 선형 사영해 벡터로 만듭니다. 그 벡터 하나가 "비주얼 토큰"이 됩니다. 패치 토큰은 연속 임베딩이며 별도 코드북이 없습니다.

패치 토큰화(개념)

이미지  H x W x 3
  -> 패치 분할 (p x p)
  -> 패치 수 = (H/p) x (W/p)
  -> 각 패치 -> 선형사영 -> 벡터(D 차원)
  -> 비주얼 토큰 시퀀스 (N_patch x D)

예: 224x224 이미지, p=14 -> 16 x 16 = 256 토큰
   448x448 이미지, p=14 -> 32 x 32 = 1024 토큰

해상도가 올라가면 토큰 수가 제곱으로 늘어납니다. 이것이 뒤에서 다룰 토큰 폭증의 1차 원인입니다.

VQ(벡터 양자화) 방식

VQ-VAE/VQGAN 계열은 이미지를 이산 코드로 양자화합니다. 인코더가 이미지를 잠재 격자로 만들고, 각 위치 벡터를 코드북에서 가장 가까운 코드로 치환합니다. 그러면 이미지가 "이산 토큰 ID의 격자"가 되어, 텍스트 토큰처럼 정수 인덱스로 표현됩니다.

VQ 이미지 토큰화(개념)

이미지 -> 인코더 -> 잠재 격자 (h x w x D)
  각 위치 벡터를 코드북의 최근접 코드로 양자화
  -> 코드 인덱스 격자 (h x w), 각 값 in {0..K-1}
  -> flatten -> 이산 토큰 시퀀스

장점: 텍스트와 동일한 "이산 어휘"로 통일 -> 생성 모델에 유리
단점: 양자화 손실, 코드북 붕괴(collapse) 위험

패치 방식은 이해(understanding)형 VLM에서, VQ 방식은 통합 생성(이미지 생성 포함) 모델에서 자주 쓰입니다. 둘을 섞는 설계도 있습니다.

오디오 토큰화: 이산 코덱

오디오는 시간 축의 연속 신호입니다. 이를 토큰으로 만들려면 시간을 프레임으로 자르고 각 프레임을 이산 단위로 양자화합니다. 뉴럴 오디오 코덱(neural audio codec)이 이 역할을 합니다.

코덱 인코더가 파형을 일정 프레임율의 잠재 표현으로 압축하고, 잔차 벡터 양자화(residual vector quantization)로 여러 코드북에 걸쳐 이산화합니다. 결과는 시간 프레임마다 여러 개의 코드로 구성된 토큰 스트림입니다.

오디오 이산 코덱(개념)

파형(샘플레이트 높음) -> 코덱 인코더 -> 프레임 표현(낮은 프레임율)
  각 프레임을 RVQ로 다층 양자화
  -> 프레임당 코드 Q개 (계층적)
  -> [t=1: c1..cQ][t=2: c1..cQ]... 이산 오디오 토큰 스트림

특징: 프레임율과 코드북 수가 비트레이트/품질을 결정
     초당 토큰 수가 텍스트보다 훨씬 많을 수 있음

핵심 함정은 오디오 토큰의 밀도입니다. 1초의 음성이 수십~수백 토큰이 되기 쉬워, 긴 오디오는 컨텍스트를 빠르게 소진합니다. 그래서 프레임율과 양자화 계층 수를 신중히 잡습니다.

비디오 프레임 샘플링

비디오는 이미지의 시퀀스라 토큰 수가 가장 폭발하기 쉽습니다. 30fps 영상 10초면 300프레임이고, 프레임당 수백 토큰이면 수만 토큰입니다. 그래서 프레임 샘플링이 필수입니다.

비디오 토큰화 전략(개념)

원본: 30fps x 길이
  -> 프레임 샘플링 (예: 1~2 fps로 다운샘플)
  -> 키프레임/장면전환 우선 선택(선택적)
  -> 각 프레임을 패치 토큰화
  -> 시간 구분 토큰 삽입(프레임 경계 표시)
  -> 시공간 토큰 시퀀스

추가 압축: 인접 프레임 토큰 병합/풀링으로 중복 제거

샘플링은 정보 손실과 비용의 트레이드오프입니다. 빠른 동작을 봐야 하면 프레임율을 높여야 하고, 그만큼 토큰이 늘어 비용이 커집니다.

통합 시퀀스 구성: 인터리빙

각 모달리티를 토큰으로 만들었으면, 이제 하나의 시퀀스로 엮어야 합니다. 텍스트와 비주얼 토큰을 자리표시자(placeholder) 위치에 끼워 넣는 인터리빙(interleaving)이 일반적입니다.

인터리빙 입력 구성(개념)

사용자 입력:
  "다음 이미지를 설명해줘 [IMG] 그리고 이 소리도 [AUDIO]"

토큰 시퀀스로 전개:
  [txt: 다음 이미지를 설명해줘]
  [IMG_START][v1 v2 ... v256][IMG_END]
  [txt: 그리고 이 소리도]
  [AUD_START][a1 a2 ... aM][AUD_END]

LLM은 이 단일 시퀀스를 통째로 어텐션 처리한다.

비주얼/오디오 토큰은 자리표시자 한 칸이 실제로는 수백 개 토큰으로 확장된다는 점이 중요합니다. 텍스트 프롬프트에서는 토큰 한두 개여도, 펼쳐지면 컨텍스트의 큰 부분을 차지합니다.

모달리티 임베딩과 구분 토큰

모델이 "이 토큰이 어느 모달리티에서 왔는지" 알아야 처리에 유리합니다. 이를 위해 두 가지 장치를 씁니다.

  • 구분(특수) 토큰: 이미지 시작/끝, 오디오 시작/끝을 표시하는 특수 토큰으로 경계를 명시합니다.
  • 모달리티 임베딩: 토큰 임베딩에 모달리티 종류를 나타내는 학습 임베딩을 더해, 같은 위치라도 출처를 구분합니다.

위치 정보도 중요합니다. 이미지는 2D 공간 위치를, 비디오는 시간+공간 위치를 가져야 합니다. 최근 VLM은 임의 해상도를 다루기 위해 멀티차원 회전 위치(예: M-RoPE류)로 시간·세로·가로 좌표를 함께 인코딩합니다.

위치 인코딩 차원(개념)

텍스트: 1D 위치 (순서)
이미지: 2D 위치 (행, 열)
비디오: 3D 위치 (시간, 행, 열)

멀티차원 RoPE: 각 축을 분할해 회전 위치로 인코딩
-> 임의 해상도/길이에 유연

토큰 폭증과 압축

멀티모달의 가장 현실적인 문제는 토큰 수입니다. Transformer 어텐션 비용은 시퀀스 길이에 제곱으로 늘기 때문에, 비주얼 토큰이 많으면 연산과 메모리가 급증합니다. 그래서 압축이 핵심 기술입니다.

토큰 프루닝(token pruning)

중요도가 낮은 토큰을 버립니다. 어텐션 점수나 학습된 점수로 토큰의 정보량을 추정하고, 배경처럼 덜 중요한 패치 토큰을 제거합니다. 레이어를 거치며 점진적으로 줄이는 방식이 흔합니다.

토큰 병합(token merging)

유사한 토큰을 묶어 하나로 합칩니다. 인접하거나 임베딩이 비슷한 토큰을 평균/가중합으로 병합하면, 정보를 비교적 보존하며 개수를 줄일 수 있습니다.

Q-Former류 압축

learnable query를 두고, 비주얼 특징을 key/value로 하는 교차 어텐션으로 정보를 소수의 쿼리 토큰에 응축합니다. 입력 패치 수와 무관하게 고정된 작은 수의 토큰만 LLM으로 넘어갑니다.

Q-Former류 압축(개념)

비주얼 패치 특징 (N_patch x D)  <- 많음 (예: 1024)
            |
learnable query (Q x D)  <- 적음 (예: 32~64)
            |
교차 어텐션: query가 패치를 참조하며 정보 응축
            |
압축된 비주얼 토큰 (Q x D)  -> LLM 입력

효과: LLM이 보는 비주얼 토큰을 1024 -> 64로 감소
주의: 과도 압축은 세부 정보(작은 글자, OCR) 손실

압축은 만능이 아닙니다. OCR이나 미세한 차트 읽기처럼 세부가 중요한 과제에서는 과도한 압축이 성능을 떨어뜨립니다. 과제 특성에 맞춰 압축 강도를 조절해야 합니다.

컨텍스트 비용

토큰 수는 곧 비용입니다. 세 가지 측면을 봐야 합니다.

  • 연산 비용: 어텐션은 시퀀스 길이에 제곱, FFN은 선형. 비주얼 토큰이 많으면 프리필(prefill) 단계 연산이 크게 늘어납니다.
  • 메모리 비용: KV 캐시는 토큰 수에 비례. 긴 멀티모달 입력은 KV 캐시 메모리를 빠르게 잡아먹습니다.
  • 지연/요금: API 과금과 지연이 토큰 수에 직결됩니다. 고해상도 이미지를 무심코 넣으면 비용이 급등합니다.
토큰 수가 비용에 미치는 영향(개념)

비주얼 토큰 N_v 증가 ->
  - prefill FLOPs: 어텐션 O((N_v + N_t)^2) 항 증가
  - KV 캐시 메모리: O(N_v + N_t) 증가
  - TTFT(첫 토큰 지연): prefill 길어져 증가

대응: 해상도 상한, 동적 해상도, 압축(프루닝/병합/Q-Former)

실무에서는 입력 해상도 정책(상한, 동적 조절), 압축 강도, 캐싱을 함께 설계합니다. 같은 정확도라면 토큰을 줄이는 쪽이 거의 항상 유리합니다.

동적 해상도와 임의 종횡비

현실의 이미지는 정사각형이 아닙니다. 가로로 긴 파노라마, 세로로 긴 문서 스캔, 작은 아이콘까지 종횡비와 크기가 제각각입니다. 고정 해상도(예: 224x224)로 강제 리사이즈하면 종횡비가 깨져 정보가 왜곡됩니다. 특히 문서나 차트처럼 텍스트가 빽빽한 이미지는 강제 리사이즈로 글자가 뭉개지기 쉽습니다.

최근 VLM은 임의 해상도(naive dynamic resolution)를 지원합니다. 원본 종횡비를 유지하면서 패치 격자를 동적으로 구성하고, 그 결과 비주얼 토큰 수가 이미지마다 달라집니다. 이를 위해 위치 인코딩도 임의 격자를 다룰 수 있어야 합니다.

고정 해상도 vs 동적 해상도(개념)

[고정] 모든 이미지를 224x224로 강제 리사이즈
  -> 종횡비 왜곡, 작은 글자 뭉개짐
  -> 토큰 수는 항상 동일(예측 쉬움)

[동적] 원본 종횡비 유지, 패치 격자 가변
  -> 왜곡 적음, 문서/차트에 유리
  -> 토큰 수가 이미지마다 달라짐(예측 어려움)

절충: 최소/최대 토큰 상한을 두고 그 범위에서 동적 조절

동적 해상도는 품질에 유리하지만, 토큰 수 변동이 커져 메모리 계획과 배칭을 어렵게 합니다. 그래서 보통 최소/최대 토큰 상한을 두고 그 범위 안에서만 동적으로 조절합니다.

멀티차원 위치 인코딩 자세히

위치 인코딩은 모달리티마다 차원이 다릅니다. 텍스트는 1D, 이미지는 2D, 비디오는 3D 위치가 필요합니다. 단일 1D 위치만 쓰면 이미지의 공간 구조나 비디오의 시간 구조를 제대로 표현하지 못합니다.

회전 위치 인코딩(RoPE)을 다차원으로 확장하면 이 문제를 풀 수 있습니다. 임베딩 차원을 여러 그룹으로 나누고, 각 그룹에 서로 다른 축(시간/세로/가로)의 위치를 회전으로 인코딩합니다. 그러면 하나의 토큰이 시간·공간 좌표를 동시에 담을 수 있습니다.

멀티차원 RoPE 분할(개념)

임베딩 차원 D를 세 구획으로 분할:
  [ 시간축 회전 | 세로축 회전 | 가로축 회전 ]
       D_t           D_h          D_w

각 토큰의 (t, h, w) 좌표를 해당 구획에 회전으로 인코딩
-> 텍스트(t만), 이미지(h,w), 비디오(t,h,w)를 통일된 틀로 처리
-> 임의 해상도/길이에 외삽 유연

이 방식의 장점은 학습 때 보지 못한 해상도나 길이에도 비교적 잘 일반화한다는 것입니다. 다만 학습 분포와 추론 분포가 지나치게 다르면 외삽이 깨질 수 있어, 학습 단계에서 다양한 해상도를 충분히 노출하는 것이 좋습니다.

토큰 예산 계획

멀티모달 입력을 다룰 때는 토큰 예산(budget)을 명시적으로 계획해야 합니다. 텍스트만 셀 때와 달리, 비주얼 토큰이 확장되며 예산을 빠르게 소진하기 때문입니다.

토큰 예산 계산(개념)

총 컨텍스트 한도 = C  (예: 32768)

입력 토큰 = 텍스트 토큰 + 비주얼 토큰(확장 후) + 특수 토큰
출력 여유 = C - 입력 토큰

점검:
  - 비주얼 토큰을 자리표시자가 아니라 "확장 후" 값으로 계산했는가
  - 이미지 여러 장의 합을 더했는가
  - 출력 길이를 위한 여유를 남겼는가

초과 시 대응: 해상도 하향, 압축 강화, 이미지 수 제한

실무 버그의 상당수는 자리표시자를 한 토큰으로 착각해 예산을 잘못 잡는 데서 옵니다. 항상 확장 후 길이로 계산하는 습관이 중요합니다.

모달리티별 토큰 밀도 비교

같은 1초, 같은 1장이라도 모달리티에 따라 토큰 밀도가 크게 다릅니다. 이 감각을 갖고 있어야 비용과 컨텍스트를 직관적으로 가늠할 수 있습니다.

대략적 토큰 밀도(개념, 모델/설정 의존)

텍스트  1문단(약 100단어)        -> 약 130 토큰
이미지  중간 해상도 1장          -> 수백 토큰
이미지  고해상도 문서 1장        -> 수천 토큰
오디오  1초 음성                 -> 수십 토큰
비디오  1초(샘플링 후)           -> 수백~수천 토큰

함의: 비디오 > 고해상도 이미지 > 오디오 > 텍스트 순으로 밀도 큼
     긴 영상은 컨텍스트를 가장 빨리 소진

이 표가 정확한 수치는 아니지만 상대적 규모 감각을 줍니다. 영상과 고해상도 이미지가 컨텍스트의 주된 소비자라는 점을 기억하면 설계가 쉬워집니다.

VQ 코드북의 실제 동작

VQ 토큰화를 더 깊이 들여다보겠습니다. 코드북은 K개의 학습된 벡터(코드)로 구성됩니다. 인코더가 만든 각 위치 벡터를, 코드북에서 거리가 가장 가까운 코드로 치환하는 것이 양자화입니다.

VQ 양자화 단계(개념)

인코더 출력 z (위치별 벡터)
코드북 E = [e_0, e_1, ..., e_{K-1}]

각 z에 대해:
  최근접 코드 인덱스 = argmin_k 거리(z, e_k)
  양자화 출력 = e_{최근접}

학습:
  - 인코더는 코드와 가까워지도록
  - 코드북은 사용된 코드가 입력 평균을 향하도록
  - 직선 통과(straight-through)로 그래디언트 전달

VQ의 고질적 문제는 코드북 붕괴(collapse)입니다. 일부 코드만 계속 선택되고 나머지는 죽어버려, 표현 다양성이 줄어듭니다. 이를 막으려 코드북 재시작(dead code 재초기화), 지수이동평균(EMA) 갱신, 커밋먼트 손실 등을 씁니다. 코드북 활용률(얼마나 많은 코드가 실제 쓰이는지)을 모니터링하는 것이 중요합니다.

어댑터 설계의 트레이드오프

비전 특징을 LLM 공간으로 옮기는 어댑터(프로젝터)는 설계 선택지가 여럿입니다. 각각 토큰 수와 정보 보존 사이에서 다른 균형을 가집니다.

어댑터 유형 비교(개념)

[선형/MLP 프로젝터]
  패치 특징을 위치별로 LLM 차원에 사상
  토큰 수 = 패치 수 (압축 없음)
  장점: 단순, 정보 보존 좋음
  단점: 패치가 많으면 토큰도 많음

[Q-Former류 (learnable query)]
  소수 쿼리로 정보 응축
  토큰 수 = 쿼리 수 (고정, 압축)
  장점: 토큰 수 제어 용이
  단점: 과압축 시 세부 손실, 학습 까다로움

[풀링/병합 기반]
  인접 패치 토큰을 묶어 다운샘플
  중간 정도의 압축

실무 선택은 과제 특성에 달렸습니다. OCR·문서처럼 세부가 중요하면 압축이 적은 선형/MLP 쪽이, 일반 장면 이해처럼 요약이 충분하면 Q-Former류가 유리할 수 있습니다. 많은 최신 VLM이 단순 MLP 프로젝터 + 동적 해상도 조합으로 좋은 결과를 내기도 합니다.

인터리빙의 함정: 순서와 정렬

인터리빙에서 토큰의 순서와 정렬은 미묘하지만 중요합니다. 같은 정보라도 배치 순서가 다르면 모델이 다르게 해석합니다.

인터리빙 순서의 영향(개념)

[이미지 먼저]
  [IMG ...][질문 텍스트]
  -> 모델이 이미지를 먼저 보고 질문에 답

[질문 먼저]
  [질문 텍스트][IMG ...]
  -> 질문 맥락 위에서 이미지를 해석

함의: 순서가 어텐션 흐름과 결과에 영향
     학습 분포와 일관된 순서를 쓰는 것이 안전

또 여러 이미지를 넣을 때는 각 이미지에 인덱스나 라벨을 붙여 "첫 번째 이미지", "두 번째 이미지"를 명확히 지칭할 수 있게 하는 것이 좋습니다. 구분 토큰과 함께 이런 라벨링이 멀티이미지 추론의 정확도를 높입니다.

토큰화 결과의 캐싱과 재사용

비주얼 토큰화는 비쌉니다. 비전 인코더 순전파와 프로젝터 연산이 들어가기 때문입니다. 그런데 같은 이미지가 여러 번 등장하는 상황(멀티턴 대화, 동일 문서 반복 질의, 인기 이미지)에서는 토큰화 결과를 캐싱해 재사용할 수 있습니다.

비주얼 토큰 캐싱(개념)

캐시 키 = 해시(이미지 바이트 + 전처리 파라미터)
  전처리 파라미터: 목표 해상도, 정규화 설정 등

요청 -> 키 계산
  히트: 캐시된 비주얼 토큰 즉시 사용 (인코더 스킵)
  미스: 인코딩 후 결과 저장

주의:
  - 전처리 파라미터를 키에서 빠뜨리면 잘못된 토큰 재사용
  - 메모리/디스크 한도와 만료 정책 필요

캐싱은 토큰화 자체를 줄이지는 못하지만, 반복 비용을 크게 절감합니다. 특히 토큰 수가 많은 고해상도 이미지를 반복 처리할 때 효과가 큽니다. 캐시 키 설계에서 전처리 파라미터를 반드시 포함해야 잘못된 재사용을 피할 수 있습니다.

비교: 토큰화·압축 방식

항목방식장점단점
이미지패치(ViT)연속표현, 이해형에 강함해상도에 비례해 토큰 증가
이미지VQ 이산텍스트와 어휘 통일, 생성 유리양자화 손실, 코드북 붕괴
오디오이산 코덱(RVQ)통일된 이산 토큰초당 토큰 밀도 높음
압축프루닝단순, 효과적중요 토큰 손실 위험
압축병합정보 보존적구현 복잡
압축Q-Former고정 소수 토큰과압축 시 세부 손실

함정과 트러블슈팅

  • 자리표시자 확장 누락: 자리표시자 한 칸이 수백 토큰으로 펼쳐지는 걸 잊으면 컨텍스트 예산 계산이 틀어집니다. 항상 확장 후 길이로 계산하세요.
  • 구분 토큰 누락/충돌: 모달리티 경계 토큰이 빠지면 모델이 텍스트와 비주얼을 뒤섞어 이해할 수 있습니다.
  • 해상도 폭주: 고해상도 이미지를 그대로 넣어 토큰이 폭증하면 지연과 비용이 급등합니다. 동적 해상도/상한을 두세요.
  • 과도 압축: OCR·소형 객체·차트에서 세부가 사라집니다. 과제별로 압축 강도를 다르게 두세요.
  • 오디오/비디오 길이: 길이에 비례해 토큰이 선형 증가합니다. 샘플링율과 청크 분할 전략이 필요합니다.
  • 위치 인코딩 불일치: 학습과 추론의 해상도/프레임율이 크게 다르면 위치 일반화가 깨질 수 있습니다.

마치며

멀티모달 LLM은 결국 "모든 것을 토큰으로 바꾸는" 기술 위에 서 있습니다. 이미지는 패치 또는 VQ로, 오디오는 이산 코덱으로, 비디오는 샘플링 후 패치로 토큰화됩니다. 이 토큰들을 구분 토큰과 모달리티 임베딩으로 표시하며 텍스트와 인터리빙해 하나의 시퀀스를 만듭니다.

가장 큰 실무 과제는 토큰 폭증입니다. 프루닝, 병합, Q-Former류 압축으로 토큰을 줄이되, OCR 같은 세부 과제에서는 과압축을 경계해야 합니다. 토큰 수는 곧 연산·메모리·요금이므로, 해상도 정책과 압축을 함께 설계하는 것이 비용 효율의 핵심입니다. 다음 글에서는 이렇게 만들어진 멀티모달 입력을 실제로 서빙할 때 생기는 새로운 과제를 다루겠습니다.

참고 자료