Jerry's Log

VLM

contents

LLM(ChatGPT 같은 모델)이 AI의 "두뇌"라면, VLM"눈"이 달린 두뇌라고 할 수 있습니다. 컴퓨터 비전(픽셀)과 자연어(텍스트) 사이의 간극을 메워주는 기술입니다.


1. 개요 (High-Level Overview)

VLM은 이미지(종종 비디오 포함)와 텍스트를 함께 받아들이고, 두 가지 모두를 이해해야 하는 작업을 수행할 수 있는 멀티모달 AI 시스템입니다.

주요 예시:


2. 핵심 아키텍처: 어떻게 작동하는가?

최신 VLM은 처음부터 새로 만들어지는 경우가 드뭅니다. 보통 세 가지 다른 부분을 결합한 "프랑켄슈타인" 모델에 가깝습니다.

A. 비전 인코더 (Vision Encoder, "눈")

이미지(픽셀)를 수학적 표현(임베딩)으로 변환하는 구성 요소입니다.

B. 언어 모델 (Language Model, "두뇌")

일반적으로 사전에 학습된 표준 LLM(Llama 3, Vicuna, Mistral 등)을 사용합니다. 텍스트, 논리, 추론을 이해합니다.

C. 프로젝터 / 어댑터 (The Projector / Adapter, "다리")

가장 중요한 부분입니다. 비전 인코더의 "언어"(시각적 벡터)는 LLM의 "언어"(텍스트 벡터)와 다릅니다.


3. VLM 학습 방법

학습은 보통 두 가지 주요 단계로 진행됩니다.

1단계: 대조 학습 (Contrastive Learning - 정렬)

OpenAI의 CLIP에 의해 대중화된 방식입니다.

2단계: 시각적 지시 튜닝 (Visual Instruction Tuning - 채팅 능력)

이 단계가 모델을 챗봇(LLaVA 등)으로 만듭니다.


4. 주요 기능

  1. VQA (Visual Question Answering): "이 사진에서 빨간 모자를 쓴 사람은 몇 명인가요?"
  2. OCR 없는 텍스트 이해: 단순히 글자를 읽는 OCR과 달리, 이미지 속 텍스트의 _의미_를 이해합니다 (예: 밈(Meme)을 설명하거나, 메뉴판을 읽고 채식 요리를 추천).
  3. 시각적 추론: 기하학 문제를 풀거나 차트/그래프를 분석합니다.
  4. 공간적 그라운딩 (Spatial Grounding): 일부 VLM은 객체의 위치를 경계 상자(좌표)로 출력할 수 있습니다. "강아지가 어디 있어?" -> [0.2, 0.5, 0.4, 0.8].

5. 진화 과정: CLIP에서 LLaVA까지

전체적인 흐름을 이해하기 위해 타임라인을 알 필요가 있습니다.

시대 모델 설명
1세대: 정렬 CLIP (2021) 이미지와 텍스트를 매칭(제로샷 분류)할 수 있었지만, 텍스트를 생성할 수는 없었습니다. 대화 불가능.
2세대: 인터리브 Flamingo (2022) 딥마인드의 혁신. 여러 장의 이미지와 텍스트가 섞인 입력을 처리할 수 있었으나 비공개(Closed Source)였습니다.
3세대: 지시 튜닝 LLaVA (2023) 게임 체인저. Llama에 간단한 프로젝션 레이어로 비전 인코더를 붙이기만 해도 놀랍도록 잘 작동함을 증명했습니다. 오픈 소스 VLM 붐을 일으켰습니다.
4세대: 네이티브 GPT-4o / Gemini 1.5 이들은 나중에 붙인 것이 아니라, 처음부터 이미지/텍스트 혼합 데이터로 학습된 "네이티브 멀티모달" 모델일 가능성이 높습니다.

6. 코드 예제 (Python & Transformers)

Hugging Face transformers 라이브러리를 사용하여 VLM(구체적으로 LLaVA)을 프로그래밍 방식으로 실행하는 코드는 다음과 같습니다.

from transformers import LlavaNextProcessor, LlavaNextForConditionalGeneration
import torch
from PIL import Image
import requests

# 1. 모델 및 프로세서 로드
processor = LlavaNextProcessor.from_pretrained("llava-hf/llava-v1.6-mistral-7b-hf")
model = LlavaNextForConditionalGeneration.from_pretrained(
    "llava-hf/llava-v1.6-mistral-7b-hf", 
    torch_dtype=torch.float16, 
    low_cpu_mem_usage=True
) 
model.to("cuda:0")

# 2. 이미지 및 텍스트 준비
url = "https://github.com/haotian-liu/LLaVA/blob/1a91fc274d7c35a9b50b3cb29c4247ae5837ce39/images/llava_logo.jpg?raw=true"
image = Image.open(requests.get(url, stream=True).raw)
prompt = "[INST] \nWhat is shown in this image? [/INST]"

# 3. 입력 전처리 (이미지를 픽셀로, 텍스트를 토큰으로 변환)
inputs = processor(prompt, image, return_tensors="pt").to("cuda:0")

# 4. 출력 생성 (Autoregressive generation)
output = model.generate(**inputs, max_new_tokens=100)

# 5. 디코딩 (토큰을 다시 텍스트로 변환)
print(processor.decode(output[0], skip_special_tokens=True))

7. 도전 과제 및 한계

많은 기대에도 불구하고 VLM은 명확한 약점을 가지고 있습니다.

references