비전-언어 모델(Vision-Language Models) — ViT-MLP-LLM 패턴

비전 인코더(vision encoder)가 이미지를 토큰(token)으로 바꿉니다. MLP 프로젝터(projector)가 그 토큰을 LLM의 임베딩 공간(embedding space)으로 매핑합니다. 나머지는 언어 모델(language model)이 처리합니다. 이 ViT-MLP-LLM 패턴이 2026년 모든 프로덕션(production) VLM의 기본 구조입니다.

유형: Learn + Use 언어: Python 선수 조건: Phase 4 Lesson 14(ViT), Phase 4 Lesson 18(CLIP), Phase 7 Lesson 02(Self-Attention) 소요 시간: 약 75분

학습 목표

  • ViT-MLP-LLM 아키텍처를 말할 수 있고, 세 구성 요소가 각각 어떤 역할을 맡는지 설명합니다.
  • Qwen3-VL, InternVL3.5, LLaVA-Next, GLM-4.6V를 파라미터 수(parameter count), 컨텍스트 길이(context length), 벤치마크 성능(benchmark performance) 기준으로 비교합니다.
  • DeepStack을 설명합니다. 여러 층의 ViT 특징(multi-level ViT features)이 마지막 층 하나의 특징(last-layer feature)보다 비전-언어 정합(vision-language alignment)을 더 단단하게 만드는 이유를 이해합니다.
  • 프로덕션 환경의 VLM 환각(hallucination)을 교차 양상 오류율(Cross-Modal Error Rate; CMER)로 측정하고, 그 신호에 따라 조치합니다.

문제

CLIP(Phase 4 Lesson 18)은 이미지와 텍스트가 공유하는 임베딩 공간(shared embedding space)을 제공합니다. 이는 제로샷 분류(zero-shot classification)와 검색(retrieval)에는 충분합니다. 하지만 "이 이미지에 빨간 자동차가 몇 대 있나요?"에는 답할 수 없습니다. CLIP은 텍스트를 생성하지 않고 유사도(similarity)만 점수로 매기기 때문입니다.

비전-언어 모델(Vision-Language Models; VLMs), 즉 Qwen3-VL, InternVL3.5, LLaVA-Next, GLM-4.6V는 CLIP 계열의 이미지 인코더(image encoder)를 완전한 언어 모델에 결합합니다. 모델은 이미지와 질문을 함께 보고 답을 생성합니다. 2026년에는 오픈소스 VLM이 MMMU, MMBench, DocVQA, ChartQA, MathVista, OSWorld 같은 멀티모달 벤치마크(multimodal benchmark)에서 GPT-5와 Gemini-2.5-Pro에 맞먹거나 앞섭니다.

세 조각(ViT, 프로젝터, LLM)이 표준 구조입니다. 모델 간 차이는 어떤 ViT를 쓰는지, 어떤 프로젝터를 쓰는지, 어떤 LLM인지, 그리고 학습 데이터(training data)와 정합 레시피(alignment recipe)가 무엇인지에 있습니다. 패턴을 이해하면 구성 요소를 교체하는 일은 기계적인 작업이 됩니다.

사전 테스트

2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요

1.ViT-MLP-LLM VLM 패턴에서 정합(alignment) 단계에 다른 구성 요소는 동결(frozen)한 채로 가장 흔히 학습하는 구성 요소는 무엇인가요?

2.Qwen3-VL에서 쓰는 DeepStack은 어떤 일을 하나요?

0/2 답변 완료

개념

ViT-MLP-LLM 아키텍처

flowchart LR
    IMG["Image<br/>(H x W x 3)"] --> ViT["Vision encoder<br/>(ViT, CLIP-L,<br/>SigLIP, DINOv3)"]
    ViT --> FEATS["Image tokens<br/>(N, d_vit)"]
    FEATS --> PROJ["Projector<br/>(2-4 layer MLP<br/>or Q-former)"]
    PROJ --> VTOK["Image tokens<br/>in LLM space<br/>(N, d_llm)"]
    TXT["Text prompt"] --> TOK["LLM tokenizer"]
    TOK --> TTOK["Text tokens<br/>(M, d_llm)"]
    VTOK --> CONCAT["Interleave<br/>or concat"]
    TTOK --> CONCAT
    CONCAT --> LLM["Decoder LLM<br/>(Qwen3, LLaMA, etc.)"]
    LLM --> OUT["Text answer"]

    style ViT fill:#dbeafe,stroke:#2563eb
    style PROJ fill:#fef3c7,stroke:#d97706
    style LLM fill:#dcfce7,stroke:#16a34a
  1. 비전 인코더(Vision encoder): 사전 학습된 ViT입니다. CLIP-L/14, SigLIP, DINOv3 또는 그 파인튜닝(fine-tuned) 변형이 쓰이며, 패치 토큰(patch token)을 만듭니다.
  2. 프로젝터(Projector): 비전 토큰을 LLM의 임베딩 차원으로 매핑하는 작은 모듈(module)입니다. 2-4층 MLP 또는 Q-former가 쓰입니다. 파인튜닝의 대부분이 여기서 일어납니다.
  3. LLM: 디코더 전용(decoder-only) 언어 모델입니다. Qwen3, Llama, Mistral, GLM, InternLM 등이 있으며, 비전 토큰과 텍스트 토큰을 시퀀스(sequence)로 읽고 텍스트를 생성합니다.

