🤖 AI/ML

MoE

Mixture of Experts

여러 전문가(Expert) 네트워크를 선택적으로 활성화하는 아키텍처. 효율적인 대규모 모델 구축의 핵심 기술로 GPT-4, Mixtral, Gemini 등에 적용.

📖 상세 설명

MoE(Mixture of Experts)는 여러 개의 "전문가" 서브네트워크 중 일부만 선택적으로 활성화하여 연산 효율을 극대화하는 신경망 아키텍처입니다. 전체 파라미터 수는 크지만 실제 추론 시에는 일부만 사용하므로 "Sparse" 모델이라고도 불립니다.

MoE의 핵심은 Gating Network(라우터)입니다. 각 입력 토큰이 들어오면 라우터가 어떤 Expert를 활성화할지 결정합니다. 예를 들어 Mixtral 8x7B는 8개 Expert 중 Top-2를 선택하여 총 45B 파라미터 중 12B만으로 추론합니다. 이를 통해 Dense 모델 대비 2-4배 적은 FLOPs로 유사한 성능을 달성합니다.

MoE의 장점은 모델 용량(capacity) 확장에 있습니다. Expert 수를 늘려 전체 지식 용량을 키우면서도 추론 비용은 일정하게 유지할 수 있습니다. Google의 Switch Transformer는 1.6T 파라미터를 달성했고, Mistral Large 3는 675B 중 41B만 활성화합니다.

실무에서 MoE는 대규모 LLM 서비스의 비용 효율화에 필수입니다. 다만 전체 파라미터를 메모리에 로드해야 하므로 메모리 요구량은 줄지 않으며, Expert 간 로드 밸런싱이 학습의 핵심 과제입니다. vLLM, TensorRT-LLM 등 MoE 최적화 서빙 프레임워크를 사용하면 효율적인 배포가 가능합니다.

모델총 파라미터활성 파라미터Expert 수
Mixtral 8x7B45B12B8 (Top-2)
Mixtral 8x22B141B39B8 (Top-2)
Mistral Large 3675B41BGranular MoE
Switch Transformer1.6T~12B2048 (Top-1)

💻 코드 예제

# MoE 모델 사용 예제 (Mixtral)
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# Mixtral 8x7B Instruct 로드 (약 90GB VRAM 필요)
model_id = "mistralai/Mixtral-8x7B-Instruct-v0.1"

tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype=torch.bfloat16,
    device_map="auto",  # 여러 GPU에 자동 분산
    load_in_4bit=True   # 양자화로 메모리 절약 (약 25GB)
)

# 추론
messages = [{"role": "user", "content": "MoE 아키텍처의 장단점을 설명해주세요."}]
inputs = tokenizer.apply_chat_template(messages, return_tensors="pt").to(model.device)

outputs = model.generate(
    inputs,
    max_new_tokens=512,
    do_sample=True,
    temperature=0.7,
    top_p=0.9
)

response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(response)

# ===== MoE 모델 서빙 (vLLM) =====
# pip install vllm
from vllm import LLM, SamplingParams

# vLLM은 MoE 전용 최적화 지원
llm = LLM(
    model="mistralai/Mixtral-8x7B-Instruct-v0.1",
    tensor_parallel_size=2,  # 2 GPU 병렬
    dtype="bfloat16"
)

sampling_params = SamplingParams(temperature=0.7, max_tokens=512)

prompts = ["[INST] Python에서 async/await의 작동 원리는? [/INST]"]
outputs = llm.generate(prompts, sampling_params)

for output in outputs:
    print(output.outputs[0].text)

# ===== MoE 레이어 간단 구현 =====
import torch.nn as nn
import torch.nn.functional as F

class SimpleMoE(nn.Module):
    def __init__(self, dim, num_experts=8, top_k=2):
        super().__init__()
        self.num_experts = num_experts
        self.top_k = top_k

        # Expert FFN 네트워크들
        self.experts = nn.ModuleList([
            nn.Sequential(
                nn.Linear(dim, dim * 4),
                nn.GELU(),
                nn.Linear(dim * 4, dim)
            ) for _ in range(num_experts)
        ])

        # Gating Network (라우터)
        self.gate = nn.Linear(dim, num_experts)

    def forward(self, x):
        # 라우터: 각 토큰에 대해 Expert 선택
        gate_logits = self.gate(x)  # (batch, seq, num_experts)

        # Top-K Expert 선택
        weights, selected = torch.topk(gate_logits, self.top_k, dim=-1)
        weights = F.softmax(weights, dim=-1)

        # 선택된 Expert들의 출력 가중 합산
        output = torch.zeros_like(x)
        for i, expert in enumerate(self.experts):
            mask = (selected == i).any(dim=-1)
            if mask.any():
                expert_out = expert(x[mask])
                # 해당 Expert의 가중치 적용
                for k in range(self.top_k):
                    k_mask = (selected[..., k] == i) & mask.unsqueeze(-1)
                    if k_mask.any():
                        output[k_mask[..., 0]] += weights[..., k:k+1][k_mask[..., 0]] * expert_out

        return output

# 사용
moe = SimpleMoE(dim=512, num_experts=8, top_k=2)
x = torch.randn(2, 10, 512)  # (batch=2, seq=10, dim=512)
out = moe(x)
print(f"MoE 출력: {out.shape}")  # (2, 10, 512)

🗣️ 실무에서 이렇게 말하세요

💬 모델 선정 회의에서
"비용 효율을 위해 MoE 모델을 검토해봐요. Mixtral 8x7B는 45B 파라미터지만 추론 FLOPs는 12B Dense와 비슷해요. 같은 GPU 예산으로 더 큰 모델 용량을 쓸 수 있습니다."
💬 면접에서
"MoE는 Sparse 아키텍처로 전체 파라미터 중 일부 Expert만 활성화합니다. Gating Network가 입력별로 적합한 Expert를 선택하죠. 연산량은 줄지만 메모리는 전체 파라미터를 로드해야 해서 줄지 않습니다. 학습 시 Load Balancing Loss로 Expert 활용 균형을 맞추는 게 중요합니다."
💬 기술 토론에서
"Dense vs MoE 트레이드오프가 있어요. Dense는 구현이 단순하고 메모리 효율적이지만 스케일링 한계가 있고, MoE는 연산 효율이 좋지만 Expert Parallelism 분산 처리가 필요해요. 대규모 서비스에선 MoE가 유리합니다."

⚠️ 흔한 실수 & 주의사항

❌
메모리 절감 기대

MoE는 연산(FLOPs)을 줄이지 메모리를 줄이지 않습니다. 8x7B MoE는 여전히 45B 전체를 메모리에 로드해야 합니다.

❌
단일 GPU 시도

대형 MoE 모델은 단일 GPU에 맞지 않습니다. Tensor Parallelism이나 양자화가 필수입니다.

✅
올바른 접근: 최적화된 서빙

vLLM, TensorRT-LLM 등 MoE 최적화를 지원하는 프레임워크를 사용하세요. Expert Parallelism으로 여러 GPU에 Expert를 분산하면 효율적입니다. 4-bit 양자화로 메모리를 절약할 수 있습니다.

🔗 관련 용어

📚 더 배우기