DeepSeek 라는 중국의 스타트업에서 만든 V3 모델은, OpenAI의 4o 모델에 대응되는 모델로서, 그 성능이 4o와 유사하면서, 추론 비용이 압도적으로 저렴하기에 현재 AI 커뮤니티에서 큰 파장을 불러일으키고 있다.
논문의 Abstract 란에서 바로 벤치마크를 살펴볼 수 있다. Transformer 모델인 만큼 전반적인 벤치마크 수준은 o1, R1 모델 대비 낮지만, 벤치로 식별하기 어려운 창의적인 대화에서는 더 높은 성능을 보여준다.
1. 소개
최근 몇년간 LLM 모델은 진화를 거듭하면서 AGI에 다가가고 있다. 대표적으로 ChatGPT, Claude, LLaMA, Qwen 등을 꼽을 수 있다. 이러한 변화의 물결에 올라, DeepSeek 사는 V3 모델을 제작하였다. V3는 MoE를 기반으로 제작되었으며, 오픈 소스 모델의 한계를 확장하기 위해 제작하였다고 밝히고 있다.
V3 모델을 제작하며 DeepSeek 측에서는 특히 '비용적' 측면에서 모델을 강화하려 노력했다 이를 위해 MLA(Multi-head Latent Attention) 와 학습 비용 절약을 위해 DeepSeekMoE를 채택하고 있다. 이러한 두 아키텍처는 이미 V2 모델에서 검증되었으며, 효율적인 학습과 추론을 달성하면서도 견고한 모델 성능을 유지할 수 있는 능력을 입증했다.
특히 `Table 1` 에서 보여지는 총 훈련 비용이 인상적이다. 약 560만 달러, 즉 한화 80억원 가량의 비용만으로 최첨단 폐쇄형 모델 성능에 도달한 것이다. 또한 여기서 언급된 H800 GPU는 중국시장에 판매하기 위해 고의적으로 성능을 낮춘 버전이다. (해당 내용에 관해서, 실제로는 '대여' 해서 학습하지 않았음에도, GPU '대여' 기준으로 학습비용을 낮춰잡았다는 일부 비판여론이 존재한다.)
2. 구조
위에서 언급한 MLA와 DeepSeekMoE가 해당 모델에서 특징적인 부분이다.
이미지 좌측 부분에 Transformer Block을 확인할 수 있다. 일반적으로 Transformer Decoder 구조는 아래와 같이 구성된다.
LLM 모델의 경우 일반적으로 Decoder 만 사용되지만, 원론적인 Decoder 구조와 다른 이유는 효율을 위해 DeepSeek 사에서 여러 변형을 거쳐 도출된 구조로 추정된다. V3 모델은 아래와 같이 구성되어 있다.
- RMSNorm → Attention → RMSNorm → Feed-Forward Netwok
- Attention 구조는 MLA
- FFN 구조는 DeepSeekMoE
V3 모델의 핵심은 MLA, DeepSeekMoE 이기에, 해당 구조에 관해서 리뷰한다.
2-1. Multi-head Latent Attention
해당 리뷰를 보고있다면, Attention, Multi-Head 같은 기본 지식을 인지하고 있을 것이기에 생략한다.
그렇다면 결국 Latent(잠재) 라는 단어가 남는데, 이 단어가 바로 키 포인트이다. 기본적으로 Attention을 진행할 때 관련성 있는 단어들간의 중요성을 평가하는 과정을 거친다. 이 때 모든시점의 은닉 상태들을 KV(Key-Value) Cache 라는 이름으로 저장하는데, 이 과정에서 매우 많은 메모리를 소모하게 된다. 때문에 DeepSeek 팀에서는 KV 캐시를 작게 압축할 수 있는 방법인 MLA를 적용했다.
$$\begin{align}
\boxed{\mathbf{c}_t^{KV}} &= \mathbf{W}^{DKV} \mathbf{h}_t, \tag{1} \\
\left[ \mathbf{k}_{t,1}^C; \mathbf{k}_{t,2}^C; \ldots; \mathbf{k}_{t,n_h}^C \right] = k^{C}_{t} &= \mathbf{W}^{UK} \mathbf{c}_t^{KV}, \tag{2} \\
\boxed{\mathbf{k}_t^R} &= \text{RoPE}\left( \mathbf{W}^{KR} \mathbf{h}_t \right), \tag{3} \\
\mathbf{k}_{t,i} &= \left[ \mathbf{k}_{t,i}^C;\, \mathbf{k}_t^R \right], \tag{4} \\
\left[ \mathbf{v}_{t,1}^C; \mathbf{v}_{t,2}^C; \ldots; \mathbf{v}_{t,n_h}^C \right] = \mathbf{v}_t^C &= \mathbf{W}^{UV} \mathbf{c}_t^{KV}, \tag{5}
\end{align}$$
- $\boxed{\mathbf{c}_t^{KV}} = \mathbf{W}^{DKV} \mathbf{h}_t$ : 입력 임베딩 $h_t$를 저차원 잠재 벡터 $c_t^{KV}$로 압축
- $C$ : Compressed 벡터
- $h_t$ : $t$번째 토큰 입력 임베딩 벡터 (차원 : $d$)
- $W^{DKV}$ : Down-Projection 행렬 (차원 : $d_c \times d$)
- $c_t^{KV}$ : 압축된 Key Value 잠재 벡터 (차원 : $d_c$)
- 목적 : KV 캐시 메모리 사용량 감소
- $\left[ \mathbf{k}_{t,1}^C; \mathbf{k}_{t,2}^C; \ldots; \mathbf{k}_{t,n_h}^C \right] = k^{C}_{t} = \mathbf{W}^{UK} \mathbf{c}_t^{KV}$ : 압축 벡터 $c_t^{KV}$를 Up-Projection 해서 Multihead-Key 를 복원
- $[;]$ : 벡터 연결 연산자
- $W^{UK}$ : Key Up-Projection 행렬 (차원 : $d_h h_n \times d_c$)
- $k^C_{t,i}$ : $i$번째 헤드의 압축 Key 벡터 (차원 : $d_h$)
- $n_h$ : 어텐션 헤드 수
- 목적 : 행렬 분해를 통해 계산 효율성 확보
- $\boxed{\mathbf{k}_t^R} = \text{RoPE}\left( \mathbf{W}^{KR} \mathbf{h}_t \right)$ : 입력 임베딩에 RoPE(Rotary Positional Embedding)를 적용한 Key 생성
- $W^{KR}$ : RoPE Key 프로젝션 행렬. (차원 : $d^R_h \times d$)
- $K^R_t$ : 윗첨자 $R$은 RoPE가 적용된 Key 벡터를 의미.
- 목적 : 위치 정보를 명시적으로 인코딩하여 Transformer 고질적 문제 해결
- $\mathbf{k}_{t,i} = \left[ \mathbf{k}_{t,i}^C;\, \mathbf{k}_t^R \right]$ : 압축 키($K^{C}_{t,i}$) 와 RoPE Key ($K^R_t$)를 연결
- $k_{t,i}$ : $i$번째 헤드의 최종 Key (차원 : $d_h + d^R_h$)
- 효과 : 압축 정보와 위치 정보를 병렬로 활용.
- $\left[ \mathbf{v}_{t,1}^C; \mathbf{v}_{t,2}^C; \ldots; \mathbf{v}_{t,n_h}^C \right] = \mathbf{v}_t^C = \mathbf{W}^{UV} \mathbf{c}_t^{KV}$ : 압축 벡터 $c^{KV}_t$ 를 Up-Projection 하여 멀티헤드 value 생성.
- $W^{UV}$ : Value Up-Projection 행렬 (차원 : $d_h n_h \times d_c$)
- $v^{C}_{t,i}$: $i$번째 헤드의 Value 벡터 (차원 : $d_h$)
- 즉, $v^{C}_{t,1}$ 내의 $C$는 $c^{KV}_{t}$ 에서 복원되었음을 의미.
- 효과 : Key-Value 쌍이 동일한 압축 벡터 $c^{KV}_{t}$를 공유하여 메모리 효율성 증가.
복잡하게 기술되어 있지만 전체적으로 요약하자면 아래와 같다.
- 입력 압축: 고차원 입력($h_t$) → 저차원 ($c^{KV}_{t}$)
- Key 생성 : 압축 Key복원 (2) + RoPE 적용 (3) + 결합 (4)
- Value 생성 : 압축 벡터로부터 직접 복원 (5)
- 결론 : KV 캐시 크기 감소 ($d_c \ll d_h n_h$)
- $d_c$ : 압축차원
- $d_h h_h$ : 원본차원
더하여, 위 로직과 비슷하게 Attention 의 Query 역시 훈련중 활성 메모리를 줄일 수 있는 low-rank 압축을 수행한다. 전반적으로 KV 와 비슷한 로직이므로 상세한 설명은 생략하겠다.
$$\begin{align}
{c}_t^{Q} &= \mathbf{W}^{DQ} \mathbf{h}_t, \tag{6} \\
\left[ \mathbf{q}_{t,1}^C; \mathbf{q}_{t,2}^C; \ldots; \mathbf{q}_{t,n_h}^C \right] = q^{C}_{t} &= \mathbf{W}^{UQ} \mathbf{c}_t^{Q}, \tag{7} \\
\left[ \mathbf{q}_{t,1}^R; \mathbf{q}_{t,2}^R; \ldots; \mathbf{q}_{t,n_h}^R \right] = q^{R}_{t} &= \text{RoPE}(W^{QR} c^Q_t), \tag{8}\\
\mathbf{q}_{t,i} &= \left[ \mathbf{q}_{t,i}^C;\, \mathbf{q}_{t,i}^R \right], \tag{9} \\
\end{align}$$
2-2. DeepSeekMoE
MoE(Mixture of Experts) 는 여러 개의 전문가(expert) 하위 네트워크로 분할하는 신경망의 아키텍처 패턴으로서, 처음 해당 구조를 들엇을 때는 Attention에 사용될 것이라 예상했는데, V3 모델에 사용된 MoE는 FFN 레이어에서 사용된다.
For Feed-Forward Networks (FFNs), DeepSeek-V3 employs the DeepSeekMoE architecture (Dai et al., 2024)
V3에 사용된 DeepSeekMoE는 전통적인 MoE 기법인 GShard 와는 다르게, 세분화된 전문가들을 사용하며 일부 전문가들을 공유해서 사용한다.
아래 수식은, $u_t$가 FFN의 $t$번째 토큰의 입력을 나타낸다고 가정할 때, FFN의 출력 $h^{\prime}_t$ 를 계산하는 방법이다.
$$\begin{align}
\mathbf{h}_t^{\prime} &= \mathbf{u}_t + \sum_{i=1}^{N_s} \text{FFN}_i^{(s)}(\mathbf{u}_t) + \sum_{i=1}^{N_r} g_{i,t} \text{FFN}_i^{(r)}(\mathbf{u}_t), \tag{12} \\
g_{i,t} &= \frac{g_{i,t}'}{\sum_{j=1}^{N_r} g_{j,t}'}, \tag{13} \\
g_{i,t}' &=
\begin{cases}
s_{i,t}, & s_{i,t} \in \text{Top}k(\{s_{j,t} | 1 \leq j \leq N_r\}, K_r), \\
0, & \text{otherwise},
\end{cases} \tag{14} \\
s_{i,t} &= \sigma(\mathbf{u}_t^\top \mathbf{e}_i), \tag{15}
\end{align}$$
상세하게 설명하자면 아래와 같다.
- $\mathbf{h}_t^{\prime} = \mathbf{u}_t + \sum_{i=1}^{N_s} \text{FFN}_i^{(s)}(\mathbf{u}_t) + \sum_{i=1}^{N_r} g_{i,t} \text{FFN}_i^{(r)}(\mathbf{u}_t)$ : 최종 출력 계산
- $h^{\prime}_t$ : 최종 출력 벡터(토큰 $t$에 대한 출력.)
- $u_t$ : 입력 벡터 (토큰 $t$에 대한)
- $FFN_i^{(s)}$ : $i$ 번째 공유 전문가(Shared Expert)로, 모든 토큰이 공통으로 사용하는 전문가.
- $FFN_i^{(r)}$ : $i$번째 라우팅 전문가(Routed Expert)로, 특정 토큰에 따라 선택되는 전문가.
- $g_{i,t}$ : $i$번째 라우팅 전문가의 가중치. 해당 값은 토큰 $t$와 전문가 $i$의 유사도에 따라 결정.
- $N_s$ : 공유 전문가의 수
- $N_r$ : 라우팅 전문가의 수
- $g_{i,t} = \frac{g_{i,t}'}{\sum_{j=1}^{N_r} g_{j,t}'}$ : 가중치 정규화 방법으로서, 선택된 전문가들의 가중치 합이 1이 되도록 보장하며 출력의 스케일 조정.
- $g_{i,t}'= \begin{cases} s_{i,t}, & s_{i,t} \in \text{Top}k(\{s_{j,t} | 1 \leq j \leq N_r\}, K_r), \\ 0, & \text{otherwise}, \end{cases}$ : 토큰 $t$와 각 라우팅 전문가 간의 유사도 점수를 기반으로 상위 $K_r$개의 전문가를 선택한다. 선택된 전문가의 초기 가중치 유사도는 점수 $s_{i,t}$로 설정되고, 나머지 전문가의 초기 가중치는 0로 설정한다.
- $s_{i,t} = \sigma(\mathbf{u}_t^\top \mathbf{e}_i)$ : 토큰 $t$와 라우팅 전문가 $i$간의 유사도를 계산한다. 이 때 내적값이 클수록 두 벡터가 유사하다는 것을 의미하며, sigmoid($\sigma$) 0~1 범위로 정규화 된다.
최종적으로 정리하자면, DeepSeekMoE는 공유 전문가, 라우팅 전문가를 사용하여 입력 토큰에 따라 다른 전문가를 선택하는 방식으로, 이 선택과정은 유사도 점수를 기반으로 상위 $K_r$개의 전문가를 선택하고, 이들의 출력을 가중합으로 결합한다. 그 후 가중치 정규화를 통해 출력 스케일을 조정하고, $\sigma$ 함수를 통해 유사도 점수를 정규화한다.
외에도 논문에서는 적용된 여러 기법들에 대해서 설명하고 있다. 하지만 핵심적인 기법은 MLA와 DeepSeekMoE 기법이기에 나머지 기법들에 대해선 생략한다.
2-3. FP8
해당 모델은 여러 버전으로 배포된 것으로 보인다. HuggingFace 에서 Tensor type 이 아래와 같기 때문이다.
일반적으로 BF16 를 사용하는데, 해당 모델에서는 FP8을 사용하면서도 BF16대비 손실오차 0.25% 이하로 유지하는데 성공하였다. 즉, 성능하락은 체감하기 어려운 반면, 메모리 소모량은 크게 줄일 수 있는 방법을 적용하였다.
3. 결론
DeepSeek V3는 그 성능도 최고 수준이지만, 가장 무서운 점은 '압도적인 가성비' 이다. 많은 사람들이 중국 제품에 대해 안전하지 못하다는 감정을 느끼면서도 중국 제품을 찾는 이유는 '가성비' 이다. 개인적으로 생각하기에도 3배 이상 저렴하다면, 일상적인 용도로 DeepSeek 제품을 충분히 권장할만 하다.(오히려 권장하지 않는다는게 문제라는 생각이다.)
한편으로 느끼는 궁금증은 다른 AI 제조사들의 비싼 비용이다. GPT-4o도 MoE를 사용하고, 내부적으로 많은 최적화 기법들이 고려되었을 것이다. 하지만 4o는 V3 보다 3배 비싸며, o1은 R1 보다 30배 더 비싸다.
논문을 읽어보면서 느끼길, 논문의 내용을 내가 구현하기에는 무리가 있는 레벨이지만, 결코 OpenAI 가 구현하기에 버거울 수준의 내용은 아니라고 판단했다. 하지만 DeepSeek는 구현했고, OpenAI는 현재까지 구현하지 못했다. 조만간 2주내로 o3, o3-mini 모델이 공개될 예정인데... 잘 나와서 LLM 기술에서 경쟁이 활발해지길 바란다.