원칙적으로 세 조각 모두 학습 가능합니다. 실제로는 비전 인코더와 LLM은 대부분 동결(frozen) 상태로 두고 프로젝터만 학습합니다. 적은 비용으로 수십억 파라미터의 신호를 활용하는 셈입니다.

DeepStack

기본 프로젝션(vanilla projection)은 마지막 ViT 층만 사용합니다. DeepStack(Qwen3-VL)은 여러 ViT 깊이의 특징을 표본화(sampling)해 쌓아(stack) 올립니다. 깊은 층은 고수준 의미(high-level semantics)를, 얕은 층은 미세한 공간·질감 정보(fine-grained spatial and textural information)를 담습니다. 둘을 모두 LLM에 넣으면 "이미지에 무엇이 있는가"(의미)와 "정확히 어디에 있는가"(공간적 그라운딩; spatial grounding) 사이의 간극이 좁아집니다.

세 가지 학습 단계

현대 VLM은 단계별로 학습합니다.

  1. 정합 단계(Alignment): ViT와 LLM을 동결하고, 이미지-캡션 쌍(image-caption pair)에서 프로젝터만 학습합니다. 비전 공간을 언어 공간으로 매핑하는 방법을 가르칩니다.
  2. 사전 학습(Pre-training): 모든 것을 해제(unfreeze)하고, 대규모로 교차 배치된 이미지-텍스트 데이터(interleaved image-text data, 5억 쌍 이상)에서 학습합니다. 모델의 시각적 지식을 만듭니다.
  3. 지시 튜닝(Instruction tuning): 선별한 (이미지, 질문, 답) 트리플(triple)로 파인튜닝합니다. 대화 행동(conversational behaviour)과 과제 형식(task format)을 가르칩니다. 이것이 "비전을 인식하는 LM"을 실제로 쓸 수 있는 비서로 바꿉니다.

대부분의 LoRA 파인튜닝은 작은 라벨링 데이터셋(labelled dataset)으로 3단계를 겨냥합니다.

모델 패밀리 비교(2026년 초)

ModelParamsVision encoderLLMContextStrengths
Qwen3-VL-235B-A22B (MoE)235B (22B active)custom ViT + DeepStackQwen3256KGeneral SOTA, GUI agent
Qwen3-VL-30B-A3B (MoE)30B (3B active)custom ViT + DeepStackQwen3256KSmaller MoE alternative
Qwen3-VL-8B (dense)8Bcustom ViTQwen3128KProduction dense default
InternVL3.5-38B38BInternViT-6BQwen3 + GPT-OSS128KStrong MMBench / MMVet
InternVL3.5-241B-A28B241B (28B active)InternViT-6BQwen3128KCompetitive with GPT-4o
LLaVA-Next 72B72BSigLIPLlama-332KOpen, easy to fine-tune
GLM-4.6V~70BcustomGLM64KOpen-source, strong OCR
MiniCPM-V-2.68BSigLIPMiniCPM32KEdge-friendly

시각 에이전트(Visual agents)

Qwen3-VL-235B는 OSWorld에서 세계 최상위 성능을 냅니다. OSWorld는 데스크톱, 모바일, 웹 GUI를 조작하는 시각 에이전트(visual agent) 벤치마크입니다. 모델은 화면 스크린샷을 보고 UI를 이해한 뒤, 클릭(click), 입력(type), 스크롤(scroll) 같은 동작을 출력합니다. 도구(tool)와 결합하면 일반적인 데스크톱 작업의 순환(loop)을 닫을 수 있습니다. 2026년의 "AI PC" 데모 대부분은 이런 구조를 내부에서 사용합니다.

