🤖 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 양자화로 메모리를 절약할 수 있습니다.

🔗 관련 용어

📚 더 배우기