다양한 모달리티 간 연결: AI 모달리티의 다리

텍스트, 이미지 및 오디오를 공유된 임베딩 공간에 통합하세요.

Page content

크로스모달 임베딩은 인공지능 분야에서의 중요한 돌파구로, 다양한 데이터 유형을 하나의 통합된 표현 공간 내에서 이해하고 추론하는 것을 가능하게 합니다.

이 기술은 이미지 검색부터 콘텐츠 생성에 이르는 현대의 다중모달 애플리케이션을 지원합니다.

크로스모달 임베딩 이 이미지는 다음 기사에서 가져왔습니다: CrossCLR: 다중모달 비디오 표현을 위한 크로스모달 대비 학습, Mohammadreza Zolfaghari 등

크로스모달 임베딩 이해하기

크로스모달 임베딩은 텍스트, 이미지, 오디오, 비디오와 같은 다양한 모달리티에서 정보를 인코딩하는 벡터 표현입니다. 전통적인 단일 모달리티 임베딩과 달리, 크로스모달 접근 방식은 원래 형식에 관계없이 의미적으로 유사한 개념이 모여 있는 통합된 표현을 학습합니다.

크로스모달 임베딩이란 무엇인가요?

핵심적으로, 크로스모달 임베딩은 인공지능에서 해결해야 할 중요한 문제인, 다양한 데이터 유형 간의 정보 비교 및 관계를 어떻게 처리할 것인가를 해결합니다. 전통적인 이미지 분류기는 이미지만 처리할 수 있고, 텍스트 모델은 텍스트만 처리합니다. 크로스모달 임베딩은 다양한 모달리티를 공통 벡터 공간으로 투영하여:

  • 고양이의 이미지와 “고양이"라는 단어는 유사한 임베딩 벡터를 가집니다.
  • 의미적 관계는 모달리티를 관계없이 보존됩니다.
  • 거리 측정(코사인 유사도, 유럽 거리)은 크로스모달 유사도를 측정합니다.

이 통합 표현은 텍스트 쿼리를 사용한 이미지 검색, 이미지에서 캡션 생성, 또는 특정 작업에 대한 훈련 없이도 제로샷 분류와 같은 강력한 기능을 가능하게 합니다.

크로스모달 학습 뒤의 아키텍처

현대의 크로스모달 시스템은 일반적으로 대비 학습 목표를 사용하는 이중 인코더 아키텍처를 채택합니다:

이중 인코더: 각 모달리티를 인코딩하는 별도의 신경망을 사용합니다. 예를 들어, CLIP은 다음과 같이 사용합니다:

  • 이미지에 대한 시각 트랜스포머(ViT) 또는 ResNet
  • 언어에 대한 트랜스포머 기반 텍스트 인코더

대비 학습: 모델은 일치하는 쌍(예: 이미지와 그 캡션) 간 유사도를 최대화하고, 불일치하는 쌍 간 유사도를 최소화함으로써 학습합니다. 대비 손실 함수는 다음과 같이 표현할 수 있습니다:

$$ \mathcal{L} = -\log \frac{\exp(\text{sim}(v_i, t_i) / \tau)}{\sum_{j=1}^{N} \exp(\text{sim}(v_i, t_j) / \tau)} $$

여기서 $v_i$는 이미지 임베딩, $t_i$는 텍스트 임베딩, $\text{sim}$은 유사도(일반적으로 코사인), $\tau$는 온도 매개변수입니다.

주요 기술 및 모델

CLIP: 시각-언어 이해의 선구자

OpenAI의 CLIP(Contrastive Language-Image Pre-training)은 인터넷에서 4억 개의 이미지-텍스트 쌍을 사용하여 훈련함으로써 분야를 혁신적으로 바꾸었습니다. 모델 아키텍처는 다음과 같이 구성됩니다:

import torch
from transformers import CLIPProcessor, CLIPModel
from PIL import Image

# 사전 훈련된 CLIP 모델 로드
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

# 입력 준비
image = Image.open("example.jpg")
texts = ["고양이의 사진", "개의 사진", "새의 사진"]

# 처리 및 임베딩 가져오기
inputs = processor(text=texts, images=image, return_tensors="pt", padding=True)