에이전트 역량과 RoPE 변형

VLM은 비디오에서 프레임이 언제 등장하는지 알아야 합니다. Qwen3-VL은 T-RoPE(temporal rotary position embeddings)에서 텍스트 기반 시간 정합(text-based time alignment) 으로 발전했습니다. 명시적인 타임스탬프(timestamp) 텍스트 토큰을 비디오 프레임 사이에 끼워 넣습니다. 모델은 "<timestamp 00:32> frame, prompt"를 보고 시간적 관계(temporal relationship)를 추론합니다.

정합 문제(The alignment problem)

크롤링된 데이터셋(crawled dataset)의 이미지-텍스트 쌍 중 약 12%는 이미지에 완전히 근거(grounded)하지 않은 설명을 포함합니다. 이런 데이터로 학습된 VLM은 조용히 환각을 배웁니다. 객체를 지어내고, 숫자를 잘못 읽고, 관계를 만들어 냅니다. 프로덕션 환경에서는 이것이 가장 큰 실패 양상(failure mode)입니다.

Skywork.ai는 이를 추적하기 위해 교차 양상 오류율(Cross-Modal Error Rate; CMER) 을 도입했습니다.

CMER = 텍스트 신뢰도(text confidence)는 높지만 이미지-텍스트 유사도(CLIP 계열 검증기 기준)는 낮은 출력의 비율

CMER가 높다는 것은 모델이 이미지에 근거하지 않은 내용을 자신 있게 말한다는 뜻입니다. CMER를 모니터링하고 프로덕션 KPI로 다루면 환각률(hallucination rate)을 약 35% 줄일 수 있습니다. 핵심은 "모델을 즉시 고친다"가 아니라 "CMER가 높은 출력을 사람 검토(human review)로 라우팅한다"입니다.

LoRA / QLoRA 파인튜닝

70B 규모 VLM의 전체 파인튜닝(full fine-tuning)은 대부분의 팀에는 부담스럽습니다. 어텐션(attention)과 프로젝터 층에 LoRA(rank 16-64)를 적용하거나, 4-bit 베이스 가중치(base weights)를 사용하는 QLoRA는 단일 A100 / H100에도 들어갑니다. 비용은 예제 5,000-50,000개, 연산 비용 $100-$5,000, 학습 시간 2-10시간 정도입니다.

공간 추론은 여전히 약하다

현재 VLM은 위-아래(above-below), 좌-우(left-right), 개수 세기(counting), 거리(distance) 같은 공간 추론(spatial reasoning) 벤치마크에서 50-60% 수준입니다. "어떤 객체가 어떤 객체 위에 있는가"가 중요한 사용 사례라면 강하게 검증해야 합니다. 일반 VLM의 성능은 사람보다 낮습니다. 순수한 공간 과제에서는 전용 키포인트/자세 추정기(specialised keypoint / pose estimator), 깊이 모델(depth model), 또는 박스 기하(box geometry)를 후처리(post-processing)한 검출 모델(detection model)이 VLM보다 낫습니다.

만들어 보기

Step 1: 프로젝터

가장 자주 학습하게 될 부분입니다. GELU를 사용하는 2-4층 MLP입니다.

import torch
import torch.nn as nn


class Projector(nn.Module):
    def __init__(self, vit_dim=768, llm_dim=4096, hidden=4096):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(vit_dim, hidden),
            nn.GELU(),
            nn.Linear(hidden, llm_dim),
        )

    def forward(self, x):
        return self.net(x)

입력은 (N_patches, d_vit) 토큰 텐서(tensor)입니다. 출력은 (N_patches, d_llm)입니다. LLM은 각 출력 행(row)을 또 하나의 토큰처럼 다룹니다.

Step 2: ViT-MLP-LLM을 처음부터 끝까지 조립

최소 VLM의 순전파(forward pass) 골격입니다. 실제 코드는 transformers를 쓰지만, 여기서는 개념적 구성도를 보여 줍니다.

class MinimalVLM(nn.Module):
    def __init__(self, vit, projector, llm, image_token_id):
        super().__init__()
        self.vit = vit
        self.projector = projector
        self.llm = llm
        self.image_token_id = image_token_id  # 텍스트 프롬프트 안의 placeholder 토큰

    def forward(self, image, input_ids, attention_mask):
        # 1. 비전 특징 추출
        vision_tokens = self.vit(image)                     # (B, N_patches, d_vit)
        vision_embeds = self.projector(vision_tokens)       # (B, N_patches, d_llm)

        # 2. 텍스트 임베딩
        text_embeds = self.llm.get_input_embeddings()(input_ids)  # (B, M, d_llm)

        # 3. 이미지 placeholder 토큰을 비전 임베딩으로 교체
        merged = self._merge(text_embeds, vision_embeds, input_ids)

        # 4. LLM 실행
        return self.llm(inputs_embeds=merged, attention_mask=attention_mask)

    def _merge(self, text_embeds, vision_embeds, input_ids):
        out = text_embeds.clone()
        expected = vision_embeds.size(1)
        for b in range(input_ids.size(0)):
            positions = (input_ids[b] == self.image_token_id).nonzero(as_tuple=True)[0]
            if len(positions) != expected:
                raise ValueError(
                    f"batch item {b}에는 이미지 토큰이 {len(positions)}개 있지만 vision_embeds에는 패치가 {expected}개 있습니다."
                    " batch의 모든 sample은 같은 수의 이미지 placeholder 토큰으로 미리 padding되어야 합니다.")
            out[b, positions] = vision_embeds[b]
        return out

텍스트의 <image> placeholder 토큰이 실제 이미지 임베딩으로 교체됩니다. LLaVA, Qwen-VL, InternVL이 모두 동일한 패턴을 사용합니다.

Step 3: CMER 계산

가벼운 런타임 점검(runtime check)입니다.

import torch.nn.functional as F


def cross_modal_error_rate(image_emb, text_emb, text_confidence, sim_threshold=0.25, conf_threshold=0.8):
    """
    image_emb, text_emb: 이미지와 생성된 텍스트의 임베딩 (내부에서 정규화)
    text_confidence:     토큰별 확률의 평균, [0, 1] 범위
    Returns:             신뢰도가 높지만 이미지-텍스트 정합이 낮은 출력의 비율
    """
    image_emb = F.normalize(image_emb, dim=-1)
    text_emb = F.normalize(text_emb, dim=-1)
    sim = (image_emb * text_emb).sum(dim=-1)        # cosine similarity (코사인 유사도)
    high_conf_low_sim = (text_confidence > conf_threshold) & (sim < sim_threshold)
    return high_conf_low_sim.float().mean().item()

CMER를 프로덕션 KPI로 다루세요. 엔드포인트별, 프롬프트 유형별, 고객별로 모니터링합니다. CMER가 상승한다는 것은 어떤 입력 분포(input distribution)에서 모델이 환각을 시작했다는 신호입니다.

Step 4: 장난감 VLM 분류기(runnable)

프로젝터가 학습된다는 점을 보여 줍니다. 가짜 "ViT 특징"을 넣고, 작은 LLM 스타일의 토큰이 클래스를 예측합니다.

class ToyVLM(nn.Module):
    def __init__(self, vit_dim=32, llm_dim=64, num_classes=5):
        super().__init__()
        self.projector = Projector(vit_dim, llm_dim, hidden=64)
        self.head = nn.Linear(llm_dim, num_classes)

    def forward(self, vision_tokens):
        projected = self.projector(vision_tokens)
        pooled = projected.mean(dim=1)
        return self.head(pooled)

합성된 (특징, 클래스) 쌍에 200 step 미만으로 맞출 수 있습니다. 프로젝터 패턴이 동작한다는 점을 보이기에 충분합니다.

사용하기

2026년 프로덕션 팀은 VLM을 세 가지 방식으로 활용합니다.

  • 호스팅 API(Hosted API): OpenAI Vision, Anthropic Claude Vision, Google Gemini Vision입니다. 인프라가 필요 없지만 벤더 종속(vendor risk)이 있습니다.
  • 오픈소스 자체 호스팅(Open-source self-host): Qwen3-VL 또는 InternVL3.5를 transformersvllm으로 운영합니다. 제어권이 크지만 초기 노력이 큽니다.
  • 도메인 파인튜닝(Domain fine-tune): Qwen2.5-VL-7B 또는 LLaVA-1.6-7B를 불러와 맞춤 예제 5천-5만 개로 LoRA를 적용한 뒤 vllm 또는 TGI로 서빙(serving)합니다.
from transformers import AutoProcessor, AutoModelForVision2Seq
import torch
from PIL import Image

model_id = "Qwen/Qwen3-VL-8B-Instruct"
processor = AutoProcessor.from_pretrained(model_id)
model = AutoModelForVision2Seq.from_pretrained(model_id, torch_dtype=torch.bfloat16, device_map="auto")

messages = [{
    "role": "user",
    "content": [
        {"type": "image", "image": Image.open("plot.png")},
        {"type": "text", "text": "What does this chart show?"},
    ],
}]
inputs = processor.apply_chat_template(messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt").to("cuda")
generated = model.generate(**inputs, max_new_tokens=256)
answer = processor.decode(generated[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)

apply_chat_template<image> placeholder 토크나이징(tokenisation)을 감춰 줍니다. 모델은 내부에서 병합(merge)을 처리합니다.

산출물 만들기

이 레슨에서는 다음을 만듭니다.

  • outputs/prompt-vlm-selector.md: 정확도(accuracy), 지연(latency), 컨텍스트 길이, 예산(budget)에 따라 Qwen3-VL / InternVL3.5 / LLaVA-Next / API 중 무엇을 고를지 안내하는 프롬프트입니다.
  • outputs/skill-cmer-monitor.md: 프로덕션 VLM 엔드포인트에 교차 양상 오류율, 엔드포인트별 대시보드(dashboard), 알림 임계값(alert threshold)을 계측(instrument)하는 코드를 생성하는 스킬(skill)입니다.

연습문제

  1. (쉬움) 아무 오픈 VLM이나 골라 다섯 장의 이미지에 대해 세 가지 프롬프트("what is this?", "count the objects", "describe the scene")를 실행합니다. 각 답을 정답/부분 정답/환각 중 어느 쪽인지 손으로 평가하고, 1차 CMER 유사 지표(CMER-like rate)를 계산합니다.
  2. (중간) Qwen2.5-VL-3B 또는 LLaVA-1.6-7B를 특정 도메인의 캡션이 달린 이미지 500장으로 LoRA(rank 16) 파인튜닝합니다. 제로샷과 파인튜닝 후의 MMBench 스타일 정확도를 비교합니다.
  3. (어려움) VLM의 이미지 인코더를 기본 SigLIP/CLIP 대신 DINOv3로 교체합니다. LLM과 DINOv3는 동결한 상태에서 프로젝터만 다시 학습합니다. 개수 세기, 공간 추론 같은 조밀 예측(dense-prediction) 과제가 개선되는지 측정합니다.

핵심 용어

용어흔한 설명실제 의미
ViT-MLP-LLM"VLM 패턴"비전 인코더 + 프로젝터 + 언어 모델. 2026년 모든 VLM의 기본 구조
프로젝터(Projector)"다리(bridge)"비전 토큰을 LLM 임베딩 공간으로 매핑하는 2-4층 MLP 또는 Q-former
DeepStack"Qwen3-VL의 특징 트릭"마지막 층만 쓰지 않고 여러 층의 ViT 특징을 쌓는 방식
이미지 토큰(Image token)"<image> placeholder"텍스트 스트림 안의 특수 토큰. 투영된 비전 임베딩으로 교체된다
CMER"환각 KPI"Cross-Modal Error Rate. 텍스트 신뢰도는 높지만 이미지-텍스트 유사도가 낮을 때 커진다
시각 에이전트(Visual agent)"클릭하는 VLM"도구 호출과 함께 GUI(OSWorld, mobile, web)를 조작하는 VLM
Q-former"고정 개수 토큰 다리"고정 개수의 비주얼 쿼리(visual query) 토큰을 만드는 BLIP-2 스타일 프로젝터
정합 / 사전 학습 / 지시 튜닝(Alignment / pre-training / instruction tuning)"세 단계"표준 VLM 학습 파이프라인

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

main
Code

산출물

이 강의에서 생성된 프롬프트, 스킬, 코드 산출물 2개

skill-cmer-monitor

Instrument a production VLM endpoint with Cross-Modal Error Rate monitoring, dashboards, and alerts

Skill
prompt-vlm-selector

Pick Qwen3-VL / InternVL3.5 / LLaVA-Next / API given accuracy, latency, context length, and budget

Prompt

확인 문제

3문제 · 모두 맞추면 완료 표시가 가능합니다

1.프로덕션 VLM이 높은 텍스트 신뢰도(text confidence)를 보이지만 생성된 텍스트가 이미지에 없는 객체를 설명합니다. 이 실패를 포착하는 지표(metric)는 무엇인가요?

2.현대 VLM은 왜 지도학습된 ImageNet ResNet 대신 SigLIP 또는 맞춤 비전 인코더를 백본(backbone)으로 사용하나요?

3.Qwen3-VL-235B-A22B는 OSWorld에서 최상위 점수를 냅니다. OSWorld는 무엇이며, 이는 무엇을 의미하나요?

0/3 답변 완료