# 크로스모달 유사도 점수 가져오기
outputs = model(**inputs)
logits_per_image = outputs.logits_per_image
probs = logits_per_image.softmax(dim=1)

print(f"확률: {probs}")

CLIP의 주요 혁신은 규모와 단순성입니다. 대규모 웹 규모 데이터를 수동적인 주석 없이 훈련함으로써, CLIP은 놀라운 제로샷 전이 능력을 달성했습니다. CLIP은 전통적인 시각 모델과 어떻게 다릅니까? 고정된 라벨 집합에 대해 감독 분류기를 훈련하는 것과 달리, CLIP은 자연 언어 감독을 통해 학습하여, 텍스트로 설명 가능한 모든 시각 개념에 적응할 수 있습니다.

ImageBind: 6개 모달리티로 확장

Meta의 ImageBind는 시각과 언어를 넘어 다음을 포함하여 크로스모달 임베딩을 확장합니다:

  • 오디오(환경 소리, 말)
  • 깊이 정보
  • 적외선 영상
  • IMU(운동 센서) 데이터

이것은 모든 6개의 모달리티가 정렬된 진정한 다중모달 임베딩 공간을 생성합니다. 주요 통찰은 이미지가 “바인딩” 모달리티를 제공한다는 것입니다. 이미지를 다른 모달리티와 쌍으로 만들고 기존의 시각-언어 정렬을 활용함으로써, ImageBind는 훈련 중 모든 가능한 모달리티 쌍이 필요하지 않음에도 불구하고 통합된 공간을 생성합니다.

오픈소스 대안

생태계는 여러 오픈소스 구현으로 확장되었습니다:

OpenCLIP: 커뮤니티 구현으로 더 큰 모델과 다양한 훈련 레시피를 제공합니다:

import open_clip

model, _, preprocess = open_clip.create_model_and_transforms(
    'ViT-L-14', 
    pretrained='laion2b_s32b_b82k'
)
tokenizer = open_clip.get_tokenizer('ViT-L-14')

LAION-5B 모델: 대규모 오픈 LAION-5B 데이터세트에서 훈련된 모델로, 특허 모델과 비슷하거나 더 우수한 성능을 제공합니다.

최신 오픈소스 텍스트 임베딩 솔루션에 관심이 있는 개발자에게는 Qwen3 임베딩 및 리랭커 모델 Ollama 상에서가 훌륭한 다국어 성능과 간단한 로컬 배포를 제공합니다.

구현 전략

크로스모달 검색 시스템 구축

크로스모달 임베딩을 위한 세미틱 검색의 실용적인 구현은 여러 구성 요소를 포함합니다. 크로스모달 임베딩의 주요 응용 분야는 무엇인가요? 이들은 전자상거래 제품 검색부터 콘텐츠 감시, 창의 도구에 이르는 사용 사례를 지원합니다.

import numpy as np
from typing import List, Tuple
import faiss
from transformers import CLIPModel, CLIPProcessor

class CrossModalSearchEngine:
    def __init__(self, model_name: str = "openai/clip-vit-base-patch32"):
        self.model = CLIPModel.from_pretrained(model_name)
        self.processor = CLIPProcessor.from_pretrained(model_name)
        self.image_index = None
        self.image_metadata = []
        
    def encode_images(self, images: List) -> np.ndarray:
        """이미지를 임베딩으로 인코딩"""
        inputs = self.processor(images=images, return_tensors="pt", padding=True)
        with torch.no_grad():
            embeddings = self.model.get_image_features(**inputs)
        return embeddings.cpu().numpy()
    
    def encode_text(self, texts: List[str]) -> np.ndarray:
        """텍스트 쿼리를 임베딩으로 인코딩"""
        inputs = self.processor(text=texts, return_tensors="pt", padding=True)
        with torch.no_grad():
            embeddings = self.model.get_text_features(**inputs)
        return embeddings.cpu().numpy()
    
    def build_index(self, image_embeddings: np.ndarray):
        """효율적인 유사도 검색을 위한 FAISS 인덱스 생성"""
        dimension = image_embeddings.shape[1]
        
        # 코사인 유사도를 위해 임베딩 정규화
        faiss.normalize_L2(image_embeddings)
        
        # 대규모 배포를 위한 HNSW 사용
        self.image_index = faiss.IndexHNSWFlat(dimension, 32)
        self.image_index.hnsw.efConstruction = 40
        self.image_index.add(image_embeddings)
    
    def search(self, query: str, k: int = 10) -> List[Tuple[int, float]]:
        """텍스트 쿼리를 사용한 이미지 검색"""
        query_embedding = self.encode_text([query])
        faiss.normalize_L2(query_embedding)
        
        distances, indices = self.image_index.search(query_embedding, k)
        return list(zip(indices[0], distances[0]))

# 사용 예시
engine = CrossModalSearchEngine()

# 이미지 컬렉션에서 인덱스 구축
image_embeddings = engine.encode_images(image_collection)
engine.build_index(image_embeddings)

# 텍스트로 검색
results = engine.search("산 위에 있는 일몰", k=5)

도메인 특화 작업을 위한 미세 조정

일반적인 목적에 적합한 사전 훈련 모델이 있지만, 도메인 특화 응용에는 미세 조정이 유리합니다:

from transformers import CLIPModel, CLIPProcessor, AdamW
import torch.nn as nn

class FineTuneCLIP:
    def __init__(self, model_name: str, num_epochs: int = 10):
        self.model = CLIPModel.from_pretrained(model_name)
        self.processor = CLIPProcessor.from_pretrained(model_name)
        self.num_epochs = num_epochs
        
    def contrastive_loss(self, image_embeddings, text_embeddings, temperature=0.07):
        """InfoNCE 대비 손실 계산"""
        # 임베딩 정규화
        image_embeddings = nn.functional.normalize(image_embeddings, dim=1)
        text_embeddings = nn.functional.normalize(text_embeddings, dim=1)
        
        # 유사도 행렬 계산
        logits = torch.matmul(image_embeddings, text_embeddings.T) / temperature
        
        # 라벨은 대각선 (일치하는 쌍)
        labels = torch.arange(len(logits), device=logits.device)
        
        # 대칭 손실
        loss_i = nn.functional.cross_entropy(logits, labels)
        loss_t = nn.functional.cross_entropy(logits.T, labels)
        
        return (loss_i + loss_t) / 2
    
    def train(self, dataloader, learning_rate=5e-6):
        """도메인 특화 데이터로 미세 조정"""
        optimizer = AdamW(self.model.parameters(), lr=learning_rate)
        
        self.model.train()
        for epoch in range(self.num_epochs):
            total_loss = 0
            for batch in dataloader:
                images, texts = batch['images'], batch['texts']
                
                # 입력 처리
                inputs = self.processor(
                    text=texts, 
                    images=images, 
                    return_tensors="pt", 
                    padding=True
                )
                
                # 순전파
                outputs = self.model(**inputs, return_loss=True)
                loss = outputs.loss
                
                # 역전파
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
                
                total_loss += loss.item()
            
            avg_loss = total_loss / len(dataloader)
            print(f"에포크 {epoch+1}/{self.num_epochs}, 손실: {avg_loss:.4f}")

생산 배포 고려 사항

추론 성능 최적화

생산 환경에서 크로스모달 임베딩을 최적화하려면 어떻게 해야 하나요? 실세계 배포에 대한 성능 최적화는 매우 중요합니다:

모델 양자화: 모델 크기 감소 및 추론 속도 증가:

import torch
from torch.quantization import quantize_dynamic

# CPU 추론을 위한 동적 양자화
quantized_model = quantize_dynamic(
    model, 
    {torch.nn.Linear}, 
    dtype=torch.qint8
)

ONNX 변환: 최적화된 추론을 위해 ONNX로 내보내기:

import torch.onnx

dummy_input = processor(text=["샘플"], return_tensors="pt")
torch.onnx.export(
    model,
    tuple(dummy_input.values()),
    "clip_model.onnx",
    input_names=['input_ids', 'attention_mask'],
    output_names=['output'],
    dynamic_axes={
        'input_ids': {0: 'batch_size'},
        'attention_mask': {0: 'batch_size'}
    }
)

배치 처리: 배치를 통해 GPU 활용률 최대화:

def batch_encode(items: List, batch_size: int = 32):
    """효율을 위해 배치로 처리"""
    embeddings = []
    for i in range(0, len(items), batch_size):
        batch = items[i:i+batch_size]
        batch_embeddings = encode_batch(batch)
        embeddings.append(batch_embeddings)
    return np.concatenate(embeddings, axis=0)

대규모 벡터 저장

대규모 응용 프로그램에서는 벡터 데이터베이스가 필수적입니다. 크로스모달 임베딩 구현을 지원하는 프레임워크는 무엇인가요? 모델 자체를 넘어 인프라가 중요합니다:

FAISS (Facebook AI Similarity Search): 효율적인 유사도 검색 라이브러리

  • 수십억 개의 벡터 지원
  • 여러 인덱스 유형 (평평한, IVF, HNSW)
  • GPU 가속 가능

Milvus: 오픈소스 벡터 데이터베이스

from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType

# 스키마 정의
fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
    FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=512),
    FieldSchema(name="metadata", dtype=DataType.JSON)
]
schema = CollectionSchema(fields, description="이미지 임베딩")

# 컬렉션 생성
collection = Collection("images", schema)

# 인덱스 생성
index_params = {
    "metric_type": "IP",  # 내적 곱 (코사인 유사도)
    "index_type": "IVF_FLAT",
    "params": {"nlist": 1024}
}
collection.create_index("embedding", index_params)

Pinecone/Weaviate: 쉽게 확장 및 유지가 가능한 관리형 벡터 데이터베이스 서비스.

고급 사용 사례 및 응용

제로샷 분류

크로스모달 임베딩은 작업 특화 훈련 없이 분류를 가능하게 합니다. 이 능력은 전통적인 컴퓨터 비전 접근법을 넘어갑니다. 예를 들어, 더 전문적인 TensorFlow를 사용한 객체 감지에 관심이 있다면, 특정 감지 작업에 대한 보완적인 감독 학습 접근법으로 간주됩니다.

def zero_shot_classify(image, candidate_labels: List[str], model, processor):
    """임의의 범주로 이미지 분류"""
    # 텍스트 프롬프트 생성
    text_inputs = [f"a photo of a {label}" for label in candidate_labels]
    
    # 임베딩 가져오기
    inputs = processor(
        text=text_inputs, 
        images=image, 
        return_tensors="pt", 
        padding=True
    )
    outputs = model(**inputs)
    
    # 확률 계산
    logits = outputs.logits_per_image
    probs = logits.softmax(dim=1)
    
    # 순위가 정렬된 예측 반환
    sorted_indices = probs.argsort(descending=True)[0]
    return [(candidate_labels[idx], probs[0][idx].item()) for idx in sorted_indices]

# 예시 사용
labels = ["고양이", "개", "새", "고기", "말"]
predictions = zero_shot_classify(image, labels, model, processor)
print(f"최상위 예측: {predictions[0]}")

다중모달 RAG (Retrieval-Augmented Generation)

크로스모달 임베딩을 언어 모델과 결합하면 강력한 다중모달 RAG 시스템을 생성할 수 있습니다. 관련 문서를 검색한 후, 임베딩 모델을 사용한 리랭킹은 검색된 후보를 관련성 기준으로 재정렬하여 결과 품질을 크게 향상시킬 수 있습니다:

class MultimodalRAG:
    def __init__(self, clip_model, llm_model):
        self.clip = clip_model
        self.llm = llm_model
        self.knowledge_base = []
    
    def add_documents(self, images, texts, metadata):
        """다중모달 문서를 지식 기반에 추가"""
        image_embeds = self.clip.encode_images(images)
        text_embeds = self.clip.encode_text(texts)
        
        # 결합 정보 저장
        for i, (img_emb, txt_emb, meta) in enumerate(
            zip(image_embeds, text_embeds, metadata)
        ):
            self.knowledge_base.append({
                'image_embedding': img_emb,
                'text_embedding': txt_emb,
                'metadata': meta,
                'index': i
            })
    
    def retrieve(self, query: str, k: int = 5):
        """관련된 다중모달 콘텐츠 검색"""
        query_embedding = self.clip.encode_text([query])[0]
        
        # 유사도 계산
        similarities = []
        for doc in self.knowledge_base:
            # 모달리티 간 유사도 평균
            img_sim = np.dot(query_embedding, doc['image_embedding'])
            txt_sim = np.dot(query_embedding, doc['text_embedding'])
            combined_sim = (img_sim + txt_sim) / 2
            similarities.append((combined_sim, doc))
        
        # 상위 k개 반환
        similarities.sort(reverse=True)
        return [doc for _, doc in similarities[:k]]
    
    def answer_query(self, query: str):
        """검색된 다중모달 컨텍스트를 사용하여 질문 답변"""
        retrieved_docs = self.retrieve(query)
        
        # 검색된 문서에서 컨텍스트 구성
        context = "\n".join([doc['metadata']['text'] for doc in retrieved_docs])
        
        # LLM으로 답변 생성
        prompt = f"컨텍스트:\n{context}\n\n질문: {query}\n\n답변:"
        answer = self.llm.generate(prompt)
        
        return answer, retrieved_docs

Go로 생산 RAG 시스템을 구현하는 경우, Ollama와 Qwen3 임베딩 모델을 사용한 텍스트 문서 리랭킹 가이드는 검색 품질 최적화에 특히 유용할 수 있습니다.

콘텐츠 감시 및 안전

크로스모달 임베딩은 모달리티 간 부적절한 콘텐츠 탐지에 탁월합니다:

class ContentModerator:
    def __init__(self, model, processor):
        self.model = model
        self.processor = processor
        
        # 안전 범주 정의
        self.unsafe_categories = [
            "폭력 콘텐츠",
            "성인 콘텐츠",
            "혐오 이미지",
            "경험적인 폭력",
            "명백한 자료"
        ]
        
        self.safe_categories = [
            "업무용 안전",
            "가족 친화적",
            "교육 콘텐츠"
        ]
    
    def moderate_image(self, image, threshold: float = 0.3):
        """이미지가 불안전한 콘텐츠를 포함하는지 확인"""
        # 모든 범주 결합
        all_categories = self.unsafe_categories + self.safe_categories
        text_inputs = [f"이미지에 포함된 {cat}" for cat in all_categories]
        
        # 예측 가져오기
        inputs = self.processor(
            text=text_inputs, 
            images=image, 
            return_tensors="pt"
        )
        outputs = self.model(**inputs)
        probs = outputs.logits_per_image.softmax(dim=1)[0]
        
        # 불안전 범주 확인
        unsafe_scores = probs[:len(self.unsafe_categories)]
        max_unsafe_score = unsafe_scores.max().item()
        
        return {
            'is_safe': max_unsafe_score < threshold,
            'confidence': 1 - max_unsafe_score,
            'flagged_categories': [
                self.unsafe_categories[i] 
                for i, score in enumerate(unsafe_scores) 
                if score > threshold
            ]
        }

최선의 실천 방법 및 일반적인 함정

데이터 전처리

최적의 성능을 위해 적절한 전처리가 필수적입니다:

from torchvision import transforms

# 표준 CLIP 전처리
clip_transform = transforms.Compose([
    transforms.Resize(224, interpolation=transforms.InterpolationMode.BICUBIC),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.48145466, 0.4578275, 0.40821073],
        std=[0.26862954, 0.26130258, 0.27577711]
    )
])

편향 및 공정성 처리

크로스모달 모델은 훈련 데이터에서 편향을 상속할 수 있습니다:

완화 전략:

  • 다양한 인구통계 그룹에서 평가
  • 미세 조정 중 편향 제거 기술 사용
  • 공정성 인식 검색 실행
  • 생산 환경에서 정기적인 감사 및 모니터링

임베딩 품질 평가

생산 환경에서 임베딩 품질을 모니터링합니다:

def assess_embedding_quality(embeddings: np.ndarray):
    """임베딩 품질을 위한 메트릭 계산"""
    # 평균 쌍 간 거리 계산
    distances = np.linalg.norm(
        embeddings[:, None] - embeddings[None, :], 
        axis=2
    )
    avg_distance = distances.mean()
    
    # 클러스터링 확인 (낮은 내부 클러스터 거리)
    from sklearn.cluster import KMeans
    kmeans = KMeans(n_clusters=10)
    labels = kmeans.fit_predict(embeddings)
    
    # 실루엣 점수 계산
    from sklearn.metrics import silhouette_score
    score = silhouette_score(embeddings, labels)
    
    return {
        'avg_pairwise_distance': avg_distance,
        'silhouette_score': score
    }

Docker 배포 예제

크로스모달 애플리케이션을 쉽게 배포하기 위해 패키징합니다:

FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04

# Python 및 의존성 설치
RUN apt-get update && apt-get install -y python3-pip

WORKDIR /app

# 의존성 설치
COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt

# 애플리케이션 코드 복사
COPY . .

# API 포트 노출
EXPOSE 8000

# API 서버 실행
CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8000"]
# api.py - 크로스모달 임베딩을 위한 FastAPI 서버
from fastapi import FastAPI, File, UploadFile
from pydantic import BaseModel
import torch
from PIL import Image
import io

app = FastAPI()

# 시작 시 모델 로드
@app.on_event("startup")
async def load_model():
    global model, processor
    model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
    processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
    if torch.cuda.is_available():
        model = model.cuda()

class TextQuery(BaseModel):
    text: str

@app.post("/embed/text")
async def embed_text(query: TextQuery):
    inputs = processor(text=[query.text], return_tensors="pt", padding=True)
    if torch.cuda.is_available():
        inputs = {k: v.cuda() for k, v in inputs.items()}
    
    with torch.no_grad():
        embeddings = model.get_text_features(**inputs)
    
    return {"embedding": embeddings.cpu().numpy().tolist()}

@app.post("/embed/image")
async def embed_image(file: UploadFile = File(...)):
    image = Image.open(io.BytesIO(await file.read()))
    inputs = processor(images=image, return_tensors="pt")
    if torch.cuda.is_available():
        inputs = {k: v.cuda() for k, v in inputs.items()}
    
    with torch.no_grad():
        embeddings = model.get_image_features(**inputs)
    
    return {"embedding": embeddings.cpu().numpy().tolist()}

@app.post("/similarity")
async def compute_similarity(
    text: TextQuery, 
    file: UploadFile = File(...)
):
    # 두 임베딩 모두 가져오기
    image = Image.open(io.BytesIO(await file.read()))
    inputs = processor(text=[text.text], images=image, return_tensors="pt", padding=True)
    
    if torch.cuda.is_available():
        inputs = {k: v.cuda() for k, v in inputs.items()}
    
    outputs = model(**inputs)
    similarity = outputs.logits_per_image[0][0].item()
    
    return {"similarity": similarity}

미래 방향

크로스모달 임베딩 분야는 계속 빠르게 발전하고 있습니다:

더 큰 모달리티 커버리지: 미래의 모델은 터치(촉각 피드백), 냄새, 맛 데이터를 포함하여 진정한 포괄적인 다중모달 이해를 위해 확장될 가능성이 있습니다.

개선된 효율성: 디스티릴레이션 및 효율적인 아키텍처에 대한 연구는 강력한 크로스모달 모델이 엣지 장치에서 접근 가능하도록 할 것입니다.

더 나은 정렬: 모달리티를 더 정확하게 정렬하는 고급 기술, 포함 사이클 일관성 손실 및 적대적 훈련.

구성적 이해: 단순한 객체 인식에서 복잡한 관계 및 구성 이해로 이동.

시간 모델링: 비디오 및 시간 시계열 데이터에 대한 명확한 시간 추론을 가진 임베딩 공간에서의 더 나은 처리.

유용한 링크


크로스모달 임베딩은 AI 시스템이 정보를 처리하고 이해하는 방식에 패러다임의 변화를 가져옵니다. 다양한 데이터 유형 간의 장벽을 무너뜨리면서 이러한 기술은 더 자연스럽고 능력 있는 AI 애플리케이션을 가능하게 합니다. 검색 시스템, 콘텐츠 감시 도구, 창의 애플리케이션을 구축하려면 크로스모달 임베딩을 마스터함으로써 다중모달 AI에서 혁신의 가능성의 세계를 열 수 있습니다.