<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>MoE on Jiang Yi(姜祎)'s Homepage</title><link>https://jiangyigithub.github.io/ai.github.io/tags/moe/</link><description>Recent content in MoE on Jiang Yi(姜祎)'s Homepage</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Wed, 08 Apr 2026 21:44:44 +0800</lastBuildDate><atom:link href="https://jiangyigithub.github.io/ai.github.io/tags/moe/index.xml" rel="self" type="application/rss+xml"/><item><title>Notes on Qwen3-Next</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-qwen3-next/</link><pubDate>Fri, 23 Jan 2026 10:29:56 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-qwen3-next/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;当前大语言模型在性能与效率上面临双重挑战：纯 Softmax 注意力计算成本高，而纯线性注意力则性能不足。Qwen3-Next 尝试通过&lt;strong&gt;混合注意力机制&lt;/strong&gt;解决这一矛盾，同时结合 MoE 架构与多项训练优化策略，实现在保持高性能的同时大幅提升训练与推理效率。&lt;/p&gt;
&lt;p&gt;Qwen3-Next 包含三个模型：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Qwen3-Next-80B-A3B-Base&lt;/li&gt;
&lt;li&gt;Qwen3-Next-80B-A3B-Instruct&lt;/li&gt;
&lt;li&gt;Qwen3-Next-80B-A3B-Thinking&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;h3 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h3&gt;&lt;p&gt;模型架构如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-qwen3-next/Qwen3-Next-architecture.png"
width="2204"
height="2348"
loading="lazy"
alt="architecture of Qwen3-Next"
class="gallery-image"
data-flex-grow="93"
data-flex-basis="225px"
&gt;&lt;/p&gt;
&lt;h3 id="hybrid-attention"&gt;&lt;a href="#hybrid-attention" class="header-anchor"&gt;&lt;/a&gt;Hybrid Attention
&lt;/h3&gt;&lt;p&gt;作者首先总结了 linear attention 和 softmax attention 各自的优缺点。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;pros&lt;/th&gt;
&lt;th&gt;cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;linear attention&lt;/td&gt;
&lt;td&gt;fast&lt;/td&gt;
&lt;td&gt;low performance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;softmax attention&lt;/td&gt;
&lt;td&gt;slow&lt;/td&gt;
&lt;td&gt;high performance&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;因此，作者的动机就是是结合 linear attention 与 softmax attention, 在局部利用 linear attention 的高效性来提高训练和推理效率，在关键部分使用 softmax attention 来提高模型的能力。 这种混合注意力机制之前也有很多模型采用，比如 &lt;a class="link" href="https://maosong.website/p/notes-on-minimax-01/" target="_blank" rel="noopener"
&gt;MiniMax-01&lt;/a&gt; 等。最终 Qwen3-Next 使用了 Gated DeltaNet+Gated Attention 的混合注意力机制，模型的 transformer layers 按照 4 个为一组，前三层使用 Gated DeltaNet, 第四层使用 Gated Attention.&lt;/p&gt;
&lt;p&gt;下面是一些细节：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Gated DeltaNet 相比于 &lt;a class="link" href="https://maosong.website/p/notes-on-rnope-swa/" target="_blank" rel="noopener"
&gt;SWA&lt;/a&gt; 和 Mamba2, 其 in-context learning 能力更强&lt;/li&gt;
&lt;li&gt;对于 softmax attention:
&lt;ol&gt;
&lt;li&gt;使用了 &lt;a class="link" href="https://maosong.website/p/notes-on-gated-attention/" target="_blank" rel="noopener"
&gt;Gated Attention&lt;/a&gt; 提出的 gating 机制来解决 massive activation 和 attention sink 问题&lt;/li&gt;
&lt;li&gt;将 attention head 的 dimension 从 128 提高到 256&lt;/li&gt;
&lt;li&gt;使用了和 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v3/" target="_blank" rel="noopener"
&gt;DeepSeek-V3&lt;/a&gt; 类似的 partial RoPE 机制，仅对前 $25\%$ 的元素进行旋转&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="moe"&gt;&lt;a href="#moe" class="header-anchor"&gt;&lt;/a&gt;MoE
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;1 个共享专家，512 个路由专家，其中激活专家个数为 10 个。&lt;/li&gt;
&lt;li&gt;对于 MoE router 的参数，作者还进行了 normalization 来保证每个专家被选择的概率相同。&lt;/li&gt;
&lt;li&gt;与 &lt;a class="link" href="https://maosong.website/p/notes-on-qwen3/" target="_blank" rel="noopener"
&gt;Qwen3&lt;/a&gt; 一致，Qwen3-Next 也是用了 &lt;a class="link" href="https://maosong.website/p/notes-on-global-batch-load-balancing/" target="_blank" rel="noopener"
&gt;Global-batch load balancing&lt;/a&gt; 策略，在保持激活专家数不变的情况下，通过提高总专家个数来降低训练损失。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="normalization-and-training"&gt;&lt;a href="#normalization-and-training" class="header-anchor"&gt;&lt;/a&gt;Normalization and Training
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;使用 Gemma 提出的 Zero-Centered RMSNorm 以及 weight decay 来避免过大的权重出现&lt;/li&gt;
&lt;li&gt;为了提高数据使用效率，作者还使用了 MTP 策略来提高训练效率，模型表现以及 Speculative decoding 的接受率。&lt;/li&gt;
&lt;li&gt;预训练时，Qwen3-Next 使用了&lt;strong&gt;15T&lt;/strong&gt; token 进行训练，训练时间相比于 Qwen3-30B-A3B 有了大幅度的提升&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="experiments"&gt;&lt;a href="#experiments" class="header-anchor"&gt;&lt;/a&gt;Experiments
&lt;/h2&gt;&lt;h3 id="efficiency"&gt;&lt;a href="#efficiency" class="header-anchor"&gt;&lt;/a&gt;Efficiency
&lt;/h3&gt;&lt;p&gt;下图是 Qwen3-Next 与 Qwen3-32B 模型的训练效率对比&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-qwen3-next/Qwen3-Next-pre-training-efficiency.png"
width="2860"
height="1114"
loading="lazy"
alt="Pre-training efficiency of Qwen3-Next"
class="gallery-image"
data-flex-grow="256"
data-flex-basis="616px"
&gt;&lt;/p&gt;
&lt;p&gt;从结果可以看出，相比于 Qwen3-32B, Qwen3-Next 只用了 $9.3\%$ 的算力就达到了更强的表现。&lt;/p&gt;
&lt;p&gt;并且，在 inference 阶段，由于使用了 linear attention, Qwen3-Next 的效率也更高，下面是 Qwen3-Next 相比于 Qwen3-32B 的效率提升&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;4K&lt;/th&gt;
&lt;th&gt;32K&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prefilling&lt;/td&gt;
&lt;td&gt;$7\times$&lt;/td&gt;
&lt;td&gt;$10\times$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decoding&lt;/td&gt;
&lt;td&gt;$4\times$&lt;/td&gt;
&lt;td&gt;$10\times$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="performance"&gt;&lt;a href="#performance" class="header-anchor"&gt;&lt;/a&gt;Performance
&lt;/h3&gt;&lt;p&gt;下面是 Qwen3-Next-Base 的表现&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-qwen3-next/Qwen3-Next-base-performance.png"
width="1288"
height="844"
loading="lazy"
alt="Performance of Qwen3-Next-Base"
class="gallery-image"
data-flex-grow="152"
data-flex-basis="366px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，Qwen3-Next-Base 在多个 Benchmark 上的表现仅次于 Qwen3-235B-A22B&lt;/p&gt;
&lt;p&gt;Qwen3-Next-Instruct 的表现如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark&lt;/th&gt;
&lt;th&gt;Qwen3-Next-80B-A3B-Instruct&lt;/th&gt;
&lt;th&gt;Qwen3-235B-A22B-Instruct-2507&lt;/th&gt;
&lt;th&gt;Qwen3-32B Non-thinking&lt;/th&gt;
&lt;th&gt;Qwen3-30B-A3B-Instruct-2507&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SuperGPQA&lt;/td&gt;
&lt;td&gt;58.8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;62.6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;43.2&lt;/td&gt;
&lt;td&gt;53.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AIME25&lt;/td&gt;
&lt;td&gt;69.5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;70.3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;20.2&lt;/td&gt;
&lt;td&gt;61.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LiveCodeBench v6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;56.6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;51.8&lt;/td&gt;
&lt;td&gt;29.1&lt;/td&gt;
&lt;td&gt;43.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arena-Hard v2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;82.7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;79.2&lt;/td&gt;
&lt;td&gt;34.1&lt;/td&gt;
&lt;td&gt;69.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LiveBench&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;75.8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;75.4&lt;/td&gt;
&lt;td&gt;59.8&lt;/td&gt;
&lt;td&gt;69.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Qwen3-Next-Instruct 的长文本表现（RULER Benchmark）如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Avg.&lt;/th&gt;
&lt;th&gt;4K&lt;/th&gt;
&lt;th&gt;8K&lt;/th&gt;
&lt;th&gt;16K&lt;/th&gt;
&lt;th&gt;32K&lt;/th&gt;
&lt;th&gt;64K&lt;/th&gt;
&lt;th&gt;96k&lt;/th&gt;
&lt;th&gt;128K&lt;/th&gt;
&lt;th&gt;192k&lt;/th&gt;
&lt;th&gt;256k&lt;/th&gt;
&lt;th&gt;384k&lt;/th&gt;
&lt;th&gt;512k&lt;/th&gt;
&lt;th&gt;640k&lt;/th&gt;
&lt;th&gt;768k&lt;/th&gt;
&lt;th&gt;896k&lt;/th&gt;
&lt;th&gt;1M&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-30B-A3B-Instruct-2507&lt;/td&gt;
&lt;td&gt;86.8&lt;/td&gt;
&lt;td&gt;98.0&lt;/td&gt;
&lt;td&gt;96.7&lt;/td&gt;
&lt;td&gt;96.9&lt;/td&gt;
&lt;td&gt;97.2&lt;/td&gt;
&lt;td&gt;93.4&lt;/td&gt;
&lt;td&gt;91.0&lt;/td&gt;
&lt;td&gt;89.1&lt;/td&gt;
&lt;td&gt;89.8&lt;/td&gt;
&lt;td&gt;82.5&lt;/td&gt;
&lt;td&gt;83.6&lt;/td&gt;
&lt;td&gt;78.4&lt;/td&gt;
&lt;td&gt;79.7&lt;/td&gt;
&lt;td&gt;77.6&lt;/td&gt;
&lt;td&gt;75.7&lt;/td&gt;
&lt;td&gt;72.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-235B-A22B-Instruct-2507&lt;/td&gt;
&lt;td&gt;92.5&lt;/td&gt;
&lt;td&gt;98.5&lt;/td&gt;
&lt;td&gt;97.6&lt;/td&gt;
&lt;td&gt;96.9&lt;/td&gt;
&lt;td&gt;97.3&lt;/td&gt;
&lt;td&gt;95.8&lt;/td&gt;
&lt;td&gt;94.9&lt;/td&gt;
&lt;td&gt;93.9&lt;/td&gt;
&lt;td&gt;94.5&lt;/td&gt;
&lt;td&gt;91.0&lt;/td&gt;
&lt;td&gt;92.2&lt;/td&gt;
&lt;td&gt;90.9&lt;/td&gt;
&lt;td&gt;87.8&lt;/td&gt;
&lt;td&gt;84.8&lt;/td&gt;
&lt;td&gt;86.5&lt;/td&gt;
&lt;td&gt;84.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-Next-80B-A3B-Instruct&lt;/td&gt;
&lt;td&gt;91.8&lt;/td&gt;
&lt;td&gt;98.5&lt;/td&gt;
&lt;td&gt;99.0&lt;/td&gt;
&lt;td&gt;98.0&lt;/td&gt;
&lt;td&gt;98.7&lt;/td&gt;
&lt;td&gt;97.6&lt;/td&gt;
&lt;td&gt;95.0&lt;/td&gt;
&lt;td&gt;96.0&lt;/td&gt;
&lt;td&gt;94.0&lt;/td&gt;
&lt;td&gt;93.5&lt;/td&gt;
&lt;td&gt;91.7&lt;/td&gt;
&lt;td&gt;86.9&lt;/td&gt;
&lt;td&gt;85.5&lt;/td&gt;
&lt;td&gt;81.7&lt;/td&gt;
&lt;td&gt;80.3&lt;/td&gt;
&lt;td&gt;80.3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以看到， Qwen3-Next-Instruct 在 1M 长度范围内保持稳定性能，整体平均得分 91.8，接近 Qwen3-235B（92.5）。&lt;/p&gt;
&lt;p&gt;Qwen3-Next-Thinking 的表现如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Benchmark&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Qwen3-Next-80B-A3B-Thinking&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Gemini-2.5-Flash Thinking&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Qwen3-32B Thinking&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Qwen3-30B-A3B-Thinking2507&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SuperGPQA&lt;/td&gt;
&lt;td&gt;60.8&lt;/td&gt;
&lt;td&gt;57.8&lt;/td&gt;
&lt;td&gt;54.1&lt;/td&gt;
&lt;td&gt;56.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AIME25&lt;/td&gt;
&lt;td&gt;87.8&lt;/td&gt;
&lt;td&gt;72.0&lt;/td&gt;
&lt;td&gt;72.9&lt;/td&gt;
&lt;td&gt;85.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LiveCodeBench v6&lt;/td&gt;
&lt;td&gt;68.7&lt;/td&gt;
&lt;td&gt;61.2&lt;/td&gt;
&lt;td&gt;60.6&lt;/td&gt;
&lt;td&gt;66.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arena-Hard v2&lt;/td&gt;
&lt;td&gt;62.3&lt;/td&gt;
&lt;td&gt;56.7&lt;/td&gt;
&lt;td&gt;48.4&lt;/td&gt;
&lt;td&gt;56.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LiveBench&lt;/td&gt;
&lt;td&gt;76.6&lt;/td&gt;
&lt;td&gt;74.3&lt;/td&gt;
&lt;td&gt;74.9&lt;/td&gt;
&lt;td&gt;76.8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以看到，Qwen3-Next-Thinking 的表现在除了 Livebench 之外的三个 Benchmark 均达到了 SOTA&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Qwen3-Next 通过&lt;strong&gt;混合注意力架构&lt;/strong&gt;与&lt;strong&gt;精细化 MoE 设计&lt;/strong&gt;，在训练与推理效率上实现突破性提升。其仅以较小计算代价达到接近超大模型性能的表现，为下一代高效大语言模型的设计提供了重要参考。&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qwen.ai/blog?id=4074cca80393150c248e508aa62983f9cb7d27cd&amp;amp;from=research.latest-advancements-list" target="_blank" rel="noopener"
&gt;Qwen3-Next: Towards Ultimate Training &amp;amp; Inference Efficiency&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on GLaM</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-glam/</link><pubDate>Tue, 06 Jan 2026 18:07:29 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-glam/</guid><description>&lt;p&gt;Google 在 2022 年 8 提出了 GLaM，一个基于 MoE 架构的大语言模型系列，模型超过了 GPT-3 的表现&lt;/p&gt;
&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;作者在本文中证明了基于 MoE 架构的大语言模型可以达到与 dense 模型相同的性能，且计算更加高效。作者构建了 GLaM 大语言模型系列，包括 1.9B-A0.1B, 105B-A1.9B, 143B-A9.8B 以及 1.2T-A96.6B 等模型，尽管只激活了不到 $8\%$ 的参数，模型的 zero-shot, one-shot 和 few-shot 表现均超过了 GPT-3.&lt;/p&gt;
&lt;p&gt;作者认为，在相同的算力下，MoE 模型比 dense 模型的表现更好，MoE 模型是一个非常具有前景的方向。&lt;/p&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;p&gt;训练数据集包括 1.6T token, 具体分布如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dataset&lt;/th&gt;
&lt;th&gt;Tokens (B)&lt;/th&gt;
&lt;th&gt;Weight in mixture&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Filtered Webpages&lt;/td&gt;
&lt;td&gt;143&lt;/td&gt;
&lt;td&gt;0.42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wikipedia&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0.06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conversations&lt;/td&gt;
&lt;td&gt;174&lt;/td&gt;
&lt;td&gt;0.28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forums&lt;/td&gt;
&lt;td&gt;247&lt;/td&gt;
&lt;td&gt;0.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Books&lt;/td&gt;
&lt;td&gt;390&lt;/td&gt;
&lt;td&gt;0.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;News&lt;/td&gt;
&lt;td&gt;650&lt;/td&gt;
&lt;td&gt;0.02&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;模型架构如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-glam/GLaM-architecture.png"
width="554"
height="681"
loading="lazy"
alt="GLaM model architecture"
class="gallery-image"
data-flex-grow="81"
data-flex-basis="195px"
&gt;&lt;/p&gt;
&lt;p&gt;GLaM 的模型架构与 &lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt; 基本相同，作者将 transformer block 按照两个为一组，一组中一个 block 为 dense FFN, 另一个为 MoE layer, 交替进行。MoE layer 中，总专家个数为 64 个，激活专家个数为 2 个。&lt;/p&gt;
&lt;p&gt;模型配置如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;GLaM Model&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;$n_{\text{params}}$&lt;/th&gt;
&lt;th&gt;$n_{\text{act-params}}$&lt;/th&gt;
&lt;th&gt;$L$&lt;/th&gt;
&lt;th&gt;$M$&lt;/th&gt;
&lt;th&gt;$H$&lt;/th&gt;
&lt;th&gt;$n_{\text{heads}}$&lt;/th&gt;
&lt;th&gt;$d_{\text{head}}$&lt;/th&gt;
&lt;th&gt;$E$&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.1B&lt;/td&gt;
&lt;td&gt;Dense&lt;/td&gt;
&lt;td&gt;130M&lt;/td&gt;
&lt;td&gt;130M&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;3,072&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;$-$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.1B/64E&lt;/td&gt;
&lt;td&gt;MoE&lt;/td&gt;
&lt;td&gt;1.9B&lt;/td&gt;
&lt;td&gt;145M&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;3,072&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.7B&lt;/td&gt;
&lt;td&gt;Dense&lt;/td&gt;
&lt;td&gt;1.7B&lt;/td&gt;
&lt;td&gt;1.700B&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;$-$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.7B/32E&lt;/td&gt;
&lt;td&gt;MoE&lt;/td&gt;
&lt;td&gt;20B&lt;/td&gt;
&lt;td&gt;1.878B&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.7B/64E&lt;/td&gt;
&lt;td&gt;MoE&lt;/td&gt;
&lt;td&gt;27B&lt;/td&gt;
&lt;td&gt;1.879B&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;2,048&lt;/td&gt;
&lt;td&gt;8,192&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.7B/128E&lt;/td&gt;
&lt;td&gt;MoE&lt;/td&gt;
&lt;td&gt;53B&lt;/td&gt;
&lt;td&gt;1.881B&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.7B/256E&lt;/td&gt;
&lt;td&gt;MoE&lt;/td&gt;
&lt;td&gt;105B&lt;/td&gt;
&lt;td&gt;1.886B&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8B&lt;/td&gt;
&lt;td&gt;Dense&lt;/td&gt;
&lt;td&gt;8.7B&lt;/td&gt;
&lt;td&gt;8.7B&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;4,096&lt;/td&gt;
&lt;td&gt;16,384&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;$-$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8B/64E&lt;/td&gt;
&lt;td&gt;MoE&lt;/td&gt;
&lt;td&gt;143B&lt;/td&gt;
&lt;td&gt;9.8B&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;4,096&lt;/td&gt;
&lt;td&gt;16,384&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;137B&lt;/td&gt;
&lt;td&gt;Dense&lt;/td&gt;
&lt;td&gt;137B&lt;/td&gt;
&lt;td&gt;137B&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;8,192&lt;/td&gt;
&lt;td&gt;65,536&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;$-$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64B/64E&lt;/td&gt;
&lt;td&gt;MoE&lt;/td&gt;
&lt;td&gt;1.2T&lt;/td&gt;
&lt;td&gt;96.6B&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;8,192&lt;/td&gt;
&lt;td&gt;32,768&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;作者用 GLaM(8B/64E) 来表示一个 8B 参数的 dense model 中每隔一层被转换为 MoE layer&lt;/p&gt;
&lt;h2 id="experiments"&gt;&lt;a href="#experiments" class="header-anchor"&gt;&lt;/a&gt;Experiments
&lt;/h2&gt;&lt;p&gt;训练时，作者设置模型的上下文为 1024 token, batch size 为 1M, 优化器为 Adafactor, 作者还使用了 &lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt; 中提出来的 load balancing loss, tokenizer 为 SentencePiece&lt;/p&gt;
&lt;p&gt;GLaM 与 GPT-3 的对比如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;GPT-3&lt;/th&gt;
&lt;th&gt;GLAM&lt;/th&gt;
&lt;th&gt;relative&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;cost&lt;/td&gt;
&lt;td&gt;FLOPs / token (G)&lt;/td&gt;
&lt;td&gt;350&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;180&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-48.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Train energy (MWh)&lt;/td&gt;
&lt;td&gt;1287&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;456&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-64.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;accuracy on average&lt;/td&gt;
&lt;td&gt;Zero-shot&lt;/td&gt;
&lt;td&gt;56.9&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;62.7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;+10.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;One-shot&lt;/td&gt;
&lt;td&gt;61.6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;65.5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;+6.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Few-shot&lt;/td&gt;
&lt;td&gt;65.2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;68.1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;+4.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;实验结果显示，GLaM 的训练效率更高，且表现更好&lt;/p&gt;
&lt;p&gt;作者还探究了提升 expert 个数对最终表现的影响，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-glam/GLaM-performance-vs-num-experts.png"
width="686"
height="354"
loading="lazy"
alt="Performance vs number of experts"
class="gallery-image"
data-flex-grow="193"
data-flex-basis="465px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，随着专家个数提升，模型的表现逐渐增强，但是当专家个数超过 64 个之后，模型的表现反而有所下降。&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者在本文中提出了 GLaM 大语言模型系列，验证了 MoE 模型的有效性和效率，结果发现，MoE 模型可以在相同的算力下达到更好的表现，并且学习效率更高。&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/abs/2112.06905" target="_blank" rel="noopener"
&gt;arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on MiniMax-01</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/</link><pubDate>Tue, 06 Jan 2026 17:38:01 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/</guid><description>&lt;p&gt;MiniMax-01 是一个基于 hybrid attention 架构的大模型系列，包含 MiniMax-Text-01 和 MiniMax-VL-01 两个模型，其中 MiniMax-Text-01 推理时支持 4M 的上下文长度，MiniMax-VL-01 支持 512B 的上下文长度&lt;/p&gt;
&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;现有大部分模型的上下文长度为 32K-256K, 但实际上我们对于长上下文的需求已经超过了这个范围。已有的模型主要基于 self-attention, 这是一个平方复杂度的算法。&lt;/p&gt;
&lt;p&gt;为了解决 self-attention 的问题，相关工作如 sparse attention, linear attention, state space models 等都提出了对应的解决办法。但是已有的这些解决方法的问题就是表现不是很强劲。&lt;/p&gt;
&lt;p&gt;因此，作者在本文中就提出了一个基于 hybrid attention 架构的大语言模型系列 MiniMax-01. 作者主要从架构，数据和 infra 三个方面进行了改进。&lt;/p&gt;
&lt;p&gt;在架构上，作者使用了基于 Lightning Attention 的混合架构。作者还基于实际部署来决定模型的参数。为了最大化模型的表现，作者使用了 MoE 架构。&lt;/p&gt;
&lt;p&gt;已有的 infra 主要是针对基于 softmax 的 attention 进行优化的，MiniMax-01 包含 softmax attention, linear attention 和 MoE, 架构比较复杂，因此作者实现了 expert parallel 和 expert tensor parallel 来提高整体的计算效率和 GPU 之间的通信效率。作者还实现了 varlen ring attention 来减少计算冗余。最终，作者发现模型在 NVIDIA-H20 上的 MFU 超过了 75%.&lt;/p&gt;
&lt;p&gt;基于前面提到的架构设计，作者训练得到了 MiniMax-Text-01, 模型总参数为 456B, 激活参数为 45.9B, 专家个数为 32 个，激活专家个数为 2 个。 作者首先构建了高质量的数据集，然后构建了一个三阶段的训练 pipeline。&lt;/p&gt;
&lt;p&gt;基于 MiniMax-Text-01, 作者扩展得到了 MiniMax-VL-01,训练使用了&lt;strong&gt;512B&lt;/strong&gt; token&lt;/p&gt;
&lt;p&gt;作者总结本文的贡献如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;作者构建了一个领先的大模型系列，支持超过 4M 上下文&lt;/li&gt;
&lt;li&gt;作者构建了第一个大规模的基于 linear attention 的大语言模型系列&lt;/li&gt;
&lt;li&gt;作者详细介绍了使用的数据，模型和训练策略&lt;/li&gt;
&lt;li&gt;作者开源了模型&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h2&gt;&lt;p&gt;模型架构如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/minimax_text_01_architecture.png"
width="737"
height="908"
loading="lazy"
alt="minimax_text_01_architecture"
class="gallery-image"
data-flex-grow="81"
data-flex-basis="194px"
&gt;&lt;/p&gt;
&lt;p&gt;相比于原始的 transformer, MiniMax-01 做出了以下改进：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;将 attention block 按照 8 个 block 为一组，每组里只有最后 1 个 block 使用 softmax attention, 其余 7 个 block 使用 lightning attention&lt;/li&gt;
&lt;li&gt;使用 MoE 替换 FFN, MoE 总专家个数为 32 个，激活专家个数为 2 个&lt;/li&gt;
&lt;li&gt;softmax attention 使用了 &lt;a class="link" href="https://maosong.website/p/notes-on-gqa/" target="_blank" rel="noopener"
&gt;GQA&lt;/a&gt;, 来提高内存加载效率, group size 为 8&lt;/li&gt;
&lt;li&gt;使用了 RoPE 作为 position embedding&lt;/li&gt;
&lt;li&gt;使用了 RMSNorm 替换了 LayerNorm&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;FFN: MoE (32 个专家，激活 2 个专家)&lt;/p&gt;
&lt;p&gt;transformer: 8 个 block 为一组，一组里前 7 个使用 Lightning attention，第 8 个使用 softmax attention，80 layers&lt;/p&gt;
&lt;p&gt;Attention ： GQA，group size=8，64 heads，&lt;/p&gt;
&lt;h3 id="moe"&gt;&lt;a href="#moe" class="header-anchor"&gt;&lt;/a&gt;MoE
&lt;/h3&gt;&lt;p&gt;在训练基于 MoE 的 LLM 时，有两种策略，分别是 token-drop 和 dropless, 前者保证每个专家处理的 token 个数差不多，可以提高效率，缺点是某些 token 不会被任何专家处理，某些 token 会被多个专家处理；后者是保证每个 token 都会被处理。&lt;/p&gt;
&lt;p&gt;在本文中，作者采取了 token-drop 的方式，作者为每个专家设置一个 capacity limit，超过这个 limit 之后该专家就不再处理新的 token.&lt;/p&gt;
&lt;p&gt;为了评估 MoE 模型的有效性，作者对比了 MoE 和 dense 模型的表现，结果如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-dense-vs-MoE.png"
width="1402"
height="480"
loading="lazy"
alt="Performance of MoE v.s. Dense"
class="gallery-image"
data-flex-grow="292"
data-flex-basis="701px"
&gt;&lt;/p&gt;
&lt;p&gt;结果发现，相同的算力下，MoE 模型比 dense 模型好。&lt;/p&gt;
&lt;p&gt;但是，当 scaling up 到更大的模型是，作者发现训练产生了 routing collapse 的情况，这是因为 routing 的分布过于集中。为了解决这个问题，作者使用了 auxiliary loss 以及 global router 两个方法&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Auxiliary loss&lt;/strong&gt;
作者首先构建了 auxiliary loss 来提高负载均衡, 也就是&lt;/p&gt;
$$
\mathcal{L}_{B} = K\sum_{i=1}^K f_i P_i
$$&lt;p&gt;这里 $f_i$ 是分配给第 $i$ 个专家的 token 比例， $P_i$ 是第 $i$ 个专家的平均 routing 概率。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Global router&lt;/strong&gt;
作者还基于 &lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt; 构建了一个 global routing 策略，由于 GPU memory 限制，对于每一个 micro batch size, token 分布不仅在一个 EP group 内分布不平衡，在不同 EP group 之间可能也不平衡。因此，作者实现了一个 global token dispatching 策略。具体来说，在 token 分发到不同的 EP group 之前，作者使用 &lt;code&gt;allgather&lt;/code&gt; 来计算每个专家需要处理的 token. 这样就可以基于全局信息智能分配 token, 避免某些专家过载。&lt;/p&gt;
&lt;h3 id="linear-attention"&gt;&lt;a href="#linear-attention" class="header-anchor"&gt;&lt;/a&gt;Linear Attention
&lt;/h3&gt;&lt;p&gt;本文中使用的 linear attention 由 Lightning Attention 提出，其表达式为&lt;/p&gt;
$$
O = \mathrm{Norm}((QK^T)V)
$$&lt;p&gt;这里 $Q,K,V\in\mathbb{R}^{n\times n}$ 分别是 query, key 和 value, $n$ 和 $d$ 分别是序列长度和 hidden size.上式可以改变运算顺序，得到&lt;/p&gt;
$$
O = \mathrm{Norm}(Q(K^TV))
$$&lt;p&gt;这样，attention 的计算复杂毒就从 $O(n^2d)$ 变成了 $O(nd^2)$,&lt;/p&gt;
&lt;h4 id="lightning-attention"&gt;&lt;a href="#lightning-attention" class="header-anchor"&gt;&lt;/a&gt;Lightning Attention
&lt;/h4&gt;&lt;p&gt;当我们不考虑 attention mask 的时候，我们很轻松可以降低 attention 计算的复杂度。但实际上，LLM 会使用 causal mask, 也就是每个 token 智能看到其前面 token 的信息，这样我们的 attention 计算实际上是&lt;/p&gt;
$$
O = \mathrm{Norm}[QK^T\odot M]V)
$$&lt;p&gt;这里 $M_{ij}=\mathbb{1}(i\geq j)$ 是 attention mask.&lt;/p&gt;
&lt;p&gt;见 Lightning Attention&lt;/p&gt;
&lt;h4 id="effectiveness-of-lightning-attention"&gt;&lt;a href="#effectiveness-of-lightning-attention" class="header-anchor"&gt;&lt;/a&gt;Effectiveness of Lightning Attention
&lt;/h4&gt;&lt;p&gt;作者接下来分析了一下 softmax attention, lightning attention 和 hybrid attention 之间的效率&lt;/p&gt;
&lt;p&gt;首先，作者计算了一下三种架构的参数量以及 FLOPS. 作者分别使用 $l, d, h, b, n$ 来代表 Layer 数，hidden dimension, number of attention heads, batch size 和 sequence length.&lt;/p&gt;
&lt;p&gt;最终计算结果如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Architecture&lt;/th&gt;
&lt;th&gt;Parameter count&lt;/th&gt;
&lt;th&gt;FLOPs count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Softmax&lt;/td&gt;
&lt;td&gt;$12ld^2$&lt;/td&gt;
&lt;td&gt;$72bnld^2 (1 + \frac{n}{6d} + \frac{5}{18d} )$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lightning&lt;/td&gt;
&lt;td&gt;$12ld^2+2ld^2/h$&lt;/td&gt;
&lt;td&gt;$72bnld^2(1+\frac{1}{2h}+\frac{5}{18d})$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hybrid&lt;/td&gt;
&lt;td&gt;$12ld^2+7ld^2/4h$&lt;/td&gt;
&lt;td&gt;$72bnld^2(1+\frac{n}{48d}+\frac{7}{16h}+\frac{5}{18d})$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;[!todo] TODO
compute these results&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Scaling law&lt;/strong&gt;
作者接下来分别针对三个架构设计了 70M, 160M, 410M, 1B, 3B, 7B 系列模型，模型使用 300B token 进行训练，上下文长度为 8192, 对于每种架构，作者将 batch size 设置为 4M tokens. 与 &lt;a class="link" href="https://maosong.website/p/chinchilla-scaling-law/" target="_blank" rel="noopener"
&gt;Chinchilla scaling law&lt;/a&gt; 类似， 作者探究了以下模型的 scaling law, 结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-scaling-law.png"
width="1403"
height="584"
loading="lazy"
alt="Summary of Scaling law"
class="gallery-image"
data-flex-grow="240"
data-flex-basis="576px"
&gt;&lt;/p&gt;
&lt;p&gt;从实验结果可以看到，在相同的算力下，lighting attention 倾向于使用更多的参数和 token, 但是其表现相比于 softmax attention 更好。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;
作者还对比了一下三种 attention 在 public benchmark 上的表现，结果如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-performance-attention.png"
width="1394"
height="765"
loading="lazy"
alt="Performance of different attention architectures"
class="gallery-image"
data-flex-grow="182"
data-flex-basis="437px"
&gt;&lt;/p&gt;
&lt;p&gt;是检验结果发现，lightning attention 和 softmax attention 除了在 retrieval 任务（Needle in a Haystack）上之外，表现都差不多。与之相对的是，hybrid attention 弥补了这一问题，大幅度提升了模型在 retrieval 任务上的表现&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!tip] Observation
Lightning attention 与 softmax attention 的效果差不多，但是其在长上下文任务上的表现比较差。Hybrid attention 可以解决这个问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;作者还评估了一下三种 attention 的速度，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/Minimax-01-attention-speed-comparison.png"
width="692"
height="373"
loading="lazy"
alt="Training speed of various attention mechanisms"
class="gallery-image"
data-flex-grow="185"
data-flex-basis="445px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，softmax attention 随序列长度上升其速度急剧下降，Lightning attention 的速度基本没有太大变化。而 Hybrid attention 的速度介于两者之间。&lt;/p&gt;
&lt;p&gt;作者进一步对比了以下两种不同的变体：hybrid-cosformer2 以及 hybrid-hgrn2.这两个模型替换的逻辑与 minimax-01 的结果一致，都是 8 个 block 为一组，每组中前面 7 个 block 将 softmax attention 更换为对应的模块，最后一层不做改动。三种 hybrid attention 机制的表现如下表所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/Minimax-01-hybrid-attention-comparison.png"
width="1377"
height="190"
loading="lazy"
alt="Performance of various hybrid-linear models"
class="gallery-image"
data-flex-grow="724"
data-flex-basis="1739px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，hybrid-lightning 的表现最好。&lt;/p&gt;
&lt;p&gt;作者最后对比了以下 hybrid-lightning 和 hybrid-window, hybrid window 在每个 group 的前 7 个 block 使用了 window attention, window size 为别为 256, 512, 1024.实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-hybrid-window-comparison.png"
width="1392"
height="369"
loading="lazy"
alt="Comparison between hybrid lighting and hybrid window"
class="gallery-image"
data-flex-grow="377"
data-flex-basis="905px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Discussion&lt;/strong&gt;
作者最后总结认为，虽然 linear attention 的效率很高，但是它们在 retrieval 相关的任务表现很差，而 retrieval 对于 In-context learning 来说是至关重要的。因此，作者采取了 hybrid 架构，来兼顾模型的效率以及表现。&lt;/p&gt;
&lt;p&gt;作者给出了一个解释。&lt;/p&gt;
&lt;h3 id="ablation-study"&gt;&lt;a href="#ablation-study" class="header-anchor"&gt;&lt;/a&gt;Ablation Study
&lt;/h3&gt;&lt;p&gt;作者主要进行了两个消融实验：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hybrid-lightning 与 softmax attention 的对比：作者训练了一个总参数 28B, 激活参数 5B 的 MoE 模型，然后作者使用 MiniMax-01 的方式替换每个 group 的 softmax attention, 并使用了 1T 的 token 进行训练&lt;/li&gt;
&lt;li&gt;pre-layer normalization 与 Post-layer normalization 的对比： 现有的 LLaMA 和 Qwen 等系列模型采用的都是 PreNorm 的方式。&lt;strong&gt;PreNorm 可以让 gradient 通过 residual connection 传播更加直接，但是这也减少了模型的有效深度&lt;/strong&gt;。反之，PostNorm 则可以保留模型的有效深度，但是其问题是会导致梯度消失或爆炸。作者构建了一个总参数为 60B, 激活参数为 9.3B 的 MoE 模型，包含 48 个 block, 模型训练使用 500B token. 模型有两个变体，一个使用 PreNorm, 另一个使用 PostNorm, 对于 PostNorm, 作者使用的是 DeepNorm.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最终表现如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-module-ablation.png"
width="1392"
height="238"
loading="lazy"
alt="Module ablations"
class="gallery-image"
data-flex-grow="584"
data-flex-basis="1403px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，hybrid lightning 的表现与 softmax 的表现相当，甚至超过了 softmax 的表现。&lt;/p&gt;
&lt;p&gt;另一方面，PostNorm 的表现也超过了 PreNorm 的表现。&lt;/p&gt;
&lt;h3 id="model-spec"&gt;&lt;a href="#model-spec" class="header-anchor"&gt;&lt;/a&gt;Model Spec
&lt;/h3&gt;&lt;p&gt;基于已有的模型设计，作者探究了如何决定模型的参数。作者的目标&lt;strong&gt;在 performance 和 inference efficiency 之间达到一个平衡&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;作者将模型的参数限制在 500B 以下，要求能够在 $8\times 80G$ 的服务器上和 8-bit 的量化下面，支持 1M 的上下文长度。建模的问题如下：&lt;/p&gt;
$$
\min_{P_{all}, P_{act}}\mathcal{L}(P_{all}, P_{act}, T), \quad \mathrm{s.t.}\ C_{compute}(P_{all}, P_{act}, T)&lt;C \text{ and } P_{all} &lt; 500B
$$&lt;p&gt;其中 $\mathcal{L}$, $P_{all}$, $P_{act}$, $T$, $C_{compute}$, $C$ 分别代表损失，总参数，激活参数，训练的 token 数，算力消耗 y 以及算力的 budget.&lt;/p&gt;
&lt;p&gt;作者首先确定了几个关键的因素：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;softmax 和 lightning 的混合比例&lt;/li&gt;
&lt;li&gt;depth-to-width 的比例&lt;/li&gt;
&lt;li&gt;linear attention memory size 和 hidden size 的比例&lt;/li&gt;
&lt;li&gt;FFN 的 hidden size 大小&lt;/li&gt;
&lt;li&gt;RoPE 的 base frequency&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;作者通过实验发现，hybrid 架构需要更多的 layer 才能带来更好地表现。对于 layer 比较少的模型，其需要更多的 softmax attention layers 来达到相似的表现。&lt;/p&gt;
&lt;p&gt;作者还发现，提升 linear attention memory size 可以有效提高模型的表现。并且 RoPE 的 dimension 最好设置为 softmax attention dimension 的一半。&lt;/p&gt;
&lt;p&gt;基于这些发现，作者构建了 scaling law 来决定最优模型配置。作者训练了不同大小的模型，然后拟合 scaling law 的曲线，最后，作者将模型的总参数确定为 456B, 激活参数确定为 45.9B.&lt;/p&gt;
&lt;h2 id="infra"&gt;&lt;a href="#infra" class="header-anchor"&gt;&lt;/a&gt;Infra
&lt;/h2&gt;&lt;p&gt;本节介绍了一下 MiniMax-01 的 infra, 作者主要解决了以下几个关键问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;减少训练时 MoE 中的 all-to-all 通信开销，如何在内存使用，计算效率和 all-to-all 通信开销之间达到一个平衡&lt;/li&gt;
&lt;li&gt;在处理长上下文时，不同 GPU 之间的信息需要共享，这会导致额外的通信开销。因此，如何减少长上下文情形下的通信开销也是一个挑战&lt;/li&gt;
&lt;li&gt;如何提高 lightning attention 在 inference 阶段的效率。当前只在训练阶段做了优化，但是推理阶段也需要提高模型的效率&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="moe-optimization"&gt;&lt;a href="#moe-optimization" class="header-anchor"&gt;&lt;/a&gt;MoE Optimization
&lt;/h3&gt;&lt;p&gt;优化 MoE 架构的主要目的是&lt;strong&gt;最小化通信开销&lt;/strong&gt;，特别是 all-to-all 的通信开销。为了解决这个问题，作者构建了一个 token-grouping-based overlap scheme, 来让通信和计算尽可能并行执行，也就是在计算的同时进行通信。为了保证通信的正确性，每个 ProcessGroup 之间的通信操作必须串行执行，这就导致了不同 group 之间的通信无法 overlap, 也就造成了 idle time 的产生，示意图如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-EP-overlap.png"
width="702"
height="451"
loading="lazy"
alt="Expert parallel overlap illustration"
class="gallery-image"
data-flex-grow="155"
data-flex-basis="373px"
&gt;&lt;/p&gt;
&lt;p&gt;但是，在 MiniMax-01 上应用这种方法时，作者发现如果使用 TP 来切分 expert 的参数的话，会导致计算密度过低。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!tip] Explanation
针对 MoE 模块使用 TP 导致计算密度过低的原因是 MoE 模块是稀疏的，计算式大量 GPU 都处于空闲状态，因此计算密度低。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如果不使用 TP 的话，就必须使用更大的 PP 配置，也就是使用更多的 GPU, 但是使用 PP 并不会减少 activation 的内存占用，这在长上下文训练时，会增加内存消耗，而且不会提升整体的训练速度。因此，我们需要一种新的策略，使其能够：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;平衡内存使用与计算密度&lt;/li&gt;
&lt;li&gt;优化特定模型和任务的训练过程&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;基于这个目标，在本文中作者提出了 ETP, 也就是 Expert Tensor Parallel, 用于管理 expert 的参数划分。同时，作者还提出了 EDP, 也就是 Expert Data Parallel, 来将每个 expert 的数据并行封装在一起。&lt;code&gt;world_size&lt;/code&gt; 满足两个条件：&lt;/p&gt;
$$
\texttt{world\_size} = \texttt{size}_{PP}\times \texttt{size}_{DP}\times \texttt{size}_{CP}\times \texttt{size}_{TP}
$$&lt;p&gt;以及&lt;/p&gt;
$$
\texttt{world\_size} = \texttt{size}_{PP}\times \texttt{size}_{EDP}\times \texttt{size}_{ETP}\times \texttt{size}_{EP}
$$&lt;p&gt;首先，作者构建了 EP-ETP 策略，用于平衡内存使用以及计算密度，这个过程包括了四个步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;all-to-all dispatch: （EP）将每个 token 分发到 expert 所在 GPU 上&lt;/li&gt;
&lt;li&gt;allgather: （TP）将输入的 token 进行切分，分发给对应的 TP GPU 上&lt;/li&gt;
&lt;li&gt;Expert:（TP）执行 expert 的计算过程&lt;/li&gt;
&lt;li&gt;ReduceScatter: （TP）将 TP 输出的结果进行汇总然后再分发给不同的 TP&lt;/li&gt;
&lt;li&gt;all-to-all combine: 将不同 expert 的输出结果进行汇总，传递给下一层&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但是，由于同一个 ProcessGroup 内部的通信必须串行执行，如果计算效率比较高的话，就会产生 bubble, 作者的改进方法是提高计算量，让计算消耗的时间与通信消耗的时间大致相当。&lt;/p&gt;
&lt;p&gt;作者还尝试降低 ProcessGroup 的 size, 这样可以进一步提高计算和通信之间的 overlap, 但是问题是降低 group size 之后，group 的数量会增加，而这会导致 scheduling 以及让通信变为 CPU-bound. 作者认为这需要根据具体场景来进行设置。最终，通过优化，作者将 MoE 模块的通信开销降低了 50%.&lt;/p&gt;
&lt;p&gt;改进的示意图如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-EP-ETP-overlap.png"
width="1136"
height="660"
loading="lazy"
alt="EP-ETP overlap"
class="gallery-image"
data-flex-grow="172"
data-flex-basis="413px"
&gt;&lt;/p&gt;
&lt;h3 id="long-context-optimization"&gt;&lt;a href="#long-context-optimization" class="header-anchor"&gt;&lt;/a&gt;Long Context Optimization
&lt;/h3&gt;&lt;p&gt;为了处理不同长度的 sequence, 作者使用了 sequence packing 的技巧。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Varlen Ring Attention&lt;/strong&gt;
当前主要是使用 ring attention 来划分数据，但是 ring-attention 与 sequence packing 是冲突的。已有工作如 &lt;a class="link" href="https://maosong.website/p/chinchilla-scaling-law/" target="_blank" rel="noopener"
&gt;flash attention&lt;/a&gt; 支持 varlen data packing, 但是不支持 ring attention; 而 TransformerEngine 实现了 ring attention, 但不支持真正的 varlen. 因此作者的目的就是解决这个问题。&lt;/p&gt;
&lt;p&gt;TransformerEngine 的问题在于每个 sequence 必须是 $2\times \texttt{size}_{CP}$ 的整数倍，当 CP 很大且样本长度分布未知的时候，padding 会很严重，导致算力和内存消耗严重。&lt;/p&gt;
&lt;p&gt;作者的解决方法为使用 varlen ring attention. 具体做法就是在每一步通信中，都基于 attention mask 的 offset 来处理不同的 sequence. 示意图如下所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-varlen-ring-attention.png"
width="969"
height="374"
loading="lazy"
alt="Varlen Ring Attention"
class="gallery-image"
data-flex-grow="259"
data-flex-basis="621px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LASP+&lt;/strong&gt;
对于 lightning attention, 之前的做法是使用 LASP 算法来实现 linear attention. 但是 LASP 的问题在于其是一个串行依赖，这样导致训练效率变低。&lt;/p&gt;
&lt;p&gt;为了解决这个问题，作者提出了 LASP+, 包括以下几个步骤&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Local Prefix Sum Calculation: 每个 GPU 先计算自己局部 prefix sum, 作者将其记为 KVL&lt;/li&gt;
&lt;li&gt;Global Synchronization via AllGather: 然后，作者通过 AllGather 将自己的 KVL 发送给其他 GPU. 这样就可以一次完成所有通信&lt;/li&gt;
&lt;li&gt;Prefix Sum Computation: 最后，每个 GPU 利用所有 KVL, 分别计算自己需要的 prefix sum.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;通过这样一个优化，我们可以将 LASP 的延迟降低 $N_{pcn}$ 倍，这里 $N_{pcn}$ 是并行计算节点的个数。&lt;/p&gt;
&lt;p&gt;作者进一步结合了前面的 Varlen ring attention, 主要包括 padding to block size 和 sequential concatenation 两个步骤。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!tip] Remark
LISP+ 说明了现在大模型分布式训练的一个重要趋势，也就是用通信换并行。特别是 GPU 通信带宽特别高的情况。因此，算法设计不仅要考虑理论复杂度还要考虑实际中硬件并行的利用率。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="lightning-attention-inference-optimization"&gt;&lt;a href="#lightning-attention-inference-optimization" class="header-anchor"&gt;&lt;/a&gt;Lightning Attention Inference Optimization
&lt;/h3&gt;&lt;p&gt;已有的 lightning attention 并没有考虑实际的部署需求。作者提出了四个策略来优化 lightning attention 的 inference efficiency:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Batched Kernel Fusion&lt;/strong&gt;
作者首先对 memory-bound kernels 进行融合。在 prefill phase, 作者将多步操作，比如 Q, K, V projection, padding, partitioning 等放在一个 kernel 里，来减少内存 I/O. 在 decoding phase, 作者将 KV 的计算也放在一个 kernel 里，计算完之后就直接写入 KV cache 而不经过缓冲区&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PD separation&lt;/strong&gt;
inference 的 decoding 阶段模型每次只生成 1 个 token, 此时任务是 memory-bound, 也就是瓶颈在显存读写而不是算力，我们只需要很少的 GPU SMs 就可以跑起来。因此，作者设计了两个不同的 CUDA streams 来分别处理 length 为 1 和 length&amp;gt;1 的情况，这样就可以有效提高整体的计算效率和平衡 GPU 的利用率。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Multi-level padding&lt;/strong&gt;
已有的 padding 技巧主要是将输入的多个 sequence 都 resize 到固定长度方便处理。但是在推理的时候，使用预设的固定长度 (block size) 会导致无效计算量增加。因此，作者提出了 multi-level padding, 也就是提供不同的 block size, 比如 32, 64, 128. 这样可以有效避免模型因为 padding 而产生的额外计算开销。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;StridedBatchedMatmul Extension&lt;/strong&gt;
这一点主要是针对 Hopper GPU 进行的优化。Hopper 架构相比于 Ampere 架构有一些新的特性，作者基于这些特性来优化整体的性能。&lt;/p&gt;
&lt;p&gt;作者使用 WGMMA 来优化计算，用 TMA 来优化内存访问效率，实现计算与内存访问重叠，减少等待时间。最终，作者的目的是希望基于不同的 GPU 架构来动态调整 Pipeline stages, 以达到更好的性能。&lt;/p&gt;
&lt;p&gt;通过以上这些优化，作者在 H20 上达到了 75% 的 MFU. 作者发现，由于使用了 lightning attention, attention 不分计算从传统的 95% 以上降低到了 12% 左右，不再是算力的瓶颈部分。&lt;/p&gt;
&lt;h2 id="pre-training"&gt;&lt;a href="#pre-training" class="header-anchor"&gt;&lt;/a&gt;Pre-training
&lt;/h2&gt;&lt;p&gt;作者首先介绍了预训练的数据构成，然后作者介绍了如何选取高质量的训练数据，最后，作者介绍了实验的参数。&lt;/p&gt;
&lt;h3 id="data"&gt;&lt;a href="#data" class="header-anchor"&gt;&lt;/a&gt;Data
&lt;/h3&gt;&lt;p&gt;数据来源包括学术文献，数据，互联网语料以及代码。作者构建了如下的数据清洗策略：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;data quality enhancement: 作者使用了 rule-based cleaning 以及去重。然后，作者构建了一个 reward labeler，来从 knowledge depth, practical helpfulness 以及 categorical distribution 三个维度进行打分。&lt;/li&gt;
&lt;li&gt;data formatting optimization. 作者发现，类似 markdown 的格式会降低数据整体的多样性和质量。因此，作者构建了一个嵌套的文档格式，来将对话和 QA 数据组织起来，进而平衡自然数据和结构化数据之间的平衡性。&lt;/li&gt;
&lt;li&gt;data mixture investigation. 作者发现完全去除掉低质量的数据也会影响模型在下游任务上的表现。因此作者平衡了高质量数据和低质量数据&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;作者基于 BPE 算法来构建 tokenizer,最终 tokenizer 的大小为 &lt;strong&gt;200K&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;接下来，作者通过实验来确定最优的数据配置，给定数据集 $\mathcal{D}$, 作者作如下备择假设&lt;/p&gt;
$$
H_1: \mu_{T_{\mathcal{D}}}&gt; \mu_{T_{baseline}}
$$&lt;p&gt;这里 $\mu$ 代表模型表现的加权平均， $T$ 代表模型的表现分布。也就是说，加入新的数据集之后，其平均表现大于 baseline 的表现，则我们认为这个数据集是不被拒绝的。&lt;/p&gt;
&lt;p&gt;作者通过多项选择题来进行评估，评估时作者计算每个选项 completion 的概率，最终的分布计算方式为&lt;/p&gt;
$$
\log \mathrm{acc}_{\mathrm{norm}^2}(x) = \log\mathrm{softmax}_{p'(c\in C_x)}\left\{(p'(c^*))\right\}
$$&lt;p&gt;其中 $p_i'(c)=\frac{p_i(c)}{\mathrm{bytes(c)}}$ 是 normalized 之后的选项概率。作者在训练的时候，通过实验来保证这个 metric 的稳定性，除此之外，作者还加入了一个 discriminator, 也就是 $\Delta_{obvious}/\sigma_{seed}$, 其中 $\Delta_{obvious}$ 表示不同模型表现的差距， $\sigma_{seed}$ 表示不同随机种子的方差。&lt;/p&gt;
&lt;h3 id="training-strategy"&gt;&lt;a href="#training-strategy" class="header-anchor"&gt;&lt;/a&gt;Training Strategy
&lt;/h3&gt;&lt;p&gt;作者使用 Xavier 对模型参数进行初始化，然后使用了 DeepNorm 作为 Normalization 模块。作者使用 AdamW 作为优化器，其中 $\beta_1=0.9$, $\beta_2=0.95$, weight decay 为 $0.1$.&lt;/p&gt;
&lt;p&gt;训练的 sequence length 为 8192，batch size 分别为 16M, 32M (69B tokens), 64M (790B tokens), 128M (4.7T tokens).&lt;/p&gt;
&lt;p&gt;作者基于 training loss 和 critical batch size 来设计 schedule. 作者基于小模型的实验结果来拟合一个 power-law 关系，结果如下图所示：&lt;/p&gt;
&lt;p&gt;基于实验结果，作者&lt;/p&gt;
&lt;h2 id="post-training"&gt;&lt;a href="#post-training" class="header-anchor"&gt;&lt;/a&gt;Post-training
&lt;/h2&gt;&lt;h3 id="prompt-collection"&gt;&lt;a href="#prompt-collection" class="header-anchor"&gt;&lt;/a&gt;Prompt Collection
&lt;/h3&gt;&lt;p&gt;作者从多个 domain 收集到了数百万 diverse 和高质量的 query,作者基于任务类型，domain 和难度对 prompt 进行分类。接下来作者对 prompt 进行去重以及平衡难度问题。prompt 覆盖 long context, math, reasoning 等 domain&lt;/p&gt;
&lt;h3 id="reward-model"&gt;&lt;a href="#reward-model" class="header-anchor"&gt;&lt;/a&gt;Reward Model
&lt;/h3&gt;&lt;p&gt;作者基于以下几个原则来设计 reward:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Correctness: 对于 math 任务，作者使用 MiniMax-Text-01 来生成 binary reward; 对于 code 任务，作者使用沙盒环境运行代码，根据通过率来给出奖励&lt;/li&gt;
&lt;li&gt;Truthfulness: 作者使用先进的语言模型来评估 response 的 factual accuracy&lt;/li&gt;
&lt;li&gt;Helpfulness: 作者实现了基于规则的验证系统，来评估回答的 coherence, depth, contextual relevance 和 stylistic appropriateness.&lt;/li&gt;
&lt;li&gt;Harmlessness: 作者基于 Constitutional AI principles, 构建了一系列协议来保证模型输出的安全性。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="sft"&gt;&lt;a href="#sft" class="header-anchor"&gt;&lt;/a&gt;SFT
&lt;/h3&gt;&lt;p&gt;作者通过使用多个 expert model 来生成多样化的回答。然后，作者通过 n-gram 以及 semantic similarity 来提高数据的多样性和质量。&lt;/p&gt;
&lt;h3 id="rl"&gt;&lt;a href="#rl" class="header-anchor"&gt;&lt;/a&gt;RL
&lt;/h3&gt;&lt;p&gt;RL 训练包括 offline stage 以及 online stage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Offline RL&lt;/strong&gt;
在 offline stage, 作者使用 DPO 来进行训练。数据构造过程也比较简单，使用模型来进行采样，评估，选取最好和最差的作为正样本和负样本。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Online RL&lt;/strong&gt;
这个阶段使用 GRPO 进行训练，作者发现使用 SFT 阶段的 prompt 会导致训练饱和，因此，作者并没有采用 SFT 阶段的 prompts&lt;/p&gt;
&lt;p&gt;作者主要针对 GRPO 进行了一下改进：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Important Sampling Weight Clipping. 作者发现，PPO 以及 GRPO 只使用了单侧的 clipping, 这会导致训练的不稳定性。因此作者构建了额外的 clipping 策略。&lt;/li&gt;
&lt;li&gt;KL divergence optimization. 作者发现 KL divergence 也会导致训练不稳定，因此作者对 KL divergence 进行了 reformulate 来稳定梯度&lt;/li&gt;
&lt;li&gt;Balanced Advantage Estimation. 作者确保正样本和负样本的对 reward 的贡献差不多，来提高训练的稳定性。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="safety-alignment"&gt;&lt;a href="#safety-alignment" class="header-anchor"&gt;&lt;/a&gt;Safety Alignment
&lt;/h3&gt;&lt;p&gt;作者还加入了一个 safety alignment 阶段，用于提升模型的安全性。&lt;/p&gt;
&lt;p&gt;数据包括三类：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;safety-category specific prompts.&lt;/li&gt;
&lt;li&gt;Real-world user data collection.&lt;/li&gt;
&lt;li&gt;prompt augmentation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;接下来，作者使用一个无害的 reward model 来对模型的输出进行打分。&lt;/p&gt;
&lt;h3 id="training-recipe"&gt;&lt;a href="#training-recipe" class="header-anchor"&gt;&lt;/a&gt;Training Recipe
&lt;/h3&gt;&lt;p&gt;最终，post-training 一共包括 5 个 stage，训练时，作者将 RoPE 的 base frequency 保持在 10M.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Initial short-context training: 模型的上下文长为 8192，然后进行 SFT&lt;/li&gt;
&lt;li&gt;Extended context training: 模型的上下文长度为 1,032,192. 训练数据包括 50% 长文本和 50% 短文本&lt;/li&gt;
&lt;li&gt;Short-context Preference Optimization: 模型的上下文长度为 8192, 然后进行 DPO 的训练&lt;/li&gt;
&lt;li&gt;Long-context Preference Optimization: 模型的上下文长度为 1,032,192, 然后进行 DPO 的训练&lt;/li&gt;
&lt;li&gt;Online Reinforcement Learning: RL 的训练，与上文一致。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;训练的配置如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Stage I&lt;/th&gt;
&lt;th&gt;Stage II&lt;/th&gt;
&lt;th&gt;Stage III&lt;/th&gt;
&lt;th&gt;Stage IV&lt;/th&gt;
&lt;th&gt;Stage V&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sequence Length&lt;/td&gt;
&lt;td&gt;8192&lt;/td&gt;
&lt;td&gt;1032192&lt;/td&gt;
&lt;td&gt;8192&lt;/td&gt;
&lt;td&gt;1032192&lt;/td&gt;
&lt;td&gt;8192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Epoch&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Batch Size&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max LR&lt;/td&gt;
&lt;td&gt;1e-5&lt;/td&gt;
&lt;td&gt;3e-6&lt;/td&gt;
&lt;td&gt;5e-7&lt;/td&gt;
&lt;td&gt;5e-7&lt;/td&gt;
&lt;td&gt;1e-6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Min LR&lt;/td&gt;
&lt;td&gt;1e-6&lt;/td&gt;
&lt;td&gt;3e-6&lt;/td&gt;
&lt;td&gt;5e-8&lt;/td&gt;
&lt;td&gt;5e-7&lt;/td&gt;
&lt;td&gt;1e-7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LR Decay&lt;/td&gt;
&lt;td&gt;Cosine&lt;/td&gt;
&lt;td&gt;Constant&lt;/td&gt;
&lt;td&gt;Cosine&lt;/td&gt;
&lt;td&gt;Constant&lt;/td&gt;
&lt;td&gt;Cosine&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="llm-evaluation"&gt;&lt;a href="#llm-evaluation" class="header-anchor"&gt;&lt;/a&gt;LLM Evaluation
&lt;/h2&gt;&lt;p&gt;作者对比了 GPT-4o, Claude-3.5-Sonnet, Gemini-1.5-Pro, Qwen2.5-72B, DeepSeek-V3 以及 LLaMA3.1-405B, 实验结果如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-text-performance.png"
width="1393"
height="953"
loading="lazy"
alt="Performance of MiniMax-Text-01"
class="gallery-image"
data-flex-grow="146"
data-flex-basis="350px"
&gt;&lt;/p&gt;
&lt;p&gt;作者还评估了以下 MiniMax-Text-01 在长上下文情境下表现，我们这里列出 Ruler 上的结果，如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-text-Ruler-performance.png"
width="1334"
height="250"
loading="lazy"
alt="MiniMax-Text-01 performance on Ruler benchmark"
class="gallery-image"
data-flex-grow="533"
data-flex-basis="1280px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到在 1M 上下文时，模型的表现超过了 Gemini-1.5-Pro 的表现。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="vlm-architecture"&gt;&lt;a href="#vlm-architecture" class="header-anchor"&gt;&lt;/a&gt;VLM Architecture
&lt;/h2&gt;&lt;p&gt;作者基于 MiniMax-Text-01 开发了 MiniMax-VL-01, 来扩展模型的多模态理解能力。MiniMax-VL-01 是一个标准的 ViT-MLP-LLM 架构，其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ViT: 从零开始训练的 ViT, 参数为 303M&lt;/li&gt;
&lt;li&gt;MLP: 2 层的 MLP, 激活函数为 GeLU&lt;/li&gt;
&lt;li&gt;LLM: MiniMax-Text-01&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;作者实现了动态分辨率策略，用于处理不同大小的图片。每张图片都被切分为 $336\times 336$ 的大小， 然后作者还加入了一个 thumbnail image 用于提取全局信息。&lt;/p&gt;
&lt;h2 id="data-1"&gt;&lt;a href="#data-1" class="header-anchor"&gt;&lt;/a&gt;Data
&lt;/h2&gt;&lt;p&gt;为了训练 vision encoder, 作者使用了 &lt;strong&gt;694M&lt;/strong&gt; 的 Image-caption pair 数据，为了提高数据质量，作者对其中 180M 的数据进行的 caption 的改写，训练的时候原始数据和重写数据的采样概率都是 $50\%$.&lt;/p&gt;
&lt;p&gt;作者还从公开数据收集到了 100M 的图片，每个图片都有详细的描述，这些描述都由一个 caption model 生成，然后再由人类进行修正。每条描述大概包含 300 个 text token&lt;/p&gt;
&lt;p&gt;作者还构建了一个高质量的 instruction dataset, 这个数据集是通过预定义一系列任务，然后对于每个任务分别生成对应的 QA pair 得到的。在训练的时候，作者平衡了不同任务的采样概率。&lt;/p&gt;
&lt;p&gt;最后，作者对收集收集数据的类别分布进行了可视化，结果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-VL-data-distribution.png"
width="692"
height="707"
loading="lazy"
alt="Visualization of top rags of sampled instruction data"
class="gallery-image"
data-flex-grow="97"
data-flex-basis="234px"
&gt;&lt;/p&gt;
&lt;h2 id="training"&gt;&lt;a href="#training" class="header-anchor"&gt;&lt;/a&gt;Training
&lt;/h2&gt;&lt;p&gt;训练一共包含 5 个 stage, 第一个 stage 用于单独训练 ViT, 后面三个 stage 分别用于对齐和提升模型的多模态能力。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 0: ViT training&lt;/strong&gt;
作者基于 ViT-L/14 来训练 vision encoder, 作者使用了基于对比学习的方法，参考了 CoCa 里的方法。训练过程中，作者首先在 224 的图片精度下训练了 &lt;strong&gt;37B&lt;/strong&gt; 的 image-caption pairs. 接下来，作者在 336 的精度下使用了 &lt;strong&gt;1.2B&lt;/strong&gt; 的 pairs 进行微调。最终，模型在 ImageNet-1K 的表现达到了 80.55%.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 1: Modality alignment&lt;/strong&gt;
这个阶段的目的是对齐视觉模态和文本模态，作者冻结 LLM, 只训练 ViT 和 MLP. 这个阶段一共使用了&lt;strong&gt;80B&lt;/strong&gt; 的 image description data. 作者发现，在这个阶段，提升图片精度对模型表现提升影响不大。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 2: Enhancement of Vision Understanding&lt;/strong&gt;
这个阶段其实就是 instruction tuning, 作者解冻所有参数，然后使用了 &lt;strong&gt;420B&lt;/strong&gt; 多模态 token 以及 &lt;strong&gt;21B&lt;/strong&gt; MiniMax-Text-01 的 post-training token 来提高模型的指令跟随能力。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 3: Enhancement of User Experience&lt;/strong&gt;
这个阶段的目的是进一步提高模型在真实场景下模型的避险。作者构建了高质量的多模态数据，包括 &lt;strong&gt;44.8B&lt;/strong&gt; 的多模态 token, 这个阶段模型训练了一个 epoch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 4: Enhancement of Preference&lt;/strong&gt;
这个阶段的目的是对齐，作者使用 &lt;a class="link" href="https://maosong.website/p/notes-on-dpo/" target="_blank" rel="noopener"
&gt;DPO&lt;/a&gt; 来训练模型，数据集包括 &lt;strong&gt;40,000&lt;/strong&gt; 条数据。数据构建过程如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;prompt selection: 作者基于真实用户交互数据构建了高质量的 prompt&lt;/li&gt;
&lt;li&gt;Response generation: 作者通过多次采样，然后使用 MiniMax-Text-01 来生成多样化的数据&lt;/li&gt;
&lt;li&gt;Reward Assignment: 接下来作者使用 MiniMax-Text- 来评估最终的结果&lt;/li&gt;
&lt;li&gt;Pair Construction: 最后，基于评估结果来构建 preference pairs.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;作者还加入了一些纯文本的 preference data.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Observation
作者发现，如果 foundation model 比较强，使用 DPO 的话可能会导致过拟合，因此作者的做法是在一个 epoch 之前就停止训练。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="evaluation"&gt;&lt;a href="#evaluation" class="header-anchor"&gt;&lt;/a&gt;Evaluation
&lt;/h2&gt;&lt;p&gt;作者对比了 GPT-4o, Claude-3.5-Sonnet, Gemini-1.5-Pro, Qwen2-VL-72B, InternVL2.5-78B 和 LLaMA-3.2-90B, 实验结果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-minimax-01/MiniMax-01-VL-performance.png"
width="1342"
height="937"
loading="lazy"
alt="Performance of MiniMax-VL-01"
class="gallery-image"
data-flex-grow="143"
data-flex-basis="343px"
&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;在本文中，作者提出了 MiniMax-01 大模型系列，包括 MiniMax-Text-01 和 MiniMax-VL-01 两个模型，前者是一个总参数为 456B, 激活参数为 45.9B 的基于 MoE 和 hybrid attention 的大语言模型，后者是基于 MiniMax-Text-01 的多模态大模型。作者详细介绍了模型的架构，数据和训练。&lt;/p&gt;
&lt;p&gt;作者认为，未来有以下探索方向：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Long-context Evaluation: 如何更好评估模型的长上下文能力。现有的 long-context benchmark 的任务都比较简单，很难反应模型的真实能力&lt;/li&gt;
&lt;li&gt;Model Architecture: 当前的模型还有 1/8 的模块包含 softmax attention, 如何构建更高效的架构来去掉 softmax attention 是一个值得探究的方向。&lt;/li&gt;
&lt;li&gt;Complex Programming Tasks: 如何提高模型的 coding 能力也是一个值得探索的方向。&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Notes on Gemini3.0</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini3.0/</link><pubDate>Tue, 06 Jan 2026 10:26:39 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini3.0/</guid><description>&lt;p&gt;Gemini 3.0 是是 Google 新一代最强模型，model card 介绍了 Gemini 3.0 系列的评估结果以及基本能力&lt;/p&gt;
&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;Gemini 3.0 系列包含&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gemini 3.0 Pro&lt;/li&gt;
&lt;li&gt;Gemini 3.0 Flash&lt;/li&gt;
&lt;li&gt;Gemini 3.0 Pro Image
三个模型&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gemini 3.0 Pro 拥有原生多模态以及 reasoning 能力，可以处理 text, audio, images, video 以及 code repositories 等模态。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;modalities&lt;/th&gt;
&lt;th&gt;context&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;input&lt;/td&gt;
&lt;td&gt;text, images, audio, video&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;output&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;64K&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Gemini 3.0 Flash 与 Gemini 3.0 Pro 基本一致，与 &lt;a class="link" href="https://maosong.website/p/notes-on-gemini2.5/" target="_blank" rel="noopener"
&gt;Gemini2.5&lt;/a&gt; 相同，应该是采取了蒸馏的方式来实现更高的吞吐速度以及效率&lt;/p&gt;
&lt;p&gt;Gemini 3.0 Pro Image 基于 Gemini 3.0 Pro 开发，是一个支持 text, image prompt 的图片生成模型&lt;/p&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;p&gt;模型从零开始训练，使用了 MoE 架构和 Transformer 架构&lt;/p&gt;
&lt;p&gt;模型使用 TPU 进行训练，训练架构为 JAX 和 ML Pathways.&lt;/p&gt;
&lt;h2 id="experiments"&gt;&lt;a href="#experiments" class="header-anchor"&gt;&lt;/a&gt;Experiments
&lt;/h2&gt;&lt;p&gt;Gemini 3.0 Pro 对比了 &lt;a class="link" href="https://maosong.website/p/notes-on-gemini2.5/" target="_blank" rel="noopener"
&gt;Gemini2.5&lt;/a&gt; , Claude Sonnet 4.5 和 GPT-5.1&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini3.0/Gemini-3-0-pro-performance.png"
width="1081"
height="963"
loading="lazy"
alt="Performance of Gemini 3.0 Pro"
class="gallery-image"
data-flex-grow="112"
data-flex-basis="269px"
&gt;&lt;/p&gt;
&lt;p&gt;Gemini 3.0 Flash 对比了 Gemini 3.0 Pro, Gemini 2.5 Flash, Gemini 2.5 Pro, Claude Sonnet 4.5, GPT-5.2 和 Grok 4.1 Fast.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini3.0/Gemini-3-0-Flash-performance.png"
width="1082"
height="1073"
loading="lazy"
alt="Performance of Gemini 3.0 Flash"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="242px"
&gt;&lt;/p&gt;
&lt;p&gt;Gemini 3.0 Pro Image 对比了 Gemini 2.5 Flash Image, GPT-Image 1, Seedream v4, Flux Pro Kontext Max&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini3.0/Gemini-3-0-Pro-Image-performance.png"
width="1372"
height="795"
loading="lazy"
alt="Performance of Gemini 3.0 Pro Image on existing capabilities"
class="gallery-image"
data-flex-grow="172"
data-flex-basis="414px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini3.0/Gemini-3-0-Pro-Image-performance-new.png"
width="1332"
height="721"
loading="lazy"
alt="Performance of Gemini 3.0 Pro Image on new capabilities"
class="gallery-image"
data-flex-grow="184"
data-flex-basis="443px"
&gt;&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://storage.googleapis.com/deepmind-media/Model-Cards/Gemini-3-Pro-Model-Card.pdf" target="_blank" rel="noopener"
&gt;Gemini 3.0 Pro Model Card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://storage.googleapis.com/deepmind-media/Model-Cards/Gemini-3-Flash-Model-Card.pdf" target="_blank" rel="noopener"
&gt;Gemini 3.0 Flash Model Card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://storage.googleapis.com/deepmind-media/Model-Cards/Gemini-3-Pro-Image-Model-Card.pdf" target="_blank" rel="noopener"
&gt;Gemini 3.0 Pro Image Model Card&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MoE tutorial</title><link>https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/</link><pubDate>Sat, 13 Dec 2025 16:04:04 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/</guid><description>&lt;p&gt;本 blog 详细介绍了 MoE 模型的一些关键设计与相关实验结果，为 MoE 模型的学习提供基础。&lt;/p&gt;
&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;h3 id="motivation"&gt;&lt;a href="#motivation" class="header-anchor"&gt;&lt;/a&gt;Motivation
&lt;/h3&gt;&lt;p&gt;现有大部分大语言模型均是基于 Transformer 架构，&lt;a class="link" href="https://maosong.website/p/kaplan-scaling-law/" target="_blank" rel="noopener"
&gt;Kaplan scaling law&lt;/a&gt; 通过实验说明，大语言模型的表现与算力，数据，模型参数量息息相关。但是，对于 dense 模型来说，我们提高模型参数量时，必须同时提高所使用的算力。这就限制了大模型的 scaling law.&lt;/p&gt;
&lt;p&gt;而 MoE 模型的解决方法为在计算时只激活部分参数，这样，我们就可以在同等激活参数量/算力下训练更大参数量的模型，从而达到更好地表现。&lt;/p&gt;
&lt;p&gt;因此，MoE 模型的核心思想在于&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;使用相同的激活参数量/算力，提高模型总参数量，从而达到更好的表现。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="definition"&gt;&lt;a href="#definition" class="header-anchor"&gt;&lt;/a&gt;Definition
&lt;/h3&gt;&lt;p&gt;MoE 模型和 dense 模型的示意图如下，图源 &lt;a class="link" href="https://maosong.website/p/notes-on-olmoe/" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/olmoe-MoE_architecture.png"
width="1356"
height="912"
loading="lazy"
alt="olmoe-MoE_architecture"
class="gallery-image"
data-flex-grow="148"
data-flex-basis="356px"
&gt;&lt;/p&gt;
&lt;p&gt;一个 MoE layer 包括两个模块：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Router：Router 负责为 token 指定合适的专家&lt;/li&gt;
&lt;li&gt;Expert：Expert 负责处理 token&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;对于输入 $x\in\mathbb{R}^d$, 我们假设有 $N$ 个 Expert，router 一般是一个 linear layer 再加上一个 gating function (softmax 或者 sigmoid， 我们本文中使用 softmax), 其构建了 $\mathbb{R}^d\to\mathbb{R}^N$ 的映射，定义为：&lt;/p&gt;
$$
G(x) =[G_1(x),\dots,G_N(x)] = \mathrm{softmax}(W_gx + b)\in\mathbb{R}^N
$$&lt;p&gt;其中 $W_g\in\mathbb{R}^{N\times d}$, $b\in\mathbb{R}^N$ 是可学习的参数。$G_{i}(x)$ 代表了当前 token $x$ 选择第 $i$ 个 Expert 的概率。&lt;/p&gt;
&lt;p&gt;一般来说，Expert 会使用和 dense 模型一样的 MLP, 我们记为&lt;/p&gt;
$$
E_i(x) = \mathrm{FFN}(x), \quad i = 1,\dots,N
$$&lt;p&gt;接下来，基于 $G(x)$ 和 $E(x)$, 我们会使用合适的方法来挑选 $K&lt;N$ 个 Expert 出来，其中 $K$ 是给定的超参数，我们记挑选出来的 $K$ 个 Expert 的 index 为 $e_1,\dots,e_K$, 即&lt;/p&gt;
$$
e_i \in \{i\mid G_i(x)\in \mathrm{TopK}(G_i(x), K)\},\ i=1,\dots,K
$$&lt;p&gt;最终 MoE layer 的输出为&lt;/p&gt;
$$
y = \sum_{i=1}^K\mathrm{Normalize}(G_{e_i}(x)) E_{e_i}(x)
$$&lt;p&gt;这里 $\mathrm{Normalize}(\cdot)$ 代表我们对于输出进行归一化，即&lt;/p&gt;
$$
\mathrm{Normalize}(G_{e_i}) = \frac{\exp(G_{e_i})}{\sum_{i=1}^K \exp(G_{e_i})},\quad i=1,\dots,K
$$&lt;h3 id="why-moe"&gt;&lt;a href="#why-moe" class="header-anchor"&gt;&lt;/a&gt;Why MoE
&lt;/h3&gt;&lt;p&gt;选择 MoE 的原因有三点：效率, scaling law 以及表现。&lt;/p&gt;
&lt;h4 id="efficiency"&gt;&lt;a href="#efficiency" class="header-anchor"&gt;&lt;/a&gt;Efficiency
&lt;/h4&gt;&lt;p&gt;MoE 训练更加高效，如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/Switch-Transformer-speed-comparison.png"
width="839"
height="672"
loading="lazy"
alt="Comparison between moe and dense models (Switch Transformer)"
class="gallery-image"
data-flex-grow="124"
data-flex-basis="299px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 的 实验结果说明，MoE model 的训练效率比 dense model 快 7 倍左右。其他模型也有类似结论。总的来说，MoE 模型相比于 dense 模型，训练效率更高。&lt;/p&gt;
&lt;h4 id="scaling-law"&gt;&lt;a href="#scaling-law" class="header-anchor"&gt;&lt;/a&gt;Scaling Law
&lt;/h4&gt;&lt;p&gt;MoE 模型可以突破传统 scaling law 的限制，在算力固定的情况下，我们可以通过提高 MoE 模型的稀疏度来进一步提高模型的表现&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/EL-activation-ratio-impact.png"
width="829"
height="485"
loading="lazy"
alt="Impact of the Activation Ratio A on Loss and Efficiency"
class="gallery-image"
data-flex-grow="170"
data-flex-basis="410px"
&gt;&lt;/p&gt;
&lt;p&gt;如上图所示，在 FLOPs 给定的情况下，随着模型稀疏度的提高，模型的表现和效率都有提升&lt;/p&gt;
&lt;h4 id="performance"&gt;&lt;a href="#performance" class="header-anchor"&gt;&lt;/a&gt;Performance
&lt;/h4&gt;&lt;p&gt;MoE 模型的表现更强，如下图所示，MoE 模型的训练，验证损失以及在下游任务上的表现均超过了 dense 模型&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/olmoe-MoE-vs-Dense-training-efficiency.png"
width="1155"
height="626"
loading="lazy"
alt="MoE vs. Dense (olmoe)"
class="gallery-image"
data-flex-grow="184"
data-flex-basis="442px"
&gt;&lt;/p&gt;
&lt;h3 id="timeline"&gt;&lt;a href="#timeline" class="header-anchor"&gt;&lt;/a&gt;Timeline
&lt;/h3&gt;&lt;p&gt;激活参数比例变化图如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/moe_timeline_parameters.png"
width="3320"
height="1764"
loading="lazy"
alt="activation ratio of MoE models"
class="gallery-image"
data-flex-grow="188"
data-flex-basis="451px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，当前大部分模型的激活比例都在 $5\%$ 左右。&lt;/p&gt;
&lt;p&gt;另一方面，从专家的激活比例变化图如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/moe_timeline_experts.png"
width="3294"
height="1764"
loading="lazy"
alt="activation ratio (experts) of moe models"
class="gallery-image"
data-flex-grow="186"
data-flex-basis="448px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，现在大部分模型总专家数都在 200-400 左右，&lt;a class="link" href="https://maosong.website/p/notes-on-kimi-k2/" target="_blank" rel="noopener"
&gt;Kimi-k2&lt;/a&gt; 认为提高专家个数可以提高模型表现，而 LongCat 则是使用了 phantom expert 机制&lt;/p&gt;
&lt;h2 id="moe-design"&gt;&lt;a href="#moe-design" class="header-anchor"&gt;&lt;/a&gt;MoE Design
&lt;/h2&gt;&lt;h3 id="experts-design"&gt;&lt;a href="#experts-design" class="header-anchor"&gt;&lt;/a&gt;Experts Design
&lt;/h3&gt;&lt;h4 id="number-of-experts"&gt;&lt;a href="#number-of-experts" class="header-anchor"&gt;&lt;/a&gt;Number of Experts
&lt;/h4&gt;&lt;p&gt;一般来说，专家个数越多，模型越稀疏，模型表现越好。扩展专家个数有两个方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;直接增加专家个数，这会导致模型参数量上升，如 &lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;对已有的专家进行切分，将大专家切分为小专家，如 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 也通过实验发现，增加专家个数可以显著提高模型的训练效率和表现，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/Switch-Transformer-scaling-law.png"
width="1244"
height="497"
loading="lazy"
class="gallery-image"
data-flex-grow="250"
data-flex-basis="600px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，当我们增加专家个数的时候，模型的表现是持续提升的。并且当我们增加专家个数之后，模型的训练效率也有所提升。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 提出了 fine-granularity expert 的概念，其做法是通过减少 expert 的大小在相同参数量的场景下使用更多的专家。实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/DeepSeekMoE-ablation-experts.png"
width="1197"
height="552"
loading="lazy"
alt="DeepSeek-Moe shared experts ablation study"
class="gallery-image"
data-flex-grow="216"
data-flex-basis="520px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，在稀疏度 (激活专家个数占总专家个数比例) 不变的情况下，提高专家的粒度，可以提高模型的表现。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-olmoe/" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt; 对 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 的这个观点进行了验证，结果如下图所示，&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/olmoe-expert-granularity.png"
width="1446"
height="592"
loading="lazy"
alt="Expert granularity"
class="gallery-image"
data-flex-grow="244"
data-flex-basis="586px"
&gt;&lt;/p&gt;
&lt;p&gt;结果显示，当专家粒度从 8E-1A 扩展到 32E-4A 时，模型在 HellaSwag 上的表现提升了 $10\%$, 但是进一步扩展到 64E-8A 时，模型的表现提升不到 $2\%$, 这说明了无限制提升专家粒度对模型的提升越来越有限。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-kimi-k2/" target="_blank" rel="noopener"
&gt;Kimi-k2&lt;/a&gt; 探究了针对 MoE 模型 sparsity 的 scaling law, 结果也说明，提升 sparsity 可以提高模型的表现。因此，其相对于 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v3/" target="_blank" rel="noopener"
&gt;DeepSeek-V3&lt;/a&gt; 使用了 $50\%$ 额外的的专家数。&lt;a class="link" href="https://maosong.website/p/notes-on-ling-mini-beta/" target="_blank" rel="noopener"
&gt;Ling-mini-beta&lt;/a&gt; 进一步验证了这个观点。&lt;/p&gt;
&lt;h4 id="shared-experts"&gt;&lt;a href="#shared-experts" class="header-anchor"&gt;&lt;/a&gt;Shared Experts
&lt;/h4&gt;&lt;p&gt;Shared Expert 由 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 提出，其基本思想为，固定某几个专家，响应所有的 token，这样可以让某些专家学习到共有的知识，而让其他的专家学习到特定的知识。这个方法随后被 &lt;a class="link" href="https://maosong.website/p/notes-on-qwen1.5/" target="_blank" rel="noopener"
&gt;Qwen1.5&lt;/a&gt;, &lt;a class="link" href="https://maosong.website/p/notes-on-qwen2/" target="_blank" rel="noopener"
&gt;Qwen2&lt;/a&gt; , &lt;a class="link" href="https://maosong.website/p/notes-on-qwen2.5/" target="_blank" rel="noopener"
&gt;Qwen2.5&lt;/a&gt; 以及 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v3/" target="_blank" rel="noopener"
&gt;DeepSeek-V3&lt;/a&gt; 所采用。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 给出的实验结果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/DeepSeekMoE-ablation-experts.png"
width="1197"
height="552"
loading="lazy"
alt="DeepSeek-Moe shared experts ablation study"
class="gallery-image"
data-flex-grow="216"
data-flex-basis="520px"
&gt;&lt;/p&gt;
&lt;p&gt;作者发现，当使用 shared experts 之后，模型在大部分 benchmark 上的表现都有所提升。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-olmoe/" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt; 在 32 个专家下进行了实验，比较了 4 个激活专家和 3 个激活专家 +1 个共享专家两种设置的表现，结果如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/olmoe-shared-experts.png"
width="1156"
height="477"
loading="lazy"
alt="Olmoe shared experts performance"
class="gallery-image"
data-flex-grow="242"
data-flex-basis="581px"
&gt;&lt;/p&gt;
&lt;p&gt;作者认为，加入 shared experts 之后，组合的可能性有所减少，这会降低模型的泛化性。因此，在 olmoe 中，作者没有使用 shared experts.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;虽然 &lt;a class="link" href="https://maosong.website/p/notes-on-qwen1.5/" target="_blank" rel="noopener"
&gt;Qwen1.5&lt;/a&gt;, &lt;a class="link" href="https://maosong.website/p/notes-on-qwen2/" target="_blank" rel="noopener"
&gt;Qwen2&lt;/a&gt; 和 &lt;a class="link" href="https://maosong.website/p/notes-on-qwen2.5/" target="_blank" rel="noopener"
&gt;Qwen2.5&lt;/a&gt; 都使用了 shared experts, 但是后续的 &lt;a class="link" href="https://maosong.website/p/notes-on-qwen3/" target="_blank" rel="noopener"
&gt;Qwen3&lt;/a&gt; 中却并没有使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-ling-mini-beta/" target="_blank" rel="noopener"
&gt;Ling-mini-beta&lt;/a&gt; 通过实验得出的结论为，shared expert 应该是一个非零的尽可能小的值，作者认为将 shared expert 设置为 1 是一个比较合理的选择。&lt;/p&gt;
&lt;h3 id="activation-function"&gt;&lt;a href="#activation-function" class="header-anchor"&gt;&lt;/a&gt;Activation Function
&lt;/h3&gt;&lt;p&gt;一般来说，在选取 top-K 专家时，我们会对 gating layer 的输出进行归一化，通常我们会使用 softmax function:&lt;/p&gt;
$$
G(x) = \mathrm{softmax}(W_gx + b)\in\mathbb{R}^N
$$&lt;p&gt;但是，在 &lt;a class="link" href="https://maosong.website/p/notes-on-loss-free-balancing/" target="_blank" rel="noopener"
&gt;Loss-Free Balancing&lt;/a&gt; 中，作者通过实验发现，使用 sigmoid 作为激活函数效果更好，即&lt;/p&gt;
$$
G(x) = \mathrm{sigmoid}(W_gx + b)\in\mathbb{R}^N
$$&lt;p&gt;其对应的实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/loss-free-ablation-gating-function.png"
width="917"
height="573"
loading="lazy"
alt="Ablation study on gating function"
class="gallery-image"
data-flex-grow="160"
data-flex-basis="384px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，sigmoid function 对于超参数更加 robust, 且表现也更好一些。 下面是一些使用不同激活函数的模型例子&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Activation function&lt;/th&gt;
&lt;th&gt;Models&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;softmax&lt;/td&gt;
&lt;td&gt;Step 3, Kimi-K2, gpt-oss-120B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sigmoid&lt;/td&gt;
&lt;td&gt;GLM-4.5, dots.llm1, DeepSeek-V3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="routing-z-loss"&gt;&lt;a href="#routing-z-loss" class="header-anchor"&gt;&lt;/a&gt;Routing Z-loss
&lt;/h3&gt;&lt;p&gt;Routing Z-loss 由 &lt;a class="link" href="https://maosong.website/p/st-moe/" target="_blank" rel="noopener"
&gt;ST-MoE&lt;/a&gt; 提出， &lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 发现在 gating layer 中使用 &lt;code&gt;float32&lt;/code&gt; 精度可以提高训练稳定性，但是这还不够，因此 &lt;a class="link" href="https://maosong.website/p/st-moe/" target="_blank" rel="noopener"
&gt;ST-MoE&lt;/a&gt; 使用了如下的 router Z-loss:&lt;/p&gt;
$$
\mathcal{L}_z(x) = \frac1B\sum_{i=1}^B\left(\log\sum_{j=1}^N e^{x_j^{(i)}}\right)^2
$$&lt;p&gt;其中 $B$ 是 batch size ，$x_j^{(i)}=[W_gx_i+b]_j$ 代表了第 $j$ 个专家对 $i$ 个 token 的激活 logits. &lt;a class="link" href="https://maosong.website/p/notes-on-olmoe/" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt; 实验验证结果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/olmoe-routing-z-loss.png"
width="1162"
height="419"
loading="lazy"
alt="Ablation study on Routing Z-loss"
class="gallery-image"
data-flex-grow="277"
data-flex-basis="665px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，加入 router Z-loss 之后，模型训练的稳定性有所提升，因此 Olmoe 采取了这个改进，但是后续的 MoE 模型使用 Z-loss 较少，个人猜测原因是 &lt;a class="link" href="https://maosong.website/p/notes-on-loss-free-balancing/" target="_blank" rel="noopener"
&gt;Loss-Free Balancing&lt;/a&gt; 中提出的加入额外的 loss 会影响 nex-token prediction loss&lt;/p&gt;
&lt;h3 id="routing-strategy"&gt;&lt;a href="#routing-strategy" class="header-anchor"&gt;&lt;/a&gt;Routing Strategy
&lt;/h3&gt;&lt;p&gt;routing 策略直接决定了 MoE 模型的有效性。在为专家分配 token 的时候，我们有如下方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;为每个 token 选取若干个专家&lt;/li&gt;
&lt;li&gt;为每个专家选取若个个 token&lt;/li&gt;
&lt;li&gt;动态分配 token 与专家之间的关系&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;三种选择方式如下图所示，图源 &lt;a class="link" href="https://arxiv.org/pdf/2209.01667" target="_blank" rel="noopener"
&gt;MoE survey&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/MoE_routing.png"
width="1070"
height="458"
loading="lazy"
class="gallery-image"
data-flex-grow="233"
data-flex-basis="560px"
&gt;&lt;/p&gt;
&lt;h4 id="expert-choice"&gt;&lt;a href="#expert-choice" class="header-anchor"&gt;&lt;/a&gt;Expert Choice
&lt;/h4&gt;&lt;p&gt;每个专家选取 top-k 的 token，此时每个专家处理的 token 个数是相同的，这个方法的好处是自带 load balance。缺点是自回归生成的方式没有完整序列长度的信息，从而导致 token dropping，也就是某些 token 不会被任何专家处理，某些 token 会被多个专家处理。&lt;/p&gt;
&lt;p&gt;目前采用这个策略的有 OpenMoE-2， 核心思想是 dLLM 的输出长度固定，expert choice 策略更有效&lt;/p&gt;
&lt;h4 id="token-choice"&gt;&lt;a href="#token-choice" class="header-anchor"&gt;&lt;/a&gt;Token Choice
&lt;/h4&gt;&lt;p&gt;每个 token 选取 top-k 的专家，好处是每个 token 都会被处理，缺点是容易导致负载不均衡。因此，一般需要加上负载均衡或者 token dropping 策略来提高负载均衡&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Capacity Factor&lt;/strong&gt;
由 &lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 提出，其定义为&lt;/p&gt;
$$
\text{expert capacity} = \left(\frac{\text{tokens per batch}}{\text{number of experts}}\right) * \text{capacity factor}
$$&lt;p&gt;设置 capacity factor 之后，当某个专家处理的 token 个数超过 capacity 之后，概专家的计算就会直接跳过，退化为 residual connection. 后续 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v2/" target="_blank" rel="noopener"
&gt;DeepSeek-V2&lt;/a&gt; 也采用了这种策略，但是 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v3/" target="_blank" rel="noopener"
&gt;DeepSeek-V3&lt;/a&gt; 弃用&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Load balancing Loss&lt;/strong&gt;
在训练目标中加入负载均衡损失，要求每个专家处理的 token 个数的分布尽可能均匀。&lt;/p&gt;
&lt;p&gt;这部分具体见 &lt;a class="link" href="https://maosong.website/p/load-balancing-tutorial/" target="_blank" rel="noopener"
&gt;Load Balancing loss&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="global-choice"&gt;&lt;a href="#global-choice" class="header-anchor"&gt;&lt;/a&gt;Global Choice
&lt;/h4&gt;&lt;p&gt;全局分配决定 token 和专家的匹配关系，后续 Qwen 提出了 &lt;a class="link" href="https://maosong.website/p/notes-on-global-batch-load-balancing/" target="_blank" rel="noopener"
&gt;Global-batch load balancing&lt;/a&gt; 使用了这种方式来提高专家的特化程度&lt;/p&gt;
&lt;h4 id="dynamic-routing"&gt;&lt;a href="#dynamic-routing" class="header-anchor"&gt;&lt;/a&gt;Dynamic Routing
&lt;/h4&gt;&lt;p&gt;根据输入 token 的难度动态决定激活专家的个数。LongCat 使用了一个 Phantom expert 的方法来实现根据 token 的难度动态分配专家。具体来说，除了 $N$ 个专家之外，MoE 还包括 $Z$ 个 zero-computation expert (现在一共有 $N+Z$ 个专家参与计算), 其计算方式如下&lt;/p&gt;
$$
\begin{aligned}
y &amp;= \sum_{i=1}^{K}\mathrm{Normalize}(G_{e_i}) E_{e_i}(x), e_i \in \{i\mid G_i(x)\in \mathrm{TopK}(G_i(x), K)\}\\
E_{e_i}(x) &amp;= \begin{cases}
FFN_{e_i}(x), &amp; \text{ if }1\leq i\leq N\\
x, &amp; \text{ otherwise }\\
\end{cases}
\end{aligned}
$$&lt;blockquote&gt;
&lt;p&gt;注：LongCat 还是用了 &lt;a class="link" href="https://maosong.website/p/notes-on-loss-free-balancing/" target="_blank" rel="noopener"
&gt;Loss-Free Balancing&lt;/a&gt;, 我们这里省略掉了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="overview"&gt;&lt;a href="#overview" class="header-anchor"&gt;&lt;/a&gt;Overview
&lt;/h4&gt;&lt;p&gt;现在几乎所有的模型都选择方式 1，即每个 token 选取 top-k 的专家。 &lt;a class="link" href="https://maosong.website/p/notes-on-olmoe/" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt; 对比了以下方式 1 和方式 2 的表现，如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/olmoe-routing-strategy.png"
width="1157"
height="450"
loading="lazy"
alt="MoE routing strategy EC v.s. TC"
class="gallery-image"
data-flex-grow="257"
data-flex-basis="617px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，加入 load balancing loss 之后，相比于 Expert Choice, Token Choice 的表现更好。但是，expert choice 更加高效，作者认为 expert choice 更适用于多模态，因为丢掉 noise image tokens 对 text token 影响会比较小。因此，在 olmoe 中，作者使用 token choice 作为 routing 策略&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/celebras-routing-landscape.png"
width="1102"
height="762"
loading="lazy"
alt="Routing strategy overview (celebras)"
class="gallery-image"
data-flex-grow="144"
data-flex-basis="347px"
&gt;&lt;/p&gt;
&lt;h3 id="upcycling"&gt;&lt;a href="#upcycling" class="header-anchor"&gt;&lt;/a&gt;Upcycling
&lt;/h3&gt;&lt;p&gt;upsampling 是一个将 dense model 转化为 MoEmodel 的方法，具体做法就是我们复制 dense model 中的 FFN layer 得到对应 MoE layer 中的 Expert，然后我们再结合 router 训练，这样可以提高整体的训练效率。相关模型有 MiniCPM, &lt;a class="link" href="https://maosong.website/p/notes-on-qwen1.5/" target="_blank" rel="noopener"
&gt;Qwen1.5&lt;/a&gt; 和 &lt;a class="link" href="https://maosong.website/p/mixstral-8x7b/" target="_blank" rel="noopener"
&gt;Mixtral MoE&lt;/a&gt; (疑似)&lt;/p&gt;
&lt;p&gt;实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/olmoe-sparse-upcycling.png"
width="1440"
height="680"
loading="lazy"
class="gallery-image"
data-flex-grow="211"
data-flex-basis="508px"
&gt;&lt;/p&gt;
&lt;p&gt;从已有的结果来看，MoE 模型会被 dense 模型的一些超参数所限制，且训练不是很稳定。因此，现在一般不采用这种方法&lt;/p&gt;
&lt;h2 id="analysis-on-moe"&gt;&lt;a href="#analysis-on-moe" class="header-anchor"&gt;&lt;/a&gt;Analysis on MoE
&lt;/h2&gt;&lt;h3 id="specialization-of-experts"&gt;&lt;a href="#specialization-of-experts" class="header-anchor"&gt;&lt;/a&gt;Specialization of Experts
&lt;/h3&gt;&lt;p&gt;OpenMoE 分析了 MoE 模型的特化程度，其结论如下&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;作者发现，大部分专家对于不同的 domain 没有出现 specialization 情况，对于 math domain, specialization 现象比较明显，作者认为这是因为 math domain 包含更多的 special tokens&lt;/li&gt;
&lt;li&gt;对于不同的语言，有部分专家出现 specialization 现象&lt;/li&gt;
&lt;li&gt;部分专家对于 position ID 有 specialization 现象，并且连续的 token 更偏好相同的专家&lt;/li&gt;
&lt;li&gt;作者还发现，部分专家对于 Token ID 有 specialization 现象，作者将这种现象称为 &lt;strong&gt;Context-independent Specialization&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;专家还会对语义相似的 token 进行聚类，并且这种聚类在训练早期就已经发生，作者认为其原因在于重新分配 token 会增加最终的 loss&lt;/li&gt;
&lt;li&gt;对于 token dropping, 作者发现越靠后的 token, 其被 drop 的概率比例也越高。并且对于指令跟随数据，更多的 token 都会被丢掉，因此作者认为指令跟随数据是 MoE 模型的一种 OOD 数据&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="saturation-of-experts"&gt;&lt;a href="#saturation-of-experts" class="header-anchor"&gt;&lt;/a&gt;Saturation of Experts
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-olmoe/" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt; 探究了训练过程中激活的专家和训练结束后激活的专家的匹配程度，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/olmoe-router-saturation.png"
width="1149"
height="393"
loading="lazy"
class="gallery-image"
data-flex-grow="292"
data-flex-basis="701px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果说明，训练 $1\%$ 的数据之后，就有 $40\%$ 的 routing 和训练完毕的 routing 一致，当训练 $40\%$ 的数据之后，这个比例提升到了 $80\%$. 作者认为，这是专家特化的结果，初始的 routing 如果改变的话会带来表现下降，因此模型倾向于使用固定的专家处理特定的 token&lt;/p&gt;
&lt;p&gt;作者还发现，later layers 比 early layers 饱和更快，early layer, 特别是 layer 0, 饱和的非常慢。作者认为，这是 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 放弃在第一层使用 MoE layer 的原因，因为 load balancing loss 收敛更慢。后续 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v2/" target="_blank" rel="noopener"
&gt;DeepSeek-V2&lt;/a&gt; 和 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v3/" target="_blank" rel="noopener"
&gt;DeepSeek-V3&lt;/a&gt; 均在 early layer 上使用 dense layer 替换掉了 MoE layer&lt;/p&gt;
&lt;h2 id="optimization"&gt;&lt;a href="#optimization" class="header-anchor"&gt;&lt;/a&gt;Optimization
&lt;/h2&gt;&lt;p&gt;MoE 模型的优势在于表现好，但是模型参数往往非常大，为了方便使用，我们需要对训练好的 MoE 模型进行优化，目前主要有蒸馏，专家剪枝/合并以及量化等优化方法&lt;/p&gt;
&lt;p&gt;蒸馏是一个将大模型能力传递给小模型的做法，目前已有的包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 通过蒸馏，在仅使用 $1/20$ 参数的情况下，保留了稀疏教师模型 $30\%$ 的表现&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-gemini2.5/" target="_blank" rel="noopener"
&gt;Gemini2.5&lt;/a&gt; 通过蒸馏 Gemini2.5 Pro 得到 Gemini2.5 Flash&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-r1/" target="_blank" rel="noopener"
&gt;DeepSeek-R1&lt;/a&gt; 通过蒸馏来提升小语言模型的 reasoning 能力&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-qwen3/" target="_blank" rel="noopener"
&gt;Qwen3&lt;/a&gt; 对于小语言模型的训练使用了 off-policy distillation 和 on-policy distillation 来训练小语言模型&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="code"&gt;&lt;a href="#code" class="header-anchor"&gt;&lt;/a&gt;Code
&lt;/h2&gt;&lt;p&gt;我们这里展示基于 &lt;a class="link" href="https://maosong.website/p/notes-on-olmoe/" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt; 的代码，代码如下&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OlmoeSparseMoeBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_experts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_experts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top_k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_experts_per_tok&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;norm_topk_prob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;norm_topk_prob&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hidden_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_experts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;experts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModuleList&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;OlmoeMLP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_experts&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sequence_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hidden_dim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# hidden_states: (batch * sequence_length, hidden_dim)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;hidden_states&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hidden_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# router_logits: (batch * sequence_length, n_experts)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;router_logits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;routing_weights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;router_logits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# routing_weights: (batch * sequence_length, top_k)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# selected_experts: indices of top_k experts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;routing_weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;selected_experts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;topk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;routing_weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;norm_topk_prob&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;routing_weights&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="n"&gt;routing_weights&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keepdim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# we cast back to the input dtype&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;routing_weights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;routing_weights&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;final_hidden_states&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch_size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;sequence_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hidden_dim&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# One hot encode the selected experts to create an expert mask&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# this will be used to easily index which expert is going to be selected&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;expert_mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;functional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;one_hot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selected_experts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_classes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_experts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Loop over all available experts in the model and perform the computation on each expert&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;expert_idx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_experts&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;expert_layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;experts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;expert_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expert_mask&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;expert_idx&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Index the correct hidden states and compute the expert hidden state for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# the current expert. We need to make sure to multiply the output hidden&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# states by `routing_weights` on the corresponding tokens (top-1 and top-2)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;current_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hidden_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;current_hidden_states&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;expert_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;routing_weights&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;top_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# However `index_add_` only support torch tensors for indexing so we&amp;#39;ll use&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# the `top_x` tensor here.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;final_hidden_states&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index_add_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_hidden_states&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;final_hidden_states&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;final_hidden_states&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sequence_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hidden_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;final_hidden_states&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;router_logits&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="infra"&gt;&lt;a href="#infra" class="header-anchor"&gt;&lt;/a&gt;Infra
&lt;/h2&gt;&lt;p&gt;针对 MoE 模型的 infra 主要涉及 expert parallelism (EP), EP 将 MoE layer 的计算分为了三个阶段：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;all-to-all dispatch: 基于 gating layer 的结果，将 token 通信传输到对应专家所在的 GPU 上&lt;/li&gt;
&lt;li&gt;computation: 执行计算，即 $E_i(x)$.&lt;/li&gt;
&lt;li&gt;all-to-all combine: 收集专家计算的结果，即 $y = \sum_{i=1}^K\mathrm{Normalize}(G_{e_i}(x)) E_{e_i}(x)$.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;其框架图如下所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/moe-tutorial/MoE-EP-pipeline.png"
width="1131"
height="832"
loading="lazy"
alt="pipeline of Expert Parallelism (EP)"
class="gallery-image"
data-flex-grow="135"
data-flex-basis="326px"
&gt;&lt;/p&gt;
&lt;h2 id="challenges"&gt;&lt;a href="#challenges" class="header-anchor"&gt;&lt;/a&gt;Challenges
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;构建针对 MoE 模型的 infra 比较困难，相关工作有 DeepSeek 提出的 DeepEP.&lt;/li&gt;
&lt;li&gt;训练不稳定，特别是负载均衡。负载均衡做不好容易导致模型崩塌。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;在本文中，我们系统性回顾了 MoE 的相关概念，MoE 模型已经是现在大语言模型的主流架构，比如商业模型 &lt;a class="link" href="https://maosong.website/p/notes-on-gemini2.5/" target="_blank" rel="noopener"
&gt;Gemini2.5&lt;/a&gt;, 开源领先的模型 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v3/" target="_blank" rel="noopener"
&gt;DeepSeek-V3&lt;/a&gt; , &lt;a class="link" href="https://maosong.website/p/notes-on-llama4-blog/" target="_blank" rel="noopener"
&gt;LLaMA4&lt;/a&gt; 以及 &lt;a class="link" href="https://maosong.website/p/notes-on-qwen3/" target="_blank" rel="noopener"
&gt;Qwen3&lt;/a&gt; 等都采用了 MoE 的架构，如何进一步优化 MoE 的训练方式是当前研究的一个重点方向。&lt;/p&gt;
&lt;h2 id="appendix"&gt;&lt;a href="#appendix" class="header-anchor"&gt;&lt;/a&gt;Appendix
&lt;/h2&gt;&lt;p&gt;MoE model information&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;total parameters&lt;/th&gt;
&lt;th&gt;activated parameters&lt;/th&gt;
&lt;th&gt;shared expert&lt;/th&gt;
&lt;th&gt;Routed experts&lt;/th&gt;
&lt;th&gt;activated experts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ST-MoE&lt;/td&gt;
&lt;td&gt;2022/4&lt;/td&gt;
&lt;td&gt;269B&lt;/td&gt;
&lt;td&gt;32B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mistral&lt;/td&gt;
&lt;td&gt;2024/1&lt;/td&gt;
&lt;td&gt;47B&lt;/td&gt;
&lt;td&gt;13B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek-MoE&lt;/td&gt;
&lt;td&gt;2024/1&lt;/td&gt;
&lt;td&gt;145B&lt;/td&gt;
&lt;td&gt;22B&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek-V2&lt;/td&gt;
&lt;td&gt;2024/5&lt;/td&gt;
&lt;td&gt;236B&lt;/td&gt;
&lt;td&gt;21B&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;160&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLaMA4&lt;/td&gt;
&lt;td&gt;2025/4&lt;/td&gt;
&lt;td&gt;400B&lt;/td&gt;
&lt;td&gt;17B&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek-V3&lt;/td&gt;
&lt;td&gt;2024/12&lt;/td&gt;
&lt;td&gt;671B&lt;/td&gt;
&lt;td&gt;37B&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3&lt;/td&gt;
&lt;td&gt;2025/5&lt;/td&gt;
&lt;td&gt;235B&lt;/td&gt;
&lt;td&gt;22B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dots.llm1&lt;/td&gt;
&lt;td&gt;2025/6&lt;/td&gt;
&lt;td&gt;142B&lt;/td&gt;
&lt;td&gt;14B&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Step 3&lt;/td&gt;
&lt;td&gt;2025/7&lt;/td&gt;
&lt;td&gt;316B&lt;/td&gt;
&lt;td&gt;38B&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kimi-K2&lt;/td&gt;
&lt;td&gt;2025/7&lt;/td&gt;
&lt;td&gt;1043B&lt;/td&gt;
&lt;td&gt;32B&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;384&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GLM-4.5&lt;/td&gt;
&lt;td&gt;2025/8&lt;/td&gt;
&lt;td&gt;355B&lt;/td&gt;
&lt;td&gt;32B&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;160&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gpt-oss&lt;/td&gt;
&lt;td&gt;2025/8&lt;/td&gt;
&lt;td&gt;116B&lt;/td&gt;
&lt;td&gt;5B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LongCat&lt;/td&gt;
&lt;td&gt;2025/9&lt;/td&gt;
&lt;td&gt;560B&lt;/td&gt;
&lt;td&gt;27B*&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;768*&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ling-1T&lt;/td&gt;
&lt;td&gt;2025/10&lt;/td&gt;
&lt;td&gt;1000B&lt;/td&gt;
&lt;td&gt;51B&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Remark
LongCat 采用了动态激活的方式，因此其结果有一个浮动范围。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/pdf/2101.03961" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/pdf/2209.01667" target="_blank" rel="noopener"
&gt;MoE Survey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://openreview.net/forum?id=xXTkbTBmqq" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/pdf/2006.16668" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cnblogs.com/rossiXYZ/p/18800825" target="_blank" rel="noopener"
&gt;blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/pdf/2501.16352v1" target="_blank" rel="noopener"
&gt;MoE a big data perspective&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://huggingface.co/blog/moe" target="_blank" rel="noopener"
&gt;Mixture of Experts Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cerebras.ai/blog/moe-guide-why-moe" target="_blank" rel="noopener"
&gt;MoE Fundamentals: Sparse Models Are the Future&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cerebras.ai/blog/moe-guide-router" target="_blank" rel="noopener"
&gt;MoE router&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2507.17702" target="_blank" rel="noopener"
&gt;Ling-Mini-beta&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on Ling-mini-beta</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/</link><pubDate>Sat, 13 Dec 2025 15:58:51 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;目前已经有了针对 dense LLM 的 scaling law, 如 &lt;a class="link" href="https://maosong.website/p/kaplan-scaling-law/" target="_blank" rel="noopener"
&gt;Kaplan scaling law&lt;/a&gt; 和 &lt;a class="link" href="https://maosong.website/p/chinchilla-scaling-law/" target="_blank" rel="noopener"
&gt;Chinchilla scaling law&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;但是，对于 MoE 模型，目前还缺乏一个比较系统的 scaling law.&lt;/p&gt;
&lt;p&gt;为了解决这个问题，作者提出了 efficiency leverage (EL), 用于衡量 MoE 模型的效率，其定义为&lt;/p&gt;
$$
EL(\mathcal{X}_{\mathrm{MoE}}\mid \mathrm{Dense})=\frac{C_{\mathrm{Dense}}}{C_{{\mathrm{MoE}}}}
$$&lt;p&gt;其中 $C_{\mathrm{Dense}}, C_{{\mathrm{MoE}}}$ 分别代表了训练模型所需要的算力。EL 衡量了 moe 模型达到对应 dense 模型表现所需要的算力，EL 值越大，说明 MoE 模型效率越高。EL 的可视化如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/EL-definition.png"
width="555"
height="459"
loading="lazy"
alt="Definition of EL"
class="gallery-image"
data-flex-grow="120"
data-flex-basis="290px"
&gt;&lt;/p&gt;
&lt;p&gt;作者通过训练多个模型，探究了 MoE 架构与 EL 之间的关系。作者发现，MoE 模型的表现主要与专家激活比例以及算力相关。基于 scaling law, 作者训练了 Ling-mini-beta, 一个 17.5B-A0.85B 的 MoE 模型，其表现超过了 6.1B dense 模型的表现。&lt;/p&gt;
&lt;h2 id="preliminary"&gt;&lt;a href="#preliminary" class="header-anchor"&gt;&lt;/a&gt;Preliminary
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Notation&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$N$&lt;/td&gt;
&lt;td&gt;total parameters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$N_a$&lt;/td&gt;
&lt;td&gt;active parameters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$E$&lt;/td&gt;
&lt;td&gt;routed experts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$E_a$&lt;/td&gt;
&lt;td&gt;activated experts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$E_s$&lt;/td&gt;
&lt;td&gt;shared experts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;作者定义 activation ratio 如下:&lt;/p&gt;
$$
A = \frac{E_a+E_s}{E+E_s}
$$&lt;p&gt;定义 sharing ratio 如下&lt;/p&gt;
$$
S=\frac{E_s}{E_a+E_s}
$$&lt;p&gt;定义 expert granularity 如下&lt;/p&gt;
$$
G = \frac{d_{\mathrm{model}}}{d_{\mathrm{Expert}}}
$$&lt;p&gt;与 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-llm/" target="_blank" rel="noopener"
&gt;DeepSeek-LLM&lt;/a&gt; 一样，作者使用 $C=MD$ 来表示算力，non-embedding FLOPs $M$ 和训练 token 数 $D$ 之间的关系。&lt;/p&gt;
&lt;h3 id="hyper-parameters"&gt;&lt;a href="#hyper-parameters" class="header-anchor"&gt;&lt;/a&gt;Hyper Parameters
&lt;/h3&gt;&lt;p&gt;作者首先探究了针对 MoE 模型的超参数配置，最终你和出来的结果如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/EL-hyperparameter-scaling-law.png"
width="1377"
height="586"
loading="lazy"
alt="Scaling laws for optimal hyperparameters"
class="gallery-image"
data-flex-grow="234"
data-flex-basis="563px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果说明，相比于 dense model, MoE model 需要更大的 batch size.&lt;/p&gt;
&lt;p&gt;作者基于这个 scaling law 进行了验证，结果说明这个 scaling law 比较准确。&lt;/p&gt;
&lt;h3 id="parameters-and-dataset-size"&gt;&lt;a href="#parameters-and-dataset-size" class="header-anchor"&gt;&lt;/a&gt;Parameters and Dataset Size
&lt;/h3&gt;&lt;p&gt;接下来作者探究了对于模型参数量以及训练 token 个数之间的 scaling law, 求解的问题如下&lt;/p&gt;
$$
(M^{opt}, D^{opt}) = \arg\min_{M,D}\mathcal{L}(M,D;C,A,G,S)\quad s.t.\ C=MD
$$&lt;p&gt;实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/EL-model-data-scaling.png"
width="1374"
height="537"
loading="lazy"
alt="Scaling laws for optimal model scale and data size"
class="gallery-image"
data-flex-grow="255"
data-flex-basis="614px"
&gt;&lt;/p&gt;
&lt;p&gt;结果说明，不同架构对应的系数接近 $0.5$, 说明我们应该将算力均衡分配到数据和 model size 上。领一方面，MoE 模型可以通过使用更多的数据来达到更优的表现。&lt;/p&gt;
&lt;h2 id="efficiency-leverage"&gt;&lt;a href="#efficiency-leverage" class="header-anchor"&gt;&lt;/a&gt;Efficiency Leverage
&lt;/h2&gt;&lt;p&gt;作者将 Efficiency Leverage (EL) 定义为给定算力 $C_{target}$ 和一个 MoE 模型 $\mathcal{X}_{MoE}$, 对应 dense 模型达到 $\mathcal{X}_{MoE}$ 相同的表现所需要的算力 $C_{dense}$, 即&lt;/p&gt;
$$
\begin{aligned}
&amp;EL(\mathcal{X}_{\mathrm{MoE}}\mid \mathrm{Dense};C_{target})=\frac{C_{\mathrm{Dense}}}{C_{{\mathrm{MoE}}}}\\
s.t.\ &amp; |\mathcal{L}(C_{MoE}, \mathcal{X}_{\mathrm{MoE}})-\mathcal{L}(C_{dense}, \mathcal{X}_{\mathrm{dense}})|\leq \epsilon (\epsilon\to 0)
\end{aligned}
$$&lt;p&gt;EL 值越高说明 MoE 模型越有效。为了公平起见，dense 模型和 MoE 模型的架构参数基本相同，作者只改变 $d_{model}, d_{ffn}, d_{expert}$ 以及 $n_{layer}$.&lt;/p&gt;
&lt;p&gt;接下来，作者就探究了给定算力的情况下，最优的 MoE 配置，即&lt;/p&gt;
$$
(A^{opt}, G^{opt}, S^{opt}) = \arg\min_{(A,G,S)\in\mathcal{X}_{\mathrm{MoE}}}EL(\mathcal{X}_{\mathrm{MoE}}\mid \mathrm{Dense};C)
$$&lt;h2 id="scaling-law"&gt;&lt;a href="#scaling-law" class="header-anchor"&gt;&lt;/a&gt;Scaling Law
&lt;/h2&gt;&lt;p&gt;首先，坐着探究了最优的 activation ratio $A$, 即&lt;/p&gt;
$$
A^{opt} = \arg\min_{A}\mathcal{L}(A;C,M,G,S)
$$&lt;p&gt;拟合的结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/EL-impact-of-A.png"
width="1380"
height="487"
loading="lazy"
alt="Impact of the activation ratio"
class="gallery-image"
data-flex-grow="283"
data-flex-basis="680px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果表明：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;模型表现随激活比例降低 er 提高&lt;/li&gt;
&lt;li&gt;更系数的模型对于算力的提升其效率也提升更快&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;然后，作者探究了最优的 granularity ratio, 即&lt;/p&gt;
$$
G^{opt} = \arg\min_{G}\mathcal{L}(G;C,M,A,S)
$$&lt;p&gt;拟合的结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/EL-impact-of-G.png"
width="1376"
height="497"
loading="lazy"
alt="Impact of granularity"
class="gallery-image"
data-flex-grow="276"
data-flex-basis="664px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，无限制提升 granularity 并不会提高模型的表现。并且，不同的算力对应的最优 granularity 处于一个固定的范围&lt;/p&gt;
&lt;p&gt;接下来，作者探究了最优的 shared expert ratio, 即&lt;/p&gt;
$$
S^{opt} = \arg\min_{S}\mathcal{L}(S;C,M,A,G)
$$&lt;p&gt;拟合的结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/EL-impact-of-S.png"
width="1376"
height="487"
loading="lazy"
class="gallery-image"
data-flex-grow="282"
data-flex-basis="678px"
&gt;&lt;/p&gt;
&lt;p&gt;结果说明 shared expert 的比例也不是越多越好，其存在最优值。并且给定算力的情况下，非零最小值的 shared expert 表现最好。因此作者认为，一个 shared expert 的效果最好。&lt;/p&gt;
&lt;p&gt;作者还探究了其他可能的因素，结论如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;与 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v3/" target="_blank" rel="noopener"
&gt;DeepSeek-V3&lt;/a&gt; 一样，将 early layer 替换为 dense layer 可以避免 routing imbalance, 并且不会损害模型的表现&lt;/li&gt;
&lt;li&gt;attention 应该占 $30\%\sim40\%$ 左右的算力才能保证模型的表现和效率。进一步提升 attention 的算力占比虽然会提升表现但是会降低推理效率。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;通过前面的发现，作者将 shared expert 设置为 1 个，然后探究 EL 与 activation ratio $A$, granularity $G$, FLOPs $C$ 之间的关系。&lt;/p&gt;
&lt;p&gt;首先，作者分别假设 $EL$ 与 $A$, $G$, $C$ 之间存在如下关系：&lt;/p&gt;
$$
\begin{aligned}
\log EL_{C,G}(\hat{A}) &amp;= a_A\log\hat{A}, \text{ where }\frac{1}{\hat{A}}=\frac{1}{A+(1/A_{start}-1/A_{\max})^{-1}}+\frac{1}{A_{\max}}\\
\log EL_{C,A}(\hat{G}) &amp;= a_G+b_G(\log G(\log G+c_G))\\
\log EL_{A,G}(C) &amp;= a_C\log C+c_C
\end{aligned}
$$&lt;p&gt;拟合的结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/EL-scaling-A-G-C.png"
width="1380"
height="427"
loading="lazy"
alt="Scaling behavior of EL"
class="gallery-image"
data-flex-grow="323"
data-flex-basis="775px"
&gt;&lt;/p&gt;
&lt;p&gt;结果显示：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;提升算力以及降低 activation ratio 都可以提高 EL&lt;/li&gt;
&lt;li&gt;granularity 对 EL 的影响在不同算力的情况下都是一致的&lt;/li&gt;
&lt;li&gt;对于 MoE 模型，提升算力可以提高 EL&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;作者的结论为，activation ratio 是影响 MoE EL 的核心因素。并且随着算力的提升，MoE EL 会越来越明显。&lt;/p&gt;
&lt;p&gt;作者因此构建了一个统一的公式来统一三个因素&lt;/p&gt;
$$
EL(A,G,C) = \hat{A}^{\alpha+\gamma(\log G)^2+\beta \log G}
$$&lt;p&gt;其中 $\alpha=a+d\log C$ 代表了 EL 和 activation ratio 之间的关系。拟合出来的参数如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$\alpha$&lt;/th&gt;
&lt;th&gt;$d$&lt;/th&gt;
&lt;th&gt;$\gamma$&lt;/th&gt;
&lt;th&gt;$\beta$&lt;/th&gt;
&lt;th&gt;$A_{start}$&lt;/th&gt;
&lt;th&gt;$A_{\max}$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1.23&lt;/td&gt;
&lt;td&gt;-7.61e-2&lt;/td&gt;
&lt;td&gt;1.67e-2&lt;/td&gt;
&lt;td&gt;-1.17e-1&lt;/td&gt;
&lt;td&gt;1.63e-2&lt;/td&gt;
&lt;td&gt;5.28e+16&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;基于这个结果，作者发现在 1e22 FLOPs 的算力下，一个 activation ratio 为 $3.1\%$, granularity 为 $12$ 的 MoE 模型，其 EL 为 $7$.&lt;/p&gt;
&lt;h2 id="ling-mini-beta"&gt;&lt;a href="#ling-mini-beta" class="header-anchor"&gt;&lt;/a&gt;Ling-mini-beta
&lt;/h2&gt;&lt;p&gt;基于上一节的发现，作者构建了 Ling-mini-beta, 一个 17.5B 总参数，激活参数为 0.85B 的 MoE 模型。训练使用了 1T token, 模型参数如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;$n_{\text{layers}}$&lt;/th&gt;
&lt;th&gt;$d_{\text{model}}$&lt;/th&gt;
&lt;th&gt;$d_{\text{ffn}}$&lt;/th&gt;
&lt;th&gt;$d_{\text{expert}}$&lt;/th&gt;
&lt;th&gt;$n_{\text{heads}}$&lt;/th&gt;
&lt;th&gt;$n_{\text{kv\_head}}$&lt;/th&gt;
&lt;th&gt;$E$&lt;/th&gt;
&lt;th&gt;$E_a$&lt;/th&gt;
&lt;th&gt;$E_s$&lt;/th&gt;
&lt;th&gt;$N$&lt;/th&gt;
&lt;th&gt;$N_a$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dense 6.1B&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;4096&lt;/td&gt;
&lt;td&gt;14336&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;6.11B&lt;/td&gt;
&lt;td&gt;6.11B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ling-mini-beta (A0.8B)&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2048&lt;/td&gt;
&lt;td&gt;5120&lt;/td&gt;
&lt;td&gt;384&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;384&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;17.5B&lt;/td&gt;
&lt;td&gt;0.85B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;训练的损失变化情况如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-ling-mini-beta/EL-training-dynamics.png"
width="867"
height="596"
loading="lazy"
alt="Dynamic of training loss"
class="gallery-image"
data-flex-grow="145"
data-flex-basis="349px"
&gt;&lt;/p&gt;
&lt;p&gt;从图中我们可以看出，dense model 一开始的损失下降比较快，但是其最终表现不如 moe 模型。&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;在本文中，作者提出了 Efficiency Leverage, 一个衡量 MoE 模型相对于 dense 模型计算效率的 metric, 作者构建了针对 MoE 模型的 scaling law. scaling 揭示了两个主要影响 MoE 模型效率的因素：算力与激活参数比例。基于 scaling law, 作者构建了 Ling-mini-beta, 一个 17B-A0.8B 的 MoE 模型，其效率超过了对应 dense 模型的 7 倍。&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2507.17702" target="_blank" rel="noopener"
&gt;arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Load Balancing tutorial</title><link>https://jiangyigithub.github.io/ai.github.io/p/load-balancing-tutorial/</link><pubDate>Thu, 11 Dec 2025 16:10:08 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/load-balancing-tutorial/</guid><description>&lt;p&gt;我们在本文中探讨关于 load balancing loss 的定义，性质和推广&lt;/p&gt;
&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;我们在 &lt;a class="link" href="https://maosong.website/p/moe-tutorial/" target="_blank" rel="noopener"
&gt;MoE tutorial&lt;/a&gt; 中已经介绍了 MoE 模块，MoE 尽管可以在相同的算力下扩大模型的 size, 但是其问题在于训练时容易出现负载不均衡，也就是说只有少数几个专家被激活，其他专家处于闲置状态，从而导致模型性能下降&lt;/p&gt;
&lt;p&gt;为了解决这个问题，一个通用的做法是使用 load balancing loss. load balancing loss 可以有效实现负载均衡，让各个专家被激活的概率差不多。&lt;/p&gt;
&lt;p&gt;Load balancing loss 一共经历了如下几个阶段，发展路线如下图所示&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;flowchart&lt;/span&gt; &lt;span class="n"&gt;TD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Bengio&lt;/span&gt; &lt;span class="n"&gt;et&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Shazeer&lt;/span&gt; &lt;span class="n"&gt;et&lt;/span&gt; &lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2017&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GShard&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Switch&lt;/span&gt; &lt;span class="n"&gt;Transformer&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Loss&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt; &lt;span class="n"&gt;Balancing&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Global&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="n"&gt;balancing&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;h3 id="notation"&gt;&lt;a href="#notation" class="header-anchor"&gt;&lt;/a&gt;Notation
&lt;/h3&gt;&lt;p&gt;我们假设输入的 batch size 为 $B$, 总专家个数为 $N$, 激活专家个数为 $K$, $G_i(x_j)$ 代表 gating layer 预测的第 $i$ 个专家对于 token $x_j$ 的重要性程度。&lt;/p&gt;
&lt;h3 id="coefficient-of-variation"&gt;&lt;a href="#coefficient-of-variation" class="header-anchor"&gt;&lt;/a&gt;Coefficient of Variation
&lt;/h3&gt;&lt;p&gt;第一个阶段的 load balancing loss 针对广义的 MoE 模型。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bengio et.at 2015&lt;/strong&gt;
作者提出了一个让 batch 里每个专家平均激活概率分布更均匀的损失函数，其定义如下所示&lt;/p&gt;
$$
L_b = \sum_{i=1}^N\left\Vert \frac1B\sum_{j=1}^BG_i(x_j) - \frac1N\right\Vert_2
$$&lt;p&gt;其主要目标是让每个专家的平均激活概率接近 $1/N$, 即均匀分布.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Noam et.al 2017&lt;/strong&gt;
作者对 (Bengio et.at 2015) 进行了改进，提出了变异系数 $\mathrm{CV}(\cdot)$ 来保证负载均衡，其定义如下：&lt;/p&gt;
$$
L_{importance} = \mathrm{CV}(\mathrm{Importance}(X))^2
$$&lt;p&gt;其中&lt;/p&gt;
$$
\mathrm{Importance}_i(X) = \sum_{j=1}^B G_i(x_j),\ \mathrm{CV}(X)= \frac{\mathrm{var}[X]}{\mathbb{E}[X]},\ i=1,\dots,N
$$&lt;p&gt;注意到 $\mathrm{var}[X]\geq0$, 当且仅当 $X$ 为均匀分布时 $\mathrm{var}[X]=0$, 因此 important loss 可以让每个专家在一个 batch 中的激活的平均概率尽可能一致。&lt;/p&gt;
&lt;p&gt;但是平均概率一致不代表各个专家处理的 token 个数一致，比如一个专家可能处理比较少的 token, 但是每个 token 的权重都很大。因此，作者额外加入了 load balancing loss&lt;/p&gt;
$$
\mathcal{L}_{\mathrm{load}} = \mathrm{CV}(\mathrm{Load}(X))^2
$$&lt;p&gt;其中&lt;/p&gt;
$$
\begin{aligned}
\mathrm{Load}_i(X) &amp;= \mathrm{soft\_estimation}\left(\sum_{j=1}^B\mathbb{1}(\text{token }j \text{ selects expert }i)\right)\\
&amp;=\mathrm{soft\_estimation}\left(\sum_{j=1}^B\mathbb{1}\{i\in\mathrm{TopK}(\{G_i(x_j)\}_{i=1}^{E}, K)\}\right),\ i=1,\dots,N
\end{aligned}
$$&lt;p&gt;这里 $\mathrm{soft\_estimation}$ 是作者针对离散变量进行的一个光滑化处理，以方便反向传播。&lt;/p&gt;
&lt;h3 id="gshard"&gt;&lt;a href="#gshard" class="header-anchor"&gt;&lt;/a&gt;GShard
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt; 进一步对 (Noam et.al 2017) 提出的 loss 进行了简化，首先注意到 $\sum_{i=1}^N\mathrm{Load}_i(X)=BK$, 因此我们有&lt;/p&gt;
$$
\begin{aligned}
\mathcal{L}_{\mathrm{load}} &amp;= \mathrm{CV}(\mathrm{Load}(X))^2 \\
&amp;= \left(\frac{\mathrm{var}[\mathrm{Load}(X)]}{\mathbb{E}[\mathrm{Load}(X)]}\right)^2\\
&amp;= \left(C_1[\mathrm{Load}(X)]\right)^2\\
&amp;= C_1\mathbb{E}[\mathrm{Load}(X)^2]-C_2
\end{aligned}
$$&lt;p&gt;这里 $C_1,C_2$ 均为常数。GShard 并没有使用 soft estimation, 因此这里的 $\mathrm{Load}_i(X)$ 定义为&lt;/p&gt;
$$
\mathrm{Load}_i(X)=\sum_{j=1}^B\mathbb{1}(\text{token }j \text{ selects expert }i),\ i=1,\dots,N
$$&lt;p&gt;其代表了一个 batch 里专家 $i$ 被激活的次数，理想情况下，所有专家被激活的次数应该是一致的，从而我们就实现了负载均衡。&lt;/p&gt;
&lt;p&gt;但是现在的问题是，$\mathrm{Load}_i(X)$ 是一个离散变量，为了解决这个问题，作者使用了重要性来进行近似，即&lt;/p&gt;
$$
\begin{aligned}
\mathcal{L}_{\mathrm{load}} &amp;= \mathbb{E}[\mathrm{Load}(X)^2]\\
&amp;\approx \mathbb{E}[\mathrm{Load}(X)\cdot\mathrm{Importance}(X)]
\end{aligned}
$$&lt;h3 id="switch-transformer"&gt;&lt;a href="#switch-transformer" class="header-anchor"&gt;&lt;/a&gt;Switch Transformer
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 进一步对 &lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt; 提出 load balancing loss 进行了规范化，也是现在大部分 load balancing loss 使用的形式，其定义如下：&lt;/p&gt;
$$
\mathcal{L}_{\mathrm{load}} = \sum_{i=1}^N f_i P_i
$$&lt;p&gt;其中，&lt;/p&gt;
$$
f_i = \frac{1}{B}\mathrm{Load}_i(X)=\frac{1}{B}\sum_{j=1}^B\mathbb{1}(\text{token }j \text{ selects expert }i),\ i=1,\dots,N
$$&lt;p&gt;代表了分配给专家 $i$ 的 token 比例，&lt;/p&gt;
$$
P_i = \frac{1}{B}\mathrm{Importance}_i(X) = \frac{1}{B}\sum_{j=1}^B G_i(x_j)
$$&lt;p&gt;代表了这个 batch 里专家 $i$ 的平均激活概率。&lt;/p&gt;
&lt;p&gt;从而，这个形式和 GShard 的形式实际上是等价的：&lt;/p&gt;
$$
\mathcal{L}_{\mathrm{load}} = \sum_{i=1}^N f_i P_i = \mathbb{E}[\mathbf{f}\cdot \mathbf{P}] = N \mathbb{E}[\mathrm{Load}(X)\cdot\mathrm{Importance}(X)]
$$&lt;h2 id="analysis"&gt;&lt;a href="#analysis" class="header-anchor"&gt;&lt;/a&gt;Analysis
&lt;/h2&gt;&lt;p&gt;目前关于 load balancing loss 可以实现负载均衡的数学分析是比较少的。&lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 中进行了如下分析：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!quote]
The auxiliary loss of Equation 4 encourages uniform routing since it is minimized under a uniform distribution.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;但实际上，这个分析是错误的，Switch transformer 中定义的 load balancing loss 并不是在均匀分布时取最小值，而是取最大值。考虑如下情形，&lt;/p&gt;
$$
\mathbf{f}=[1,\dots,0],\ \mathbf{P}=[0,\dots,1]
$$&lt;p&gt;此时，我们有&lt;/p&gt;
$$
\mathbf{f}\cdot \mathbf{P} = 0\leq [1/N,\dots,1/N]\cdot [1/N,\dots,1/N] = 1/N.
$$&lt;p&gt;我找了很多资料，最后发现苏剑林老师在 &lt;a class="link" href="https://spaces.ac.cn/archives/10735" target="_blank" rel="noopener"
&gt;MoE环游记：2、不患寡而患不均&lt;/a&gt; 这篇 blog 中进行了分析。我这里基于苏剑林老师的 blog 进行了一下总结，推荐大家看苏剑林老师的原文。&lt;/p&gt;
&lt;p&gt;分析的核心思想就是，尽管 load balancing loss 目标函数没有意义，但是我们通过 straight-through estimator (STE)，就可以得到一个有意义的目标函数，其梯度与 load balancing loss 目标函数的梯度是一致的，这样 load balancing loss 目标函数就完成了其负载均衡的目标。&lt;/p&gt;
&lt;p&gt;注意到 load balancing loss 的最终目标是让每个专家处理的 token 个数尽可能一致，也就是&lt;/p&gt;
$$
\mathcal{L}_{\mathrm{load}} = \sum_{j=1}^B \left(f_i-\frac1B\right)^2
$$&lt;p&gt;但是 $f_i=\mathrm{Load}_i(X)$ 是一个离散变量不可导，因此，基于 STE, 我们可以将其改写为&lt;/p&gt;
$$
\mathcal{L}_{\mathrm{load}} = \sum_{j=1}^B \left(P_i+\mathrm{sg}[f_i-P_i]-\frac1B\right)^2
$$&lt;p&gt;其中 $\mathrm{sg}[\cdot]$ 满足：&lt;/p&gt;
$$
\mathrm{sg}[\cdot]=\begin{cases}
x, &amp;\text{forward pass}\\
0, &amp;\text{backward pass}
\end{cases}
$$&lt;p&gt;此时我们目标函数的梯度就变成了&lt;/p&gt;
$$
\begin{aligned}
\nabla_\theta\mathcal{L}_{\mathrm{load}} &amp;= \sum_{j=1}^B 2\nabla_\theta\left(P_i+\mathrm{sg}[f_i-P_i]-\frac1B\right)\left(P_i+\mathrm{sg}[f_i-P_i]-\frac1B\right)\\
&amp;= 2\sum_{j=1}^B\nabla_\theta P_i\left(f_i-\frac1B\right)\\
&amp;= 2\sum_{j=1}^B\nabla_\theta P_i\left(f_i-\frac1B\right)\\
&amp;= 2\nabla_\theta \left(\sum_{j=1}^Bf_iP_i\right)
\end{aligned}
$$&lt;p&gt;这样就对应上了我们之前的目标函数。总之，目标函数尽管本身没有意义，但是其对应的梯度却可以让模型实现负载均衡的目标。&lt;/p&gt;
&lt;h2 id="extension"&gt;&lt;a href="#extension" class="header-anchor"&gt;&lt;/a&gt;Extension
&lt;/h2&gt;&lt;h3 id="loss-free-load-balancing-strategy"&gt;&lt;a href="#loss-free-load-balancing-strategy" class="header-anchor"&gt;&lt;/a&gt;Loss Free Load Balancing Strategy
&lt;/h3&gt;&lt;p&gt;Loss-Free load balancing 是 DeepSeek 提出来的一个无需 load balancing loss 实现负载均衡的方法，其核心思想是 load balancing loss 会影响语言建模性能，因此在 $\mathrm{TopK}$ 操作时，作者加入一些扰动，从而让负载高的专家被选择的概率降低，让负载低的专家被选择的概率提高。&lt;/p&gt;
&lt;p&gt;具体细节见 &lt;a class="link" href="https://maosong.website/p/notes-on-loss-free-balancing/" target="_blank" rel="noopener"
&gt;Loss-Free Balancing&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="global-batch-load-balancing-loss-strategy"&gt;&lt;a href="#global-batch-load-balancing-loss-strategy" class="header-anchor"&gt;&lt;/a&gt;Global-batch Load Balancing Loss Strategy
&lt;/h3&gt;&lt;p&gt;Global-batch Load Balancing 是 Qwen 提出来的一个提高负载均衡的方法。其核心思想是，现有的 token choice 只是在 batch 层面达到负载均衡，这种局部均衡的性质可能会对模型的全局均衡性产生影响。因此，作者就预先在 global batch 层面对专家进行分配，从而提高专家在不同 domain 上的特化程度。&lt;/p&gt;
&lt;p&gt;具体细节见 &lt;a class="link" href="https://maosong.website/p/notes-on-global-batch-load-balancing/" target="_blank" rel="noopener"
&gt;Global-batch load balancing&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="experiments"&gt;&lt;a href="#experiments" class="header-anchor"&gt;&lt;/a&gt;Experiments
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-olmoe/" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt; 对比了加入 load balancing loss 之后模型的表现变化情况，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/load-balancing-tutorial/olmoe-load-balancing-loss.png"
width="1450"
height="532"
loading="lazy"
alt="Ablation study on load balancing loss"
class="gallery-image"
data-flex-grow="272"
data-flex-basis="654px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，加入 load balancing loss 之后，模型的表现均超过了不加时的表现。&lt;/p&gt;
&lt;p&gt;作者进一步分析了不同专家在加/不加 load balancing loss 时的激活情况，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/load-balancing-tutorial/ollmoe-load-balancing-expert-assignment.png"
width="1443"
height="566"
loading="lazy"
alt="visualization of expert assignment on load balancing"
class="gallery-image"
data-flex-grow="254"
data-flex-basis="611px"
&gt;&lt;/p&gt;
&lt;p&gt;结果显示，load balancing loss 确实可以让不同专家的激活概率大致相当。&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;在本文中，我们介绍了 load balancing loss 的演化，定义，分析以及相关的实验结果。&lt;/p&gt;
&lt;h2 id="reference"&gt;&lt;a href="#reference" class="header-anchor"&gt;&lt;/a&gt;Reference
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2006.16668" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://openreview.net/pdf/BNYMo3QRxh7PwR1riEDL.pdf" target="_blank" rel="noopener"
&gt;Bengio et.at 2015&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cs.toronto.edu/~hinton/absps/Outrageously.pdf" target="_blank" rel="noopener"
&gt;Noam et.al 2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/pdf/2408.15664" target="_blank" rel="noopener"
&gt;Loss free balancing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2501.11873" target="_blank" rel="noopener"
&gt;Global-batch load balancing loss&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://spaces.ac.cn/archives/10735" target="_blank" rel="noopener"
&gt;MoE环游记：2、不患寡而患不均&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on Global-batch load balancing</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-global-batch-load-balancing/</link><pubDate>Thu, 11 Dec 2025 16:09:34 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-global-batch-load-balancing/</guid><description>&lt;p&gt;Qwen 在 25 年 2 月提出了 global batching load balancing loss strategy, 其在 global level 上考虑每个专家的负载均衡，从而提高模型的表现&lt;/p&gt;
&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;实现 MoE 模型负载均衡的原因有两点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Effectiveness: 通过负载均衡才能更高效地利用各个专家&lt;/li&gt;
&lt;li&gt;Efficiency: 一般需要使用 expert parallel 来部署 MoE 模型，不均衡的负载会大幅度降低前向过程&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;已有的框架如 DeepSpeed, Megablocks 和 Megatron-Core 都是在 micro-batch level 上计算负载均衡损失的，但是，一个 micro-batch 通常只包含少数序列，因此 load balancing loss 就要求各个专家在每个序列上均匀分布。&lt;/p&gt;
&lt;p&gt;针对这个问题，作者在本文中提出的解决方法是在 global-batch 层面考虑负载均衡，&lt;/p&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;p&gt;MoE 模型定义如下&lt;/p&gt;
$$
y = \sum_{i\in N_E,g_i\in\mathrm{TopK}(g)}g_i(x)E_i(x)
$$&lt;p&gt;其中 $E_i$ 是对应的专家, $g_i$ 是对应的权重&lt;/p&gt;
&lt;p&gt;Load balancing loss 定义如下&lt;/p&gt;
$$
\mathrm{LBL} = N_E\sum_{i=1}^{N_E}f_iP_i
$$&lt;p&gt;一般来说，MoE 模型训练时会使用 expert parallel 策略，此时 load balancing loss 修改为&lt;/p&gt;
$$
\mathrm{LBL}_{\mathrm{micro}}= \frac{1}{N_P}\sum_{j=1}^{N_P}\left(N_E\sum_{i=1}^{N_E}f_i^hP_i^j\right)
$$&lt;p&gt;其中 $N_P$ 是 parallel groups 的个数。在这种情况下，模型需要再每个 parallel group 中实现负载均衡。但是某一个 mircro-batch 里可能只包含某一个 domain 的序列，因此各个专家被强制要求在每一个 domain 中也均衡分布。作者认为，这种方式会限制专家的能力，进而影响模型的表现。&lt;/p&gt;
&lt;p&gt;作者的解决方法在于，获取每个 parallel group 的 $f_i$ 然后求 global-batch 的 $\bar{f}_i$.&lt;/p&gt;
$$
\mathrm{LBL}_{\mathrm{global}}=N_E\sum_{i=1}^{N_E}\bar{f}_i\bar{P}_i=N_E\sum_{i=1}^{N_E}\bar{f}_i\left(\frac{1}{N_P}\sum_{j=1}^{N_P}P_j\right) = \frac{1}{N_P}\sum_{j=1}^{N_P}\left(N_E\sum_{i=1}^{N_E}\bar{f}_iP_i^j\right)
$$&lt;p&gt;实际中，由于计算节点数量有限，micro-batch size 之和可能会小于 global-batch size, 因此我们会使用 gradient accumulation. 在这种情况下， 作者使用了一个 buffer 来保存多个 micro-batch 的专家选择次数，最终算法实现过程如下所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-global-batch-load-balancing/Global-batch-LBL-approximation.png"
width="891"
height="339"
loading="lazy"
alt="Approximate Global-Batch LBL"
class="gallery-image"
data-flex-grow="262"
data-flex-basis="630px"
&gt;&lt;/p&gt;
&lt;h2 id="experiments"&gt;&lt;a href="#experiments" class="header-anchor"&gt;&lt;/a&gt;Experiments
&lt;/h2&gt;&lt;p&gt;作者使用了不同大小的模型来进行实验，作者用 &lt;strong&gt;Balance BSZ&lt;/strong&gt; 来表现计算 expert selection frequency 时的 token 数，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-global-batch-load-balancing/Global-batch-LBL-performance.png"
width="954"
height="598"
loading="lazy"
alt="Performance of different balance methods and Balance BSZ"
class="gallery-image"
data-flex-grow="159"
data-flex-basis="382px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，global LBL 可以提高模型的表现，并且，当 Balance BSZ 增加时，模型的表现也会提升。作者发现对于 &lt;a class="link" href="https://maosong.website/p/notes-on-loss-free-balancing/" target="_blank" rel="noopener"
&gt;Loss-Free Balancing&lt;/a&gt; 来说，使用 global batch 的效果也更好。&lt;/p&gt;
&lt;p&gt;作者还发现，global LBL 会提高专家的特化程度，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-global-batch-load-balancing/Global-batch-LBL-specialization.png"
width="1221"
height="571"
loading="lazy"
alt="The impact of the Balance BSZ"
class="gallery-image"
data-flex-grow="213"
data-flex-basis="513px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，使用默认的 LBL loss, 各个专家的特化程度很低，而使用本文的 global LBL 之后，专家的特化程度有了大幅度的提高。&lt;/p&gt;
&lt;p&gt;作者还进一步发现，随着 Balance BSZ 的提高，模型表现也持续提升，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-global-batch-load-balancing/Global-batch-LBL-balance-BSZ.png"
width="613"
height="455"
loading="lazy"
alt="Performance against Balance BSZ"
class="gallery-image"
data-flex-grow="134"
data-flex-basis="323px"
&gt;&lt;/p&gt;
&lt;p&gt;作者认为，synchronization 和 buffer 机制相比于 micro-batch 来说可以带来大幅度提升。&lt;/p&gt;
&lt;h2 id="analysis"&gt;&lt;a href="#analysis" class="header-anchor"&gt;&lt;/a&gt;Analysis
&lt;/h2&gt;&lt;p&gt;首先，为了分析 global batch LBL 优于 Micro batch 的关键原因，作者先同步所有 group 的矩阵 $G$, 然后再从全局 token 中随机选一批，用这批 token 计算专家选择频率。通过这个方法，我们可以保证 token 数量与 micro-batch 一致，但是分布于 Global-batch 一致。实验结果发现，这种方法的表现优于 micro-batch LBL, 说明 global batch LBL 的优势在于 Token 分布更全局，而不是 token 数量更多。&lt;/p&gt;
&lt;p&gt;作者还分析了 global batch LBL 和 micro batch LBL 两种模式，作者认为前者是后者的一个宽松版约束，作者发现从后者切换为前者之后，模型的表现可以得到进一步提升，但是其表现仍然不如一开始就使用 global batch LBL 更好。作者分析原因认为，这是因为 expert 收敛速度比较快。&lt;/p&gt;
&lt;p&gt;作者进一步通过降低 micro batch LBL 权重来探究是否可以达到同样的表现，结果发现适度江都权重确实可以提高模型的表现，但是降低太多会损害模型的表现，即此时出现了负载不均衡的现象&lt;/p&gt;
&lt;p&gt;作者对比了 global batch LBL 和 micro batch LBL 效率发现，前者比后者慢 $2\%$ 左右，这个差距几乎可以忽略不计&lt;/p&gt;
&lt;p&gt;作者进一步分析了不同 balancing 方式的专家特化程度，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-global-batch-load-balancing/Global-batch-LBL-balance-topK-score.png"
width="1269"
height="656"
loading="lazy"
alt="The topK score sums across layers"
class="gallery-image"
data-flex-grow="193"
data-flex-basis="464px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果发现：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用 global batch LBL 之后，topK sum 明显变大，这说明 routing 和 language modeling 任务对齐地更好&lt;/li&gt;
&lt;li&gt;global batch LBL 的专家在不同任务上的特化程度更明显&lt;/li&gt;
&lt;li&gt;micro batch LBL 的 topK sum 比较小&lt;/li&gt;
&lt;li&gt;Loss-free balancing 的 topK sum 介于 micro batch LBL 和 global batch LBL 之间&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者在本文中提出了 global LBL 来在全局为负载均衡提供指导，结果发现通过在更大的范围进行负载均衡的计算，我们可以有效提高专家的特化程度以及提高模型在下游任务上的表现&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2501.11873" target="_blank" rel="noopener"
&gt;Arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on DeepSeek-V3</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/</link><pubDate>Mon, 08 Dec 2025 11:14:45 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/</guid><description>&lt;p&gt;DeepSeek 在 24 年 11 月发布了 DeepSeek-V3, 一个仅花费 2.8M H800 hours 的大语言模型，且在各个 benchmark 上达到了 SOTA 表现&lt;/p&gt;
&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;作者在本文中提出了 DeepSeek-V3, 一个 671B-A37B 的 MoE 大语言模型。&lt;/p&gt;
&lt;p&gt;在训练目标和架构上，作者做了如下改进：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;efficiency inference: 采用了 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v2/" target="_blank" rel="noopener"
&gt;DeepSeek-V2&lt;/a&gt; 提出的 &lt;a class="link" href="https://maosong.website/p/notes-on-mla/" target="_blank" rel="noopener"
&gt;MLA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;cost-effective training: 采用了 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 提出了 MoE 架构&lt;/li&gt;
&lt;li&gt;auxiliary-loss-free strategy: 采用了 &lt;a class="link" href="https://maosong.website/p/notes-on-loss-free-balancing/" target="_blank" rel="noopener"
&gt;Loss-Free Balancing&lt;/a&gt; 提出的 loss balancing 策略&lt;/li&gt;
&lt;li&gt;multi-token prediction: 采用了 MTP 的训练目标来提升模型的表现&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在训练上，作者做了如下改进：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用了 FP8 混合精度进行训练并验证了其在大规模模型上的有效性&lt;/li&gt;
&lt;li&gt;作者构建了 DualPipe 算法用于高效的 pipeline parallelism&lt;/li&gt;
&lt;li&gt;构建了 cross-node all-to-all communication kernel 来高效使用 InfiniBand 以及 NVLink bandwidth&lt;/li&gt;
&lt;li&gt;优化了 memory footprint, 来避免使用 tensor parallelism&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;预训练阶段，DeepSeek-V3 使用了&lt;strong&gt;14.8T&lt;/strong&gt; token. 在 mid-training 阶段，作者将模型的上下文长度由 8K 扩展到 32K, 再扩展到 128K.&lt;/p&gt;
&lt;p&gt;后训练阶段，作者使用了 SFT 和 RL 两个阶段来提高模型的表现，作者还对 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-r1/" target="_blank" rel="noopener"
&gt;DeepSeek-R1&lt;/a&gt; 进行蒸馏来提高模型的 reasoning 能力&lt;/p&gt;
&lt;h2 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h2&gt;&lt;h3 id="basic-architecture"&gt;&lt;a href="#basic-architecture" class="header-anchor"&gt;&lt;/a&gt;Basic Architecture
&lt;/h3&gt;&lt;p&gt;DeepSeek-V3 的架构与 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v2/" target="_blank" rel="noopener"
&gt;DeepSeek-V2&lt;/a&gt; 的架构一致，如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V2-architecture.png"
width="1324"
height="1064"
loading="lazy"
alt="Architecture of DeepSeek-V2"
class="gallery-image"
data-flex-grow="124"
data-flex-basis="298px"
&gt;&lt;/p&gt;
&lt;p&gt;MLA 的介绍见 &lt;a class="link" href="https://maosong.website/p/notes-on-mla/" target="_blank" rel="noopener"
&gt;MLA&lt;/a&gt;, MoE 架构的介绍见 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt;. DeepSeek-V3 在 DeepSeekMoE 的基础上做了两点改变：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;受 &lt;a class="link" href="https://maosong.website/p/notes-on-loss-free-balancing/" target="_blank" rel="noopener"
&gt;Loss-Free Balancing&lt;/a&gt; 启发，作者使用了 sigmoid fu nction 来计算 affinity score&lt;/li&gt;
&lt;li&gt;对于 selected affinity score 应用了 normalization&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 的基础上，作者使用了 &lt;a class="link" href="https://maosong.website/p/notes-on-loss-free-balancing/" target="_blank" rel="noopener"
&gt;Loss-Free Balancing&lt;/a&gt;. 其表达式如下&lt;/p&gt;
$$
g_{i,t} = \begin{cases}
s_{i,t}, &amp; s_{i,t}+b_i\in\mathrm{Topk}(\{s_{i,j}+b_j\mid 1\leq j\leq N\}, K)\\
0, &amp;\text{otherwise}
\end{cases}
$$&lt;p&gt;其中 $b_i$ 仅影响 routing, 训练时，如果对应的 expert 负载不均衡，则对 $b_i$ 进行更新，更新方式为增加/减少 $\gamma$, 这里 $\gamma$ 是一个超参数&lt;/p&gt;
&lt;p&gt;为了提高 routing 在 sequence 层面的负载均衡，作者还是用了一个 complementary sequence-wise balance loss:&lt;/p&gt;
$$
\begin{aligned}
\mathcal{L}_{\mathrm{Bal}} &amp;= \alpha\sum_{i=1}^{N_r} f_iP_i\\
f_i &amp;= \frac{}{}\sum_{t=1}^T\mathbb{1}(s_{i,t}\in\mathrm{TopK}(\{s_{j,t}\mid 1\leq j \leq N_r\}, K_r))\\
s_{i,y}' &amp;= \frac{s_{i,t}}{\sum_{j=1}^{N_r}s_{j,t}}\\
P_i &amp;= \frac1T\sum_{t=1}^T s_{i,t}'
\end{aligned}
$$&lt;p&gt;其中 $\alpha$ 是 balance factor, 为超参数，$T$ 是 sequence length, 加入这个损失后，每个 sequence 上的负载会变得更加均衡&lt;/p&gt;
&lt;p&gt;与 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 一样，作者也在 node 层面实现负载均衡，具体做法就是，根据 node 中所包含 expert 的 affinity score 之和来选取最高的 $M$ 个 nodes, 这样就可以进一步提高 computation 和 communication 之间的 overlap.&lt;/p&gt;
&lt;p&gt;由于 DeepSeek-V3 负载均衡比较好，因此作者使用了 no token-dropping strategy.&lt;/p&gt;
&lt;h3 id="mtp"&gt;&lt;a href="#mtp" class="header-anchor"&gt;&lt;/a&gt;MTP
&lt;/h3&gt;&lt;p&gt;受 MTP 启发，DeepSeek-V3 也构建了 MTP 模块，作者认为 MTP 模块有两个优势：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;MTP objective 提供了更多的学习信号，进而提高了数据使用效率&lt;/li&gt;
&lt;li&gt;MTP 可以让模型更好预测未来的 token&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;与 MTP 不同，DeepSeek-V3 【todo】, DeepSeek-V3 所使用的 MTP 模块架构图如下所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-MTP.png"
width="1203"
height="536"
loading="lazy"
alt="Illustration of MTP"
class="gallery-image"
data-flex-grow="224"
data-flex-basis="538px"
&gt;&lt;/p&gt;
&lt;p&gt;MTP 模块使用了 $D$ sequential modules 来预测未来的 $D$ 个 token. 其中，第 $k$ 个 MTP 模块包含一个共享的 embedding layer $\mathrm{Emb}(\cdot)$ , 一个共享的 output head $\mathrm{OutHead}(\cdot)$, 一个 transformer block $\mathrm{TRM}_k(\cdot)$ 和一个 projection matrix $M_k\in\mathbb{R}^{d\times 2d}$.&lt;/p&gt;
&lt;p&gt;对于第 $i$ 个 token 以及第 $k$ 个 MTP 模块，作者首先将第 $k-1$ 个 MTP 模块的第 $i$ 个 token 的 hidden states $h_i^{k-1}\in\mathbb{R}^d$ 和第 $i+k$ 个 token 的 embedding $\mathrm{Emb}(t_{i+1})\in\mathbb{R}^d$ 联合在一起&lt;/p&gt;
$$
h_i'^{k}=M_k[\mathrm{RMSNorm(h_{i}^{k-1});\mathrm{RMSNorm(\mathrm{Emb}(t_{i+k}))}}]
$$&lt;p&gt;其中 $[\cdot;\cdot]$ 代表 concatenation 操作。当 $k=1$ 时，$h_{i}^{k-1}$ 就代表了 main model 的输出。每个 MTP 模块的 embedding layer 和 main model 的 embedding layer 是共享的，接下来， $h_i'^k$ 作为第 $k$ 个 MTP 模块 transformer block 的输入，得到&lt;/p&gt;
$$
h_{i}^k = \mathrm{TRM}_k(h_{i}'^l)
$$&lt;p&gt;最后，共享的 output head 输出对应的概率分布：&lt;/p&gt;
$$
P_{i+k+1}^k = \mathrm{OutHead}(h_i^k)
$$&lt;p&gt;这里的 $\mathrm{OutHead}(\cdot)$ 的权重与 main model 也是共享的。作者这里提到，所使用的思想与 EAGLE 是类似的，但是不同的地方在于，EAGLE 主要是用于 speculative decoding, 而 MTP 主要用于提升训练。&lt;/p&gt;
&lt;p&gt;MTP 的训练目标为未来 $T-k-1$ 个 token 的 cross-entropy loss:&lt;/p&gt;
$$
\mathcal{L}_{\mathrm{MTP}}^k = \mathrm{CrossEntropy}(P_{2+k:T+1}^k,t_{2+k:T+1}) = -\frac1T\sum_{t=k+2}^{T+1}\log P_i^k[t_i],
$$&lt;p&gt;其中 $T$ 是 sequence length, $t_i$ 是第 $i$ 个位置对应的 ground truth token, $P_i^k[t_i]$ 代表低 $k$ 个 MTP 模块给出的 $t_i$ 的预测概率。最后，作者对所有的 MTP loss 进行求和，得到&lt;/p&gt;
$$
\mathcal{L}_{\mathrm{MTP}} = \frac{\lambda}{D}\sum_{k=1}^D \mathcal{L}_{\mathrm{MTP}}^k.
$$&lt;h2 id="infra"&gt;&lt;a href="#infra" class="header-anchor"&gt;&lt;/a&gt;Infra
&lt;/h2&gt;&lt;p&gt;DeepSeek-V3 训练使用了 2048 张 H800, 每个 node 包含 8 张 GPU, node 内部使用 NVLink 和 NVSwitch 进行连接，node 之间使用 InfiniBand 进行连接&lt;/p&gt;
&lt;p&gt;与之前的 DeepSeek 系列相同，DeepSeek-V3 也是用了 HAI-LLM 框架来支持训练。训练时，DeepSeek-V3 使用了 16-way PP, 64-way EP (spanning 8 nodes, &lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt;) 以及 ZeRO-1 DP.&lt;/p&gt;
&lt;p&gt;作者主要进行了三点优化：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;构建了 DualPipe 用于高效 pipeline parallelism&lt;/li&gt;
&lt;li&gt;构建了 cross-node all-to-all communication kernels 来高效利用 IB 以及 NVLink bandwidth&lt;/li&gt;
&lt;li&gt;优化了训练时的 memory footprint, 使得训练时不再依赖 TP&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="training-framework"&gt;&lt;a href="#training-framework" class="header-anchor"&gt;&lt;/a&gt;Training Framework
&lt;/h3&gt;&lt;h4 id="dualpipe"&gt;&lt;a href="#dualpipe" class="header-anchor"&gt;&lt;/a&gt;DualPipe
&lt;/h4&gt;&lt;p&gt;DeepSeek-V3 中，由于 cross-node EP, computation-to-communication ratio 近似为 1:1, 为了解决这个问题，作者提出了 DualPipe. DualPipe 的核心思想是将 forward 和 backward 过程中的 computation 以及 communication 进行重叠。与 ZeroBubble 类似，作者将每个 chunk 分为四个部分：attention, all-to-all dispatch, MLP 以及 all-to-all combine. 对于 attention 和 MLP, 作者还进一步将 backward 拆分为 针对权重和输入的 backward. 其示意图如下所示，这里橙色部分代表 forward, 绿色代表了针对输入的 backward, 蓝色代表了针对权重的 backward&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-overlapping-strategy.png"
width="1101"
height="125"
loading="lazy"
alt="Overlapping stategy of DeepSeek-V3"
class="gallery-image"
data-flex-grow="880"
data-flex-basis="2113px"
&gt;&lt;/p&gt;
&lt;p&gt;示意图里包含两个 block, 我们记为 block1, block2, 前向计算过程为&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dispatch(F, block1) -&amp;gt; MLP(F, block1) -&amp;gt; combine(F, block1) -&amp;gt; attention(F, block2)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中，&lt;code&gt;dispatch(F, block1)&lt;/code&gt; 与 MLP 的反向传播 &lt;code&gt;MLP(B, block1)&lt;/code&gt; 计算重叠, &lt;code&gt;MLP(F, block1)&lt;/code&gt; 与 MLP 反向传播的 dispatch &lt;code&gt;dispatch(B, block1)&lt;/code&gt; 通信重叠，&lt;code&gt;combine(F, block1)&lt;/code&gt; 与 attention 反向传播的 &lt;code&gt;attention(B, block2)&lt;/code&gt; 重叠，&lt;code&gt;attention(F, block2)&lt;/code&gt; 与反向传播的 combine &lt;code&gt;combine(block2)&lt;/code&gt; 重叠。下面是一个具体的例子&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-DualPipe-scheduling.png"
width="1212"
height="210"
loading="lazy"
alt="DualPipe scheduling"
class="gallery-image"
data-flex-grow="577"
data-flex-basis="1385px"
&gt;&lt;/p&gt;
&lt;p&gt;作者进一步对比了 DualPipe, 1F1B 和 ZeroBubble, 结果如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Bubble&lt;/th&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Activation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1F1B&lt;/td&gt;
&lt;td&gt;$(PP-1)(F+B)$&lt;/td&gt;
&lt;td&gt;$1\times$&lt;/td&gt;
&lt;td&gt;$PP$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZB1P&lt;/td&gt;
&lt;td&gt;$(PP-1)(F+B-2W)$&lt;/td&gt;
&lt;td&gt;$1\times$&lt;/td&gt;
&lt;td&gt;$PP$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DualPipe (Ours)&lt;/td&gt;
&lt;td&gt;$(\frac{PP}{2}-1)(F\&amp;B+B-3W)$&lt;/td&gt;
&lt;td&gt;$2\times$&lt;/td&gt;
&lt;td&gt;$PP+1$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这里 $F$ 是 forward chunk 的执行时间，$B$ 是 backward chunk 执行的时间，$W$ 是一个 chunk &amp;ldquo;backward for weights&amp;rdquo; 的执行时间，$F\&amp;B$ 是一个 chunk 前向反向传播重叠的时间。可以看到，DualPipe 只使用了额外的 $1/PP$ 倍的 peak activation memory, 就大幅度降低了 bubble 时间&lt;/p&gt;
&lt;h4 id="cross-node-all-to-all-communication"&gt;&lt;a href="#cross-node-all-to-all-communication" class="header-anchor"&gt;&lt;/a&gt;Cross-node All-to-all Communication
&lt;/h4&gt;&lt;p&gt;作者针对 DualPipe 构建了 cross-node all-to-all communication kernels 来提高通信效率。&lt;/p&gt;
&lt;p&gt;作者提到，跨节点通信使用的是 IB, 节点内部通信使用的是 NVLink， 通信方式如下图所示。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/GPU-communication-pattern.png"
width="1360"
height="749"
loading="lazy"
alt="Communication of GPU"
class="gallery-image"
data-flex-grow="181"
data-flex-basis="435px"
&gt;&lt;/p&gt;
&lt;p&gt;对于 H800 来说,NVLink 的带宽为 160GB/s, IB 的带宽为 50GB/s, 因此 NVLInk 的通信效率是 IB 的 3.2 倍，即节点内部通信效率高于节点之间的通信效率。为了提高通信效率，作者限制每个 token 只能被分发到至多 4 个节点上（&lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v2/" target="_blank" rel="noopener"
&gt;DeepSeek-V2&lt;/a&gt; 里提到的 device limited routing）。其具体通信方式为想传输到目标 node index 相同的 rank 上，然后再通过节点内部通信传输到目标的 rank 上。通过这种方式，我们可以让节点间通信与节点内部通信进行重叠，从而每个 token 可以从一个节点上选取 3.2 个专家，这样 DeepSeek-V3 可以在不损失效率的情况下最高选取 $13$ 个专家。&lt;/p&gt;
&lt;p&gt;作者进一步采用了 warp specialization 技巧来将 20 个 SM 划分为 10 个通信 channel. 作者分别针对 dispatching 和 combing 阶段使用了不同数量的 warps.&lt;/p&gt;
&lt;h4 id="memory-saving"&gt;&lt;a href="#memory-saving" class="header-anchor"&gt;&lt;/a&gt;Memory saving
&lt;/h4&gt;&lt;p&gt;作者使用了如下技巧来减少内存访问：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Recomputation of RMSNorm and MLA Up-Projection. 在 backward 过程中重新计算 RMSNorm operation 以及 MLA up projection 来避免存储器对应的输出&lt;/li&gt;
&lt;li&gt;Exponential Moving Average in CPU. 作者将 EMA 参数保存在 CPU 中，然后进行异步更新来进一步减少内存访问&lt;/li&gt;
&lt;li&gt;Shared Embedding and Output Head for Multi-Token Prediction. 作者将 embedding layer 和 output head 放在一个 PP rank 上，这样就可以提高 MTP 的内存访问效率&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="fp8-training"&gt;&lt;a href="#fp8-training" class="header-anchor"&gt;&lt;/a&gt;FP8 Training
&lt;/h3&gt;&lt;p&gt;作者提出了一个基于 FP8 的混合精度训练框架。作者提出了两个改进方案：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;分组量化，将 tensor 按照 tile 分组或者按照 block 分组来分组量化，这样就避免了全局量化的精度损失&lt;/li&gt;
&lt;li&gt;高精度累加，作者在乘法计算时，使用了 FP8 格式，然后在累加阶段，使用了更高精度的格式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;为了进一步减少内存和通信开销，对于 activation 的 cache 以及 dispatch, 作者使用了 FP8 数据格式，然后对于优化器状态，作者使用了 BF16 数据格式。下面是对上面改进的具体说明。&lt;/p&gt;
&lt;h4 id="mixed-precision-training"&gt;&lt;a href="#mixed-precision-training" class="header-anchor"&gt;&lt;/a&gt;Mixed Precision Training
&lt;/h4&gt;&lt;p&gt;作者在本文中提出了使用 FP8 混合精度进行预训练，作者参考了 low precision training 构建 FP8 训练框架，即计算量高的使用 FP8 精度，计算量低的使用原本的数据精度, 框架如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-mixed-precision.png"
width="1210"
height="365"
loading="lazy"
alt="Mix-precision training of DeepSeek-V3"
class="gallery-image"
data-flex-grow="331"
data-flex-basis="795px"
&gt;&lt;/p&gt;
&lt;p&gt;其中各个模块使用的精度如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Precision&lt;/th&gt;
&lt;th&gt;Modules&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FP8&lt;/td&gt;
&lt;td&gt;Linear (Fprop, Dgrad, Wgrad)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;higher precision&lt;/td&gt;
&lt;td&gt;- embedding&lt;br&gt;- output head&lt;br&gt;- Moe gating&lt;br&gt;- normalization&lt;br&gt;- attention operator&lt;br&gt;- master weights&lt;br&gt;- weight gradients&lt;br&gt;- optimizer states&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="enhancing-low-precision-training-accuracy"&gt;&lt;a href="#enhancing-low-precision-training-accuracy" class="header-anchor"&gt;&lt;/a&gt;Enhancing Low-precision Training Accuracy
&lt;/h4&gt;&lt;p&gt;作者介绍了几个策略用于提高 FP8 混合精度训练的表现：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-quantization.png"
width="1162"
height="588"
loading="lazy"
alt="Quantization of DeepSeek-V3"
class="gallery-image"
data-flex-grow="197"
data-flex-basis="474px"
&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;fine-grained quantization: 对于激活值，作者将 tensor 分割为 $1\times 128$ 大小的 groups, 然后每个 group 内部进行 quantization; 对于权重，作者将其分割为 $128\times 128$ 大小的 groups, 然后进行 quantization, 这样可以降低 quantization error, 如上图左图所示&lt;/li&gt;
&lt;li&gt;increasing accumulation precision: 低精度训练会带来 underflow 的问题，而 FP8 GEMM 累加仅能保留约 14bit 精度，远低于 FP32 的 32bit 精度。为了解决这个问题，作者采用了 Tensor Core 不分累加 +CUDA core 高精度聚合的协同策略。即在 Tensor Core 上执行 MMA 指令时，先按照 14bit 精度对 $N_C$ 个元素进行累加，当达到 $N_C$ 时，作者将结果复制到 CUDA core 的 FP32 寄存器中，在 FP32 精度下完成累加。过程如上图右图所示&lt;/li&gt;
&lt;li&gt;Mantissa over exponents. 与之前的工作不同，作者使用了 E4M3 的数据格式来达到更高的精度&lt;/li&gt;
&lt;li&gt;Online Quantization. 为了降低 quantization 的误差，作者实时计算了 activation block 以及 weight block 的最大绝对值来导出 scaling factor 并量化为 FP8 精度&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="low-precision-storage-and-communication"&gt;&lt;a href="#low-precision-storage-and-communication" class="header-anchor"&gt;&lt;/a&gt;Low Precision Storage and Communication
&lt;/h4&gt;&lt;p&gt;作者通过压缩 cached activation 和 optimizer states 来进一步减少内存访问以及通信访问次数&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Low-precision optimizer states: 对于 optimizer states, 作者使用了 BF16 数据格式来保存 &lt;a class="link" href="https://maosong.website/p/notes-on-adamw/" target="_blank" rel="noopener"
&gt;AdamW&lt;/a&gt; 的优化器的一阶和二阶动量，但是对于 master weight 和 gradients 作者仍然使用了 FP32 来保证训练的数值稳定性&lt;/li&gt;
&lt;li&gt;Low-Precision Activation: 对于 linear operator, 作者将其 cache activation 使用 FP8 格式进行存储，对于 attention 的输出，作者使用了 E5M6 数据格式来存储 activations, 这些 activations 的 tile size 为 $1\times 128$, 作者还是用了 2 的幂次作为 scale factor 来减少 quantizationerror; 对于 SwiGLU, 作者将其输入也保存为 FP8 的数据格式来降低内存消耗&lt;/li&gt;
&lt;li&gt;Low-Precision Communication: 在 MoE up-projection 之前，作者将 attention 的输出量化为 FP8 数据格式再执行 dispatch 操作，这样可以降低通信开销。在反向传播的时候同理，先进行 FP8 量化，然后再进行反向 dispatch. 对于 combine 阶段，为了避免精度损失，作者还是使用了 BF16 数据格式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;作者对比了 FP8 和 BF16 精度训练，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-FP8-performance.png"
width="1056"
height="305"
loading="lazy"
alt="FP8 v.s. BF16"
class="gallery-image"
data-flex-grow="346"
data-flex-basis="830px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，FP8 混合精度训练的损失降低不足 $0.25\%$.&lt;/p&gt;
&lt;h3 id="inference-and-deployment"&gt;&lt;a href="#inference-and-deployment" class="header-anchor"&gt;&lt;/a&gt;Inference and Deployment
&lt;/h3&gt;&lt;p&gt;作者在 H800 集群上部署 DeepSeek-V3, 作者分别针对 prefilling 和 decoding 两个阶段进行了优化&lt;/p&gt;
&lt;h4 id="prefilling"&gt;&lt;a href="#prefilling" class="header-anchor"&gt;&lt;/a&gt;Prefilling
&lt;/h4&gt;&lt;p&gt;prefilling 阶段在 4 节点 32 GPU 上进行，并行策略如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模块&lt;/th&gt;
&lt;th&gt;并行策略&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dense MLP&lt;/td&gt;
&lt;td&gt;1-wat TP&lt;/td&gt;
&lt;td&gt;减少 TP 通信&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attention&lt;/td&gt;
&lt;td&gt;4-way TP, SP, 8-way DP&lt;/td&gt;
&lt;td&gt;SP 用于长文本处理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MoE&lt;/td&gt;
&lt;td&gt;32-way EP&lt;/td&gt;
&lt;td&gt;每个 GPU 包含 8 个专家&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;为了实现负载均衡，作者提出了&lt;strong&gt;redundant experts&lt;/strong&gt;的策略，具体就是将负载比较高的专家进行复制。模型会周期性进行统计，然后计算出负载比较高的专家，接下来每个 GPU 除了原来的 8 个专家之外，还会 host 一个额外的 redundant expert.&lt;/p&gt;
&lt;p&gt;为了提高 throughput, 作者同时处理两个 micro-batch, 来重叠 attention, MoE 和 dispatch, combine 通信，如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-prefilling-overlap.png"
width="661"
height="316"
loading="lazy"
alt="Prefiling overlap of DeepSeek-V3"
class="gallery-image"
data-flex-grow="209"
data-flex-basis="502px"
&gt;&lt;/p&gt;
&lt;p&gt;作者还探索了 dynamic redundancy 策略，即每个 GPU host 更多的专家（比如 16 个）然后 inference 的每一步仅激活其中的 9 个，在进行 all-to-all operation 时，作者首先进行 global optimal routing 来计算最合适的专家。作者认为 prefilling 计算量很大，因此 routing 的计算量可以忽略不计&lt;/p&gt;
&lt;h4 id="decoding"&gt;&lt;a href="#decoding" class="header-anchor"&gt;&lt;/a&gt;Decoding
&lt;/h4&gt;&lt;p&gt;在 decoding 阶段，作者在 40 个节点 320 GPU 上进行部署，并行策略如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模块&lt;/th&gt;
&lt;th&gt;并行策略&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Attention&lt;/td&gt;
&lt;td&gt;4-way TP, SP, 80-way DP&lt;/td&gt;
&lt;td&gt;SP 用于长文本处理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MoE&lt;/td&gt;
&lt;td&gt;320-way EP&lt;/td&gt;
&lt;td&gt;每个 GPU 包含 8 个专家&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这个阶段，每个 GPU 只 host 一个专家，64 个 GPU 负责 host redundant expert 以及 shared expert. 作者通过在 IB 上直接进行 P2P 的传输来降低通信的开销，作者还是用了 IBGDA 来进一步最小化 latency 以及提高通信效率&lt;/p&gt;
&lt;p&gt;在这个阶段，attention 的计算占据了大部分时间，因此，作者采取了如下的 overlap 策略&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-decoding-overlap.png"
width="896"
height="308"
loading="lazy"
alt="Decoding overlap of DeepSeek-V3"
class="gallery-image"
data-flex-grow="290"
data-flex-basis="698px"
&gt;&lt;/p&gt;
&lt;p&gt;由于 decoding 阶段一般 batch size 比较小，因此整个 decoding 的瓶颈在于 memory access, 因此为了避免影响 attention 的计算效率，作者仅安排一小部分 SM 用于 dispatch-MoE-combine.&lt;/p&gt;
&lt;h3 id="suggestions-on-hardware-design"&gt;&lt;a href="#suggestions-on-hardware-design" class="header-anchor"&gt;&lt;/a&gt;Suggestions on Hardware Design
&lt;/h3&gt;&lt;h4 id="communication-hardware"&gt;&lt;a href="#communication-hardware" class="header-anchor"&gt;&lt;/a&gt;Communication Hardware
&lt;/h4&gt;&lt;p&gt;尽管作者将计算与通信重叠来提高训练效率，但是已有的通信仍然依赖于 SM, 这样限制了计算的效率。作者希望工能够构建专门针对通信的设备，另一方面，作者希望统一 IB 和 NVLink 来降低实现难度&lt;/p&gt;
&lt;h4 id="computation-hardware"&gt;&lt;a href="#computation-hardware" class="header-anchor"&gt;&lt;/a&gt;Computation Hardware
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;提升 FP8 GEMM 的累加精度，当前精度只有 14bit, 作者希望能够在 GPU 设计上进行改进，将这个精度提升到 34-bit&lt;/li&gt;
&lt;li&gt;支持 tile 以及 block 层面的 quantization, 尽管前文作者已经设计出了改进的算法，但是 Tensor Core 以及 CUDA 之前平凡的数据移动降低了计算效率，作者希望未来能够支持细粒度的 quantization&lt;/li&gt;
&lt;li&gt;online quantization, 作者希望将 FP8 cast 以及 TMA 结合在一起，从而 quantization 可以在传输的时候完成计算，减少了内存读写。作者还建议使用 warp-level cast instruction&lt;/li&gt;
&lt;li&gt;Transposed GEMM operations. 本文中，矩阵被切分为不同的 tiles, 在计算的时候需要先加载这些 tiles 然后进行 dequantization, transpose 等操作，作者希望未来能够直接支持 transposed reads of matrices&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="pre-training"&gt;&lt;a href="#pre-training" class="header-anchor"&gt;&lt;/a&gt;Pre-training
&lt;/h2&gt;&lt;h3 id="pre-training-data"&gt;&lt;a href="#pre-training-data" class="header-anchor"&gt;&lt;/a&gt;Pre-training Data
&lt;/h3&gt;&lt;p&gt;相比于 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v2/" target="_blank" rel="noopener"
&gt;DeepSeek-V2&lt;/a&gt;, DeepSeek-V3 提升了数学和代码数据的比例，以及增加了多语种数据。最终训练数据一共包括 &lt;strong&gt;14.8T&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;作者还使用了 DeepSeekCoder-V2 里应用的 Fill in the middle 策略来让模型基于上下文越策中间的文本，对应的数据格式如下&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;|fim_begin|&amp;gt;f_pre&amp;lt;|fim_hole|&amp;gt;f_suf&amp;lt;|fim_hole|&amp;gt;f_middle&amp;lt;|fim_end|&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个结构与 sequence packing 结合在一起。&lt;/p&gt;
&lt;p&gt;Tokenizer 基于 BBPE, 大小为 128K tokens. 在训练时，作者将随机一部分 combine token 进行切分来减少 token boundary bias 问题&lt;/p&gt;
&lt;h3 id="hyper-parameters"&gt;&lt;a href="#hyper-parameters" class="header-anchor"&gt;&lt;/a&gt;Hyper-parameters
&lt;/h3&gt;&lt;p&gt;模型参数如下表所示，最终 DeepSeek-V3 拥有 671B 总参数，激活参数为 37B&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;variable&lt;/th&gt;
&lt;th&gt;notation&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;layers&lt;/td&gt;
&lt;td&gt;$\ell$&lt;/td&gt;
&lt;td&gt;61&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dense layers&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hidden dimension&lt;/td&gt;
&lt;td&gt;$d$&lt;/td&gt;
&lt;td&gt;7168&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;num of attention heads&lt;/td&gt;
&lt;td&gt;$n_h$&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;head dimension&lt;/td&gt;
&lt;td&gt;$d_h$&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KV compression dimension&lt;/td&gt;
&lt;td&gt;$d_c$&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;query compression dimension&lt;/td&gt;
&lt;td&gt;$d_c'$&lt;/td&gt;
&lt;td&gt;1536&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;decouple query and key dimension&lt;/td&gt;
&lt;td&gt;$d_h^R$&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;routed expert&lt;/td&gt;
&lt;td&gt;$N_r$&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shared expert&lt;/td&gt;
&lt;td&gt;$N_s$&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MoE hidden dimension&lt;/td&gt;
&lt;td&gt;$d_{MoE}$&lt;/td&gt;
&lt;td&gt;2048&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;activated experts&lt;/td&gt;
&lt;td&gt;$K$&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;limited node routing&lt;/td&gt;
&lt;td&gt;$M$&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MTP depth&lt;/td&gt;
&lt;td&gt;$D$&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;训练时，作者使用了 learning rate scheduling, batch size scheduling 等方法。对于 PP, routed expert 会均匀分布为 8node 对应的 64 个 GPU 上，预训练时模型的上下文长度为 4k&lt;/p&gt;
&lt;h3 id="long-context-extension"&gt;&lt;a href="#long-context-extension" class="header-anchor"&gt;&lt;/a&gt;Long Context Extension
&lt;/h3&gt;&lt;p&gt;作者使用了 &lt;a class="link" href="https://maosong.website/p/notes-on-yarn/" target="_blank" rel="noopener"
&gt;YARN&lt;/a&gt; 来扩展模型的上下文长度，模型上下文长度经过两个额外的训练阶段从 4K 扩展到 32K 再扩展到 128K, 均训练了 1000 步。&lt;/p&gt;
&lt;p&gt;YARN 配置与 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v2/" target="_blank" rel="noopener"
&gt;DeepSeek-V2&lt;/a&gt; 基本一致，在额外的 decoupled query and key 上作者没有应用这一点。参数配置如下表&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;parameter&lt;/th&gt;
&lt;th&gt;$s$&lt;/th&gt;
&lt;th&gt;$\alpha$&lt;/th&gt;
&lt;th&gt;$\beta$&lt;/th&gt;
&lt;th&gt;$\sqrt{t}$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;value&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;$0.1\ln s+1$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;第一阶段的上下文长度为 32K, batch size 为 1920, 第二个阶段的上下文长度为 128K, batch size 为 480.&lt;/p&gt;
&lt;h3 id="performance"&gt;&lt;a href="#performance" class="header-anchor"&gt;&lt;/a&gt;Performance
&lt;/h3&gt;&lt;p&gt;DeepSeek-V3 base 的表现下图所示，作者对比了 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v2/" target="_blank" rel="noopener"
&gt;DeepSeek-V2&lt;/a&gt;, &lt;a class="link" href="https://maosong.website/p/notes-on-qwen2.5/" target="_blank" rel="noopener"
&gt;Qwen2.5&lt;/a&gt;, &lt;a class="link" href="LLaMA%203.1" &gt;LLaMA 3.1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-base-performance.png"
width="1065"
height="1083"
loading="lazy"
alt="Performance of DeepSeek-V3 base"
class="gallery-image"
data-flex-grow="98"
data-flex-basis="236px"
&gt;&lt;/p&gt;
&lt;h3 id="discussion"&gt;&lt;a href="#discussion" class="header-anchor"&gt;&lt;/a&gt;Discussion
&lt;/h3&gt;&lt;p&gt;作者首先验证了 MTP 的有效性，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-ablation-MTP.png"
width="979"
height="451"
loading="lazy"
alt="Ablation study on MTP"
class="gallery-image"
data-flex-grow="217"
data-flex-basis="520px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，在模型架构相同，训练数据相同的情况下，1-MTP 的效果超过了 baseline 的表现，说明了 MTP 策略的有效性&lt;/p&gt;
&lt;p&gt;接下来，作者还验证了 &lt;a class="link" href="https://maosong.website/p/notes-on-loss-free-balancing/" target="_blank" rel="noopener"
&gt;Loss-Free Balancing&lt;/a&gt; 的有效性，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-ablation-loss-free-balancing.png"
width="987"
height="458"
loading="lazy"
alt="Ablation on loss-free balancing"
class="gallery-image"
data-flex-grow="215"
data-flex-basis="517px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，loss-free Balancing 的效果比 loss balancing 的效果更好&lt;/p&gt;
&lt;p&gt;接下来，作者对比了 loss-free balancing 和 sequence-wise auxiliary loss, 即 batch-wise v.s. sequence-wise. 作者认为，前者的约束更灵活，因为其不要求 in-domain balance. 作者在测试集上进行可视化，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-ablation-batch-wise.png"
width="1106"
height="522"
loading="lazy"
alt="Ablation study on batch-wise load balancing"
class="gallery-image"
data-flex-grow="211"
data-flex-basis="508px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果发现，loss-free 策略对应的 expert specialization 更强。作者进一步设计了一个 batch-wise auxiliary loss 来实现 batch-wise load balance, 结果发现，这种策略也能达到和 loss-free balancing 一样的效果，这说明了 batch-wise load balancing 效果更好&lt;/p&gt;
&lt;p&gt;最后，作者提了两点 loss-free 策略的问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在特定的 sequence 或者小 batch 里出现负载不均衡。作者通通过增大 batch size 来解决这个问题&lt;/li&gt;
&lt;li&gt;在推理阶段因为 domain-shift 导致的负载不均衡。作者实现了一个基于 redundant expert 的推理框架来解决这个问题&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="post-training"&gt;&lt;a href="#post-training" class="header-anchor"&gt;&lt;/a&gt;Post-training
&lt;/h2&gt;&lt;h3 id="sft"&gt;&lt;a href="#sft" class="header-anchor"&gt;&lt;/a&gt;SFT
&lt;/h3&gt;&lt;p&gt;post-training 包含 1.5M 样本，数据包括 reasoning 数据以及 non-reasoning 数据，前者由 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-r1/" target="_blank" rel="noopener"
&gt;DeepSeek-R1&lt;/a&gt; 合成，后者由 DeepSeek-V2.5 合成&lt;/p&gt;
&lt;p&gt;SFT 时，作者训练了两个 epoch, 使用了 sequence packing 技巧&lt;/p&gt;
&lt;h3 id="rl"&gt;&lt;a href="#rl" class="header-anchor"&gt;&lt;/a&gt;RL
&lt;/h3&gt;&lt;p&gt;Reward model 包含 rule-based reward model 和 model-based reward model.&lt;/p&gt;
&lt;p&gt;RL 训练使用的算法为 GRPO&lt;/p&gt;
&lt;h3 id="post-training-performance"&gt;&lt;a href="#post-training-performance" class="header-anchor"&gt;&lt;/a&gt;Post-training Performance
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v3/DeepSeek-V3-instruct-performance.png"
width="1112"
height="813"
loading="lazy"
alt="Performance of DeepSeek-V3"
class="gallery-image"
data-flex-grow="136"
data-flex-basis="328px"
&gt;&lt;/p&gt;
&lt;h3 id="post-training-discussion"&gt;&lt;a href="#post-training-discussion" class="header-anchor"&gt;&lt;/a&gt;Post-training Discussion
&lt;/h3&gt;&lt;p&gt;作者首先探究了 Distillation 对模型表现的影响，作者使用 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-r1/" target="_blank" rel="noopener"
&gt;DeepSeek-R1&lt;/a&gt; 来蒸馏 DeepSeek-V2.5, 结果如下图所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;LiveCodeBench-CoT&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;MATH-500&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Pass@1&lt;/td&gt;
&lt;td&gt;Length&lt;/td&gt;
&lt;td&gt;Pass@1&lt;/td&gt;
&lt;td&gt;Length&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek-V2.5 Baseline&lt;/td&gt;
&lt;td&gt;31.1&lt;/td&gt;
&lt;td&gt;718&lt;/td&gt;
&lt;td&gt;74.6&lt;/td&gt;
&lt;td&gt;769&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek-V2.5 +R1 Distill&lt;/td&gt;
&lt;td&gt;37.4&lt;/td&gt;
&lt;td&gt;783&lt;/td&gt;
&lt;td&gt;83.2&lt;/td&gt;
&lt;td&gt;1510&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以看到，distillation 可以显著提高模型的表现。但是其问题在于也会让模型输出的长度增加。作者认为知识蒸馏是 post-training optimization 的一个重要方向。&lt;/p&gt;
&lt;p&gt;接下来，作者讨论了 self-rewarding, 具体做法就是使用 DeepSeek-V3 来对评估结果进行投票，结果发现最终的效果很好，作者认为 LLM 可以很好地将非结构化信息转换为 rewards.&lt;/p&gt;
&lt;p&gt;最后，作者讨论了 MTP. MTP 可以于 speculative decoding 结合，进一步提高 decoding 的速度。通过实验作者发现，second token prediction 的接受率在 $85\%\sim 90\%$ 之间，说明了其有效性。&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;在本文中，作者提出了 DeepSeek-V3, 一个 671B-A37B 的 MoE 大语言模型，训练 token 数为 &lt;strong&gt;14.8T&lt;/strong&gt;. 作者使用了 loss-free-balancing strategy 来实现负载均衡。训练时作者使用了 FP8 混合精度。评估发现 DeepSeek-V3 的达到了 SOTA 表现。&lt;/p&gt;
&lt;p&gt;作者认为，DeepSeek-V3 model size 太大，不适合部署。第二，部署策略需要进一步改进。&lt;/p&gt;
&lt;p&gt;最后，作者认为未来工作有以下几点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;改进模型架构，进一步提高训练以及推理效率，扩展模型的上下文&lt;/li&gt;
&lt;li&gt;提升训练数据的数量和质量&lt;/li&gt;
&lt;li&gt;提高模型的 reasoning 能力&lt;/li&gt;
&lt;li&gt;更详尽的评估&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2412.19437" target="_blank" rel="noopener"
&gt;Arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on Gemini2.5</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini2.5/</link><pubDate>Sat, 06 Dec 2025 18:14:15 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini2.5/</guid><description>&lt;h2 id="介绍"&gt;&lt;a href="#%e4%bb%8b%e7%bb%8d" class="header-anchor"&gt;&lt;/a&gt;介绍
&lt;/h2&gt;&lt;p&gt;DeepMind 在 6 月 17 号发布了 Gemini2.x 系列的技术报告，包括&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gemini 2.5 Pro&lt;/li&gt;
&lt;li&gt;Gemini 2.5 Flash&lt;/li&gt;
&lt;li&gt;Gemini 2.0 Flash (earlier)&lt;/li&gt;
&lt;li&gt;Gemini 2.0 Flash-Lite (earlier)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;技术报告简单说了一些技术细节，主要还是模型的评估&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;注：Gemini 2.0 Flash 和 Gemini 2.0 Flash-Lite 将要被 Gemini 2.5 Flash 和 Gemini 2.5 Flash-Lite 取缔，见最新的 blog&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Gemini2.x 系列亮点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;领先的 coding 和 reasoning 能力&lt;/li&gt;
&lt;li&gt;超过 1M 的上下文，可以处理超过 3 个小时的 video&lt;/li&gt;
&lt;li&gt;集成 long context, multimodal 和 reasoning 三种能力的 agentic workflow 能力&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;模型能力对比&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Gemini 1.5 Flash&lt;/th&gt;
&lt;th&gt;Gemini 1.5 Pro&lt;/th&gt;
&lt;th&gt;Gemini 2.0 Flash-Lite&lt;/th&gt;
&lt;th&gt;Gemini 2.0 Flash&lt;/th&gt;
&lt;th&gt;Gemini 2.5 Flash&lt;/th&gt;
&lt;th&gt;Gemini 2.5 Pro&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Input Modalities&lt;/td&gt;
&lt;td&gt;Text, Image, Video, Audio&lt;/td&gt;
&lt;td&gt;Text, Image, Video, Audio&lt;/td&gt;
&lt;td&gt;Text, Image, Video, Audio&lt;/td&gt;
&lt;td&gt;Text, Image, Video, Audio&lt;/td&gt;
&lt;td&gt;Text, Image, Video, Audio&lt;/td&gt;
&lt;td&gt;Text, Image, Video, Audio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input length&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;2M&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output modalities&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;Text, Image*&lt;/td&gt;
&lt;td&gt;Text, Audio*&lt;/td&gt;
&lt;td&gt;Text, Audio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output length&lt;/td&gt;
&lt;td&gt;8K&lt;/td&gt;
&lt;td&gt;8K&lt;/td&gt;
&lt;td&gt;8K&lt;/td&gt;
&lt;td&gt;8K&lt;/td&gt;
&lt;td&gt;64K&lt;/td&gt;
&lt;td&gt;64K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thinking&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Dynamic&lt;/td&gt;
&lt;td&gt;Dynamic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supports tool use?&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Knowledge cutoff&lt;/td&gt;
&lt;td&gt;November 2023&lt;/td&gt;
&lt;td&gt;November 2023&lt;/td&gt;
&lt;td&gt;June 2024&lt;/td&gt;
&lt;td&gt;June 2024&lt;/td&gt;
&lt;td&gt;January 2025&lt;/td&gt;
&lt;td&gt;January 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;模型场景使用对比&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Gemini 2.5 Flash-Lite&lt;/th&gt;
&lt;th&gt;Gemini 2.5 Flash&lt;/th&gt;
&lt;th&gt;Gemini 2.5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Thinking&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;使用场景&lt;/td&gt;
&lt;td&gt;大规模调用&lt;/td&gt;
&lt;td&gt;日常使用&lt;/td&gt;
&lt;td&gt;coding 或者 reasoning 人物&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;速度&lt;/td&gt;
&lt;td&gt;非常快&lt;/td&gt;
&lt;td&gt;快&lt;/td&gt;
&lt;td&gt;一半&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;表现&lt;/td&gt;
&lt;td&gt;一半&lt;/td&gt;
&lt;td&gt;强&lt;/td&gt;
&lt;td&gt;非常强&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;输入价格&lt;/td&gt;
&lt;td&gt;0.1&lt;/td&gt;
&lt;td&gt;0.3&lt;/td&gt;
&lt;td&gt;1.25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;输出价格&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;2.5&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;模型表现&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini2.5/Gemini_2_5_performance.png"
width="3840"
height="2160"
loading="lazy"
alt="Gemini_2_5_performance"
class="gallery-image"
data-flex-grow="177"
data-flex-basis="426px"
&gt;&lt;/p&gt;
&lt;p&gt;模型吞吐量对比&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini2.5/Gemini_2_5_throughput.png"
width="2156"
height="960"
loading="lazy"
alt="Gemini_2_5_throughput"
class="gallery-image"
data-flex-grow="224"
data-flex-basis="539px"
&gt;&lt;/p&gt;
&lt;h2 id="架构数据与训练"&gt;&lt;a href="#%e6%9e%b6%e6%9e%84%e6%95%b0%e6%8d%ae%e4%b8%8e%e8%ae%ad%e7%bb%83" class="header-anchor"&gt;&lt;/a&gt;架构，数据与训练
&lt;/h2&gt;&lt;h3 id="架构"&gt;&lt;a href="#%e6%9e%b6%e6%9e%84" class="header-anchor"&gt;&lt;/a&gt;架构
&lt;/h3&gt;&lt;p&gt;Gemini2.5 是一个&lt;strong&gt;基于 MoE 的 transformer 架构&lt;/strong&gt;，支持 text, vision, audio 模态&lt;/p&gt;
&lt;p&gt;Flash 系列使用的是知识蒸馏的方法训练得到的，训练时使用了 $k$-sparse 的策略，也就是只保留教师模型输出概率最高的 $k$ 的词以及对应的概率。作者认为知识蒸馏可以有效提高小模型的能力。&lt;/p&gt;
&lt;h3 id="infra"&gt;&lt;a href="#infra" class="header-anchor"&gt;&lt;/a&gt;Infra
&lt;/h3&gt;&lt;p&gt;Gemini 系列在 TPUv5p 的架构上进行训练。作者主要提了两点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Slice-Granularity Elasticity：可以在部分 TPU 出现故障时快速切换并继续训练&lt;/li&gt;
&lt;li&gt;Split-Phase SDC detection：通过轻量级重放和校验机制，在几分钟内就能识别出有问题的硬件设备&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="post-training"&gt;&lt;a href="#post-training" class="header-anchor"&gt;&lt;/a&gt;Post-training
&lt;/h3&gt;&lt;p&gt;post-training 包含 SFT，reward model 以及 RL 的训练。&lt;/p&gt;
&lt;p&gt;在 RL 阶段，奖励来自 verifiable rewards 和 model-based generative rewards&lt;/p&gt;
&lt;h3 id="能力提升"&gt;&lt;a href="#%e8%83%bd%e5%8a%9b%e6%8f%90%e5%8d%87" class="header-anchor"&gt;&lt;/a&gt;能力提升
&lt;/h3&gt;&lt;p&gt;技术报告提到了几个方面能力的提升&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;code&lt;/strong&gt;
pre-training 阶段，加入了大量的代码数据，作者还评估了代码数据的质量
post-training 阶段，作者基于 reasoning 能力构建了一系列的工程任务，来提高模型解决问题的能力&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Factuality&lt;/strong&gt;
通过 search 和 tool use，reason about output 以及 issue follow-up queries 来验证 factual accuracy&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Multilinguality&lt;/strong&gt;
预训练时使用了 400 多种语言的语料进行训练&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Audio&lt;/strong&gt;
训练模型完成 audio generation 任务，生成的时候使用了&lt;strong&gt;causal audio representation&lt;/strong&gt;，训练数据覆盖了 200 多种语言&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Video&lt;/strong&gt;
通过降低每帧视频对应的 visual token 个数（258-&amp;gt; 66），来让模型可以处理 3 个小时的视频&lt;/p&gt;
&lt;h2 id="evaluation"&gt;&lt;a href="#evaluation" class="header-anchor"&gt;&lt;/a&gt;Evaluation
&lt;/h2&gt;&lt;p&gt;对比了 Claude_4, o3, &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-r1/" target="_blank" rel="noopener"
&gt;DeepSeek-R1&lt;/a&gt; 和 Grok-1&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini2.5/Gemini_2_5_evaluation.png"
width="1754"
height="1174"
loading="lazy"
alt="Gemini_2_5_evaluation"
class="gallery-image"
data-flex-grow="149"
data-flex-basis="358px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-gemini2.5/Gemini_2_5_video_understanding_performance.png"
width="1724"
height="988"
loading="lazy"
alt="Gemini_2_5_video_understanding_performance"
class="gallery-image"
data-flex-grow="174"
data-flex-basis="418px"
&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;结论里作者主要提到了两点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;模型能力的提升已经超过了 benchmark 的构建速度和成本&lt;/li&gt;
&lt;li&gt;未来如何设计经济的，覆盖广的，能动态调整难度的 benchmark 是一个关键问题&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;技术报告中作者还提到了 Gemini Plays Pokemon 的 case study，作者提到了两点问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;作者发模型对视觉信息的依赖程度并不是很高&lt;/li&gt;
&lt;li&gt;尽管模型上下文长度超过了 1M，但是对于这种复杂的 long horizon 问题，当输入超过了 100K token 之后，模型倾向于重复过去的行为，而不是生成新的计划
因此，未来如何解决 multi-turn, long-horizon 的 agentic task 也是一个值得探究的方向。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="reference"&gt;&lt;a href="#reference" class="header-anchor"&gt;&lt;/a&gt;Reference
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.google/products/gemini/gemini-2-5-model-family-expands/" target="_blank" rel="noopener"
&gt;Gemini 2.5 Flash/Flash Lite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.google/products/gemini/gemini-2-5-model-family-expands/" target="_blank" rel="noopener"
&gt;Gemini 2.5 Technical Report&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on olmoe</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/</link><pubDate>Sat, 06 Dec 2025 18:08:11 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;作者在本文中主要想完成三个目标：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;基于已有框架尝试训练一个 MoE 大语言模型&lt;/li&gt;
&lt;li&gt;详细分析 MoE 模型的 routing 机制&lt;/li&gt;
&lt;li&gt;为后续 MoE 模型开发提供经验&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;基于这三个目标，作者在本文中发布了 4 个 MoE 模型。预训练时，作者使用了 $52.25\%$ 的代码数据来提高模型的表现。作者还是用了 UL2 作为训练目标。&lt;/p&gt;
&lt;p&gt;通过实验作者发现 MoE 机制存在以下三个性质：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Context-independent Specialization: 即 MoE 模型倾向于基于 token semantics 进行聚类，而不是 context&lt;/li&gt;
&lt;li&gt;early routing learning: routing 的分布情况在训练早期就已经确定了&lt;/li&gt;
&lt;li&gt;drop towards the end: 使用 token dropping 策略之后，越往后的的 token 被丢弃掉的概率也就越大&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;h3 id="model"&gt;&lt;a href="#model" class="header-anchor"&gt;&lt;/a&gt;Model
&lt;/h3&gt;&lt;p&gt;作者介绍了模型使用的数据集如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/OpenMoE-data-mixture.png"
width="938"
height="492"
loading="lazy"
alt="data mixture of OpenMoE"
class="gallery-image"
data-flex-grow="190"
data-flex-basis="457px"
&gt;&lt;/p&gt;
&lt;p&gt;模型的 tokenizer 基于 umT5, 大小为 256K, umT5 支持多语种，并且还有 fallback 机制来处理 OOV 的 token&lt;/p&gt;
&lt;p&gt;模型配置如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;OpenMoE-Base/16E&lt;/th&gt;
&lt;th&gt;OpenMoE-8B/32E&lt;/th&gt;
&lt;th&gt;OpenMoE-34B/32E&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;total params&lt;/td&gt;
&lt;td&gt;650M&lt;/td&gt;
&lt;td&gt;8.7B&lt;/td&gt;
&lt;td&gt;34B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;activated params&lt;/td&gt;
&lt;td&gt;142M&lt;/td&gt;
&lt;td&gt;2.1B&lt;/td&gt;
&lt;td&gt;6B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;total experts&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;activated experts&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shared experts&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layout&lt;/td&gt;
&lt;td&gt;every 4&lt;/td&gt;
&lt;td&gt;every 6&lt;/td&gt;
&lt;td&gt;every 4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hidden_dim&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;2048&lt;/td&gt;
&lt;td&gt;3072&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ffn_hidden_dim&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3072&lt;/td&gt;
&lt;td&gt;8192&lt;/td&gt;
&lt;td&gt;12288&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;num_heads&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;head_dim&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;num_layers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="training"&gt;&lt;a href="#training" class="header-anchor"&gt;&lt;/a&gt;Training
&lt;/h3&gt;&lt;p&gt;作者使用了 &lt;a class="link" href="https://maosong.website/p/load-balancing-tutorial/" target="_blank" rel="noopener"
&gt;Load Balancing loss&lt;/a&gt; 和 &lt;a class="link" href="https://maosong.website/p/st-moe/" target="_blank" rel="noopener"
&gt;ST-MoE&lt;/a&gt; 提出的 Router Z-loss, 最终训练的目标函数与 &lt;a class="link" href="https://maosong.website/p/st-moe/" target="_blank" rel="noopener"
&gt;ST-MoE&lt;/a&gt; 一致&lt;/p&gt;
&lt;p&gt;作者在训练时，还是用了 UL2, UL2 结合了 mask language modeling 和 casual language modeling 两种训练方式。&lt;/p&gt;
&lt;p&gt;作者首先对各个实验配置进行了验证，其中关键接论文模型很容易在 code data 上达到比较高的准确率以及比较低的 loss, 作者认为这是因为 code data 中存在大量的特殊符号。&lt;/p&gt;
&lt;p&gt;训练过程中，作者发现模型在训练一定步数之后，容易出现过饱和现象，因此作者将训练目标函数由 UL2 降为 CasualLM, 并未作者还将代码数据的比例降低到 $15\%$.&lt;/p&gt;
&lt;h2 id="experiments"&gt;&lt;a href="#experiments" class="header-anchor"&gt;&lt;/a&gt;Experiments
&lt;/h2&gt;&lt;h3 id="analysis-openmoe"&gt;&lt;a href="#analysis-openmoe" class="header-anchor"&gt;&lt;/a&gt;Analysis OpenMoE
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;作者发现，大部分专家对于不同的 domain 没有出现 specialization 情况，对于 math domain, specialization 现象比较明显，作者认为这是因为 math domain 包含更多的 special tokens&lt;/li&gt;
&lt;li&gt;对于不同的语言，有部分专家出现 specialization 现象&lt;/li&gt;
&lt;li&gt;部分专家对于 position ID 有 specialization 现象，并且连续的 token 更偏好相同的专家&lt;/li&gt;
&lt;li&gt;作者还发现，部分专家对于 Token ID 有 specialization 现象，作者将这种现象称为 &lt;strong&gt;Context-independent Specialization&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;专家还会对语义相似的 token 进行聚类，并且这种聚类在训练早期就已经发生，作者认为其原因在于重新分配 token 会增加最终的 loss&lt;/li&gt;
&lt;li&gt;对于 token dropping, 作者发现月考后的 token, 其被 drop 的概率比例也越高。并且对于指令跟随数据，更多的 token 都会被丢掉，因此作者认为指令跟随数据是 MoE 模型的一种 OOD 数据&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="analysis-on-other-moe-models"&gt;&lt;a href="#analysis-on-other-moe-models" class="header-anchor"&gt;&lt;/a&gt;Analysis on other MoE Models
&lt;/h3&gt;&lt;p&gt;作者还分析了 &lt;a class="link" href="https://maosong.website/p/mixstral-8x7b/" target="_blank" rel="noopener"
&gt;Mixtral MoE&lt;/a&gt; 和 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 两个模型的专家路由情况。这两个模型采用了 dropless token routing 的机制。&lt;/p&gt;
&lt;p&gt;首先，作者分析了这两个模型对于 TokenID 的敏感性，结果发现，DeepSeek-MoE 的 specialization 现象比较明显，而 Mixtral MoE 由于使用了 upcycling, 其 specialization 现象不太明显，作者认为这是因为 upcycling 导致每个专家的权重都差不多。最终，作者认为对于 training from stratch 的 MoE model 这个 specialization 现象更明显。&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者在本文中提出了一个全开源的 MoE 大模型系列，包括 0.6B, 8.7B 和 34B 三个 size, 作者还对 MoE 中的 routing 进行了详细的分析，结果发现【【】】，这些发现有助于后续的 MoE 模型架构的研究。&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2402.01739" target="_blank" rel="noopener"
&gt;Arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on DeepSeek-R1</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-r1/</link><pubDate>Tue, 02 Dec 2025 18:21:54 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-r1/</guid><description/></item><item><title>Notes on DeepSeek-V2</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v2/</link><pubDate>Tue, 02 Dec 2025 18:21:54 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v2/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;作者首先提到如何提高模型的训练效率以及 inference efficiency 是两个尚未解决的问题。&lt;/p&gt;
&lt;p&gt;基于这两个问题，作者在本文中提出了 DeepSeek-V2，一个开源的 MoE 模型，DeepSeek-V2 的亮点在于训练和推理都非常高效。最终 DeepSeeK-V2 包含 236B 总参数，激活参数为 21B, 上下文长度为 128K. 作者还开源了 DeepSeek-V2-Lite, 一个 15.7B-A2.4B 的 MoE 模型，用于学术研究。&lt;/p&gt;
&lt;p&gt;DeepSeek-V2 主要改进点为：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;基于 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt;, 使用了 MoE 架构&lt;/li&gt;
&lt;li&gt;使用了 MLA 压缩 KV cache, 大幅度提高推理效率&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;DeepSeek-V2 预训练使用了 &lt;strong&gt;8.1T&lt;/strong&gt; tokens, 相比于 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-llm/" target="_blank" rel="noopener"
&gt;DeepSeek-LLM&lt;/a&gt;, 预训练数据主要增加了中文数据以及提高了数据的质量。&lt;/p&gt;
&lt;p&gt;接下来，作者收集了 &lt;strong&gt;1.5M&lt;/strong&gt; 对话数据来进行 SFT, 最终作者基于 DeepSeek Math 提出的 GRPO 来进行对齐。&lt;/p&gt;
&lt;h2 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h2&gt;&lt;p&gt;DeepSeek-V2 的模型架构如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v2/DeepSeek-V2-architecture.png"
width="1324"
height="1064"
loading="lazy"
alt="Architecture of DeepSeek-V2"
class="gallery-image"
data-flex-grow="124"
data-flex-basis="298px"
&gt;&lt;/p&gt;
&lt;p&gt;模型基于 DeepSeekMoE 开发得到，相比于 DeepSeekMoE, DeepSeek-V2 主要是使用了 MLA&lt;/p&gt;
&lt;h3 id="mla"&gt;&lt;a href="#mla" class="header-anchor"&gt;&lt;/a&gt;MLA
&lt;/h3&gt;&lt;p&gt;这部分介绍见 &lt;a class="link" href="https://maosong2022.github.io/p/notes-on-mla/" target="_blank" rel="noopener"
&gt;MLA&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="deepseekmoe"&gt;&lt;a href="#deepseekmoe" class="header-anchor"&gt;&lt;/a&gt;DeepSeekMoE
&lt;/h3&gt;&lt;h4 id="architecture-1"&gt;&lt;a href="#architecture-1" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h4&gt;&lt;p&gt;关于架构的介绍见 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="device-limited-routing"&gt;&lt;a href="#device-limited-routing" class="header-anchor"&gt;&lt;/a&gt;Device-Limited Routing
&lt;/h4&gt;&lt;p&gt;由于 DeepSeek-MoE 使用了细粒度的专家，因此专家会分布在更多的设备（GPU）上，计算时，基于 routing 的 expert 所在设备，会产生不同大小的通信开销。为了降低通信开销，作者构建了 device-limited routing mechanism. 具体的做法就是，在 Routing 之前，先基于 experts 的 affinity score 挑选 $M$ 个设备，然后基于这 $M$ 个设备的专家挑选 top-K 专家进行计算。&lt;/p&gt;
&lt;p&gt;作者通过实验发现，当 $M\geq3$ 时，device-limited routing 可以和标准的 top-K routing 表现差不多。&lt;/p&gt;
&lt;h4 id="auxiliary-loss-for-load-balance"&gt;&lt;a href="#auxiliary-loss-for-load-balance" class="header-anchor"&gt;&lt;/a&gt;Auxiliary Loss for Load Balance
&lt;/h4&gt;&lt;p&gt;作者使用了三个 loss 来实现负载均衡。其中，expert level 和 device level 的 load balancing loss 与 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 相同。第三个 loss 是 communication balance loss, 这个 loss 的目的是让每个设备的通信开销保持平衡。损失函数的表达式如下所示&lt;/p&gt;
$$
\mathcal{L}_{communication} = \alpha\sum_{i=1}^D f_iP_i
$$&lt;p&gt;其中 $\alpha$ 是超参数，$D$ 是 expert group 的个数。&lt;/p&gt;
$$
f_i = \frac{D}{MT}\sum_{t=1}^T\mathbb{1}(\text{Token }t \text{ is sent Device }i),\quad P_i = \sum_{j\in\mathcal{E}_i}P_j
$$&lt;p&gt;device limited routing 让每个 device 发送至多 $MT$ 个 hidden states 到其他设备上。而 communication balancing loss 则让每个设备最多从其他设备接收 $MT$ 个 hidden states.&lt;/p&gt;
&lt;h4 id="token-dropping-strategy"&gt;&lt;a href="#token-dropping-strategy" class="header-anchor"&gt;&lt;/a&gt;Token-Dropping Strategy
&lt;/h4&gt;&lt;p&gt;尽管前面已经增加了 load balance loss, 但毕竟不是硬约束。因此，作者就从硬件层面提出了 Token dropping 策略，来提高训练效率。核心思想就是，在训练时，主动丢弃部分 token, 强制让各个设备的计算量不会超过额度限制，进而减少资源浪费。&lt;/p&gt;
&lt;p&gt;具体做法就是，在训练之前，先将每个设备的 capacity factor 设置为 1 （定义见 &lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt;）. 然后按照 affinity score 来丢弃一些分数比较低的 token, 直到该设备的 token 数量刚到达到 capacity。为了避免过度学习导致模型表现较差，对于 $10\%$ 的训练数据，作者不执行 token dropping 策略。&lt;/p&gt;
&lt;p&gt;最终，在 inference 时，可以根据需求来决定是否丢弃 token, 比如在 low latency 场景，我们可以丢弃低价值的 token, 在高精度场景，我们就可以保留所有的 token.由于在训练阶段已经才去过 token dropping 策略，因此在推理时不管是丢弃还是全部保留模型都能比较好的适应。&lt;/p&gt;
&lt;h2 id="pre-training"&gt;&lt;a href="#pre-training" class="header-anchor"&gt;&lt;/a&gt;Pre-training
&lt;/h2&gt;&lt;h3 id="data"&gt;&lt;a href="#data" class="header-anchor"&gt;&lt;/a&gt;Data
&lt;/h3&gt;&lt;p&gt;预训练数据与 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-llm/" target="_blank" rel="noopener"
&gt;DeepSeek-LLM&lt;/a&gt; 基本上差不多，作者针对中文数据，数据质量进行了改进。最终预训练数据包括 &lt;strong&gt;8.1T&lt;/strong&gt; token, 其中中文数据比英文数据多 $12\%$.&lt;/p&gt;
&lt;p&gt;tokenizer 与 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-llm/" target="_blank" rel="noopener"
&gt;DeepSeek-LLM&lt;/a&gt; 一致。&lt;/p&gt;
&lt;h3 id="model-configuration"&gt;&lt;a href="#model-configuration" class="header-anchor"&gt;&lt;/a&gt;Model Configuration
&lt;/h3&gt;&lt;p&gt;模型配置如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;DeepSeek-V2&lt;/th&gt;
&lt;th&gt;DeepSeek-V2-Lite&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;2024-5&lt;/td&gt;
&lt;td&gt;2024-5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# Total Parameters&lt;/td&gt;
&lt;td&gt;236B&lt;/td&gt;
&lt;td&gt;15.7B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# Activated Parameters&lt;/td&gt;
&lt;td&gt;21B&lt;/td&gt;
&lt;td&gt;2.4B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# tokens&lt;/td&gt;
&lt;td&gt;8.1T&lt;/td&gt;
&lt;td&gt;5.7T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# Dense Layers&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# MoE Layers&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hidden Dim&lt;/td&gt;
&lt;td&gt;5120&lt;/td&gt;
&lt;td&gt;2048&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dense Intermediate Dim&lt;/td&gt;
&lt;td&gt;12288&lt;/td&gt;
&lt;td&gt;10944&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MoE Intermediate Dim&lt;/td&gt;
&lt;td&gt;1536&lt;/td&gt;
&lt;td&gt;1408&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attention&lt;/td&gt;
&lt;td&gt;MLA&lt;/td&gt;
&lt;td&gt;MLA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# Attention Heads&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# Key-Value Heads&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# Routed Experts&lt;/td&gt;
&lt;td&gt;160&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# Experts Active Per Token&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# Shared Experts&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这里比较特殊的一点在于，模型在第一层使用了 MoE layer, 这个做法的原因在后面的 &lt;a class="link" href="https://maosong.website/p/notes-on-olmoe/" target="_blank" rel="noopener"
&gt;olmoe&lt;/a&gt; 里有提到，核心思想是 early layer 特别是第一层 layer 收敛比较慢。&lt;/p&gt;
&lt;p&gt;MLA 的配置如下 (DeepSeek-V2)&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;field&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$d_c$&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$d_c'$&lt;/td&gt;
&lt;td&gt;1536&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$n_h$&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$d_h$&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$d_h^R$&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="training-recipe"&gt;&lt;a href="#training-recipe" class="header-anchor"&gt;&lt;/a&gt;Training Recipe
&lt;/h3&gt;&lt;p&gt;训练的配置也与 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-llm/" target="_blank" rel="noopener"
&gt;DeepSeek-LLM&lt;/a&gt; 差不多，对于 MoE，作者使用了 PP 将不同的 layers 分配在不同的 device 上，然后 MoE 的 experts 被分配在 8 个 device 上 ($D=8$), 对于 device-limited routing, 每个 token 发送到至多 3 个 device, 也就是 $M=3$.&lt;/p&gt;
&lt;h3 id="infra"&gt;&lt;a href="#infra" class="header-anchor"&gt;&lt;/a&gt;Infra
&lt;/h3&gt;&lt;p&gt;在 infra 上，DeepSeek-V2 也是用了 HAI-LLM 框架进行训练。这里面使用了 16-way zero-bubble PP, 8-way EP, ZeRO-1 DP.&lt;/p&gt;
&lt;p&gt;由于 DeepSeek-V2 的激活参数比较少，因此，作者没有使用 TP, 进而降低通信开销。作者还将 shared experts 的计算与 expert all-to-all 通信进行重叠来提高计算效率。作者还使用了 kernel fusion 和 flash attention 2 来加速训练。&lt;/p&gt;
&lt;h3 id="long-context"&gt;&lt;a href="#long-context" class="header-anchor"&gt;&lt;/a&gt;Long Context
&lt;/h3&gt;&lt;p&gt;在预训练阶段结束之后，作者使用了 &lt;a class="link" href="https://maosong.website/p/notes-on-yarn/" target="_blank" rel="noopener"
&gt;YARN&lt;/a&gt; 来将模型的上下文从 4K 扩展到 128K. 超参数设置为&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$s$&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\alpha$&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\beta$&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;target context length&lt;/td&gt;
&lt;td&gt;160K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;scaling factor&lt;/td&gt;
&lt;td&gt;$\sqrt{t} = 0.0707\ln s + 1$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;作者在 32K 的上下文下额外训练了 1000 步，然后在推理阶段通过 YaRN 将模型的上下文长度扩展到 128K.&lt;/p&gt;
&lt;h3 id="evaluation"&gt;&lt;a href="#evaluation" class="header-anchor"&gt;&lt;/a&gt;Evaluation
&lt;/h3&gt;&lt;p&gt;作者对比了 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-llm/" target="_blank" rel="noopener"
&gt;DeepSeek-LLM&lt;/a&gt;, &lt;a class="link" href="https://maosong.website/p/notes-on-qwen1.5/" target="_blank" rel="noopener"
&gt;Qwen1.5&lt;/a&gt;, &lt;a class="link" href="https://maosong.website/p/mixstral-8x7b/" target="_blank" rel="noopener"
&gt;Mixtral MoE&lt;/a&gt; 以及 &lt;a class="link" href="https://maosong.website/p/notes-on-llama3/" target="_blank" rel="noopener"
&gt;LLaMA 3&lt;/a&gt;, 实验结果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v2/DeepSeek-V2-pretraining-performance.png"
width="1264"
height="1177"
loading="lazy"
alt="Performance of DeepSeek-V2 base"
class="gallery-image"
data-flex-grow="107"
data-flex-basis="257px"
&gt;&lt;/p&gt;
&lt;h3 id="efficiency"&gt;&lt;a href="#efficiency" class="header-anchor"&gt;&lt;/a&gt;Efficiency
&lt;/h3&gt;&lt;p&gt;作者对比了以下 DeepSeek-MoE 和 DeepSeek-LLM 的训练效率，结果发现，对于 1T 的 token, DeepSeek-LLM 需要 300.6K GPU hours, 而 DeepSeek-V2 仅需要 127.8K GPU hours. 也就是说，DeepSeeK-V2 节省了 $42.5\%$ 的训练成本&lt;/p&gt;
&lt;p&gt;在推理时，作者首先将模型的精度转换为 FP8，然后作者进一步对模型进行 KV cache quantization 来进一步压缩每个 token 的 KV cache 到 6bits. 最终，DeepSeek-V2 的 throughtput 为 50K tokens/s.&lt;/p&gt;
&lt;h2 id="post-training"&gt;&lt;a href="#post-training" class="header-anchor"&gt;&lt;/a&gt;Post-training
&lt;/h2&gt;&lt;p&gt;post-training 分为 SFT 和 RL 两个阶段。&lt;/p&gt;
&lt;h3 id="sft"&gt;&lt;a href="#sft" class="header-anchor"&gt;&lt;/a&gt;SFT
&lt;/h3&gt;&lt;p&gt;在 SFT 阶段，作者构建了 &lt;strong&gt;1.5M&lt;/strong&gt; 样本，包括 1.2M 有帮助性的样本和 0.3M 安全性相关的样本。模型训练了 2 个 epoch, 学习率为 $5e-6$.&lt;/p&gt;
&lt;h3 id="rl"&gt;&lt;a href="#rl" class="header-anchor"&gt;&lt;/a&gt;RL
&lt;/h3&gt;&lt;p&gt;作者使用了 GRPO 算法来进一步对齐模型的表现。&lt;/p&gt;
&lt;p&gt;作者通过实验发现，在 reasoning data, 如 code 和 math 相关数据上进行训练时，可以有效提高模型的表现。因此作者将 RL 的训练分为两个阶段，第一个阶段用于提高模型的 reasoning 能力，第二个阶段用于对齐人类偏好。&lt;/p&gt;
&lt;p&gt;在第一个阶段，作者首先训练了一个针对 code 和 Math 的 reward model $\mathrm{RM}_{\mathrm{reasoning}}$, 然后基于这个 reward model 来训练 policy model:&lt;/p&gt;
$$
r_i=\mathrm{RM}_{\mathrm{reasoning}}(o_i)
$$&lt;p&gt;在第二阶段，作者使用了一个 Multi-reward 框架，包括一个 helpful reward model $\mathrm{RM}_{\mathrm{helpful}}$, 一个 safety reward model $\mathrm{RM}_{\mathrm{safety}}$ 和一个 rule-based reward model $\mathrm{RM}_{\mathrm{rule}}$, 最终的 reward 为&lt;/p&gt;
$$
r_i = c_1\mathrm{RM}_{\mathrm{helpful}}+c_2\mathrm{RM}_{\mathrm{safety}}+c_3\mathrm{RM}_{\mathrm{rule}}
$$&lt;p&gt;训练时，reward model 由 SFT model 初始化得到，然后基于 point-wise 或者 pair-wise loss 进行训练。&lt;/p&gt;
&lt;h3 id="evaluation-1"&gt;&lt;a href="#evaluation-1" class="header-anchor"&gt;&lt;/a&gt;Evaluation
&lt;/h3&gt;&lt;p&gt;chat 版本的模型评估结果如下所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseek-v2/DeepSeek-V2-posttraining-performance.png"
width="1325"
height="923"
loading="lazy"
alt="Performance of DeepSeek-V2-chat"
class="gallery-image"
data-flex-grow="143"
data-flex-basis="344px"
&gt;&lt;/p&gt;
&lt;h3 id="discussion"&gt;&lt;a href="#discussion" class="header-anchor"&gt;&lt;/a&gt;Discussion
&lt;/h3&gt;&lt;p&gt;作者讨论了三点发现：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SFT data 数量。已有工作认为进需要 10K 左右的样本就可以进行 SFT，但是作者发现当数据量小于 10K 时，模型在 IFEval benchmark 上的表现大幅度下降。作者认为，这是由于数据过少导致模型很难掌握特定的技能。因此，作者认为足够的数据以及数据质量都很重要，特别是写作类任务和 open-ended QA 类任务。&lt;/li&gt;
&lt;li&gt;alignment tax. 作者发现通过 human preference alignment, 模型在 open-ended generation benchmark 上的保险有了很大提升。与 RLHF 一样，作者也发现了 alignment 之后模型在一些 benchmark 上表现也会下降。作者通过改进解决了这个问题，作者认为如何在不损失模型表现的情况下实现对齐是一个值得探究的方向。&lt;/li&gt;
&lt;li&gt;online RL. 作者发现 Online RL 比 offline RL 的表现更好。作者认为如何根据不同的任务来选取 offline RL 和 online RL 也是一个值得探究的问题。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;在本文中，作者提出了 DeepSeek-V2, 一个基于 MoE 架构的大语言模型系列，模型的上下文为 128K. 作者基于 DeepSeek-MoE, 提出了 MLA 来提高模型的 inference 效率，并大幅度降低了训练的成本。&lt;/p&gt;
&lt;p&gt;作者介绍了几点未来工作：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;进一步 scaling up MoE 模型，降低模型的训练以及推理成本&lt;/li&gt;
&lt;li&gt;进一步对齐模型和人类的价值观，然后最小化人类监督信号&lt;/li&gt;
&lt;li&gt;扩展模型到多模态版本&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="reference"&gt;&lt;a href="#reference" class="header-anchor"&gt;&lt;/a&gt;Reference
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2405.04434" target="_blank" rel="noopener"
&gt;Arxiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://huggingface.co/deepseek-ai/DeepSeek-V2" target="_blank" rel="noopener"
&gt;HuggingFace&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on Loss-free Balancing</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-loss-free-balancing/</link><pubDate>Fri, 21 Nov 2025 15:38:52 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-loss-free-balancing/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;已有的 MoE 模型往往都会使用 load balancing loss 来避免 Imbalanced routing, 但是加入这个额外的损失之后，模型训练的梯度也会受到影响。&lt;/p&gt;
&lt;p&gt;DeepSeek 基于这个问题提出了 Loss-Free Balancing, 该方法不引入额外的 loss item, 而是在 routing 的结果上加入一个 bias item, bias item 可以根据 expert load 来动态更新进而实现 load balancing.&lt;/p&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;p&gt;MoE definition&lt;/p&gt;
$$
\begin{aligned}
h_t &amp;= u_t + \sum_{i=1}^Ng_{i,t}\mathrm{FFN}_i(u_t),\\
g_{i,t} &amp;= \begin{cases}
s_{i,t}, &amp; s_{i,t}\in\mathrm{Topk}(\{s_{i,j}\mid 1\leq j\leq N\}, K)\\
0, &amp;\text{otherwise}
\end{cases}\\
s_{i,t} &amp;= G(u_t^Te_i),
\end{aligned}
$$&lt;p&gt;其中 $G$ 是 gating function, $e_i$ 是第 $i$ 个专家对应 gating function 的权重&lt;/p&gt;
&lt;p&gt;load balancing loss 有两个作用：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;避免 routing collapse, 即模型只选择固定的少数专家完成任务&lt;/li&gt;
&lt;li&gt;减少通信开销&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但是引入 load balancing loss 会对 LLM 的训练产生影响，为了避免对模型性能造成影响，我们需要小心设置 load balancing loss 的权重，实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-loss-free-balancing/loss-free-balancing-hyperparameter-setting.png"
width="917"
height="575"
loading="lazy"
alt="The dilemma between load balance and model performance for auxiliary-loss-controlled training"
class="gallery-image"
data-flex-grow="159"
data-flex-basis="382px"
&gt;&lt;/p&gt;
&lt;p&gt;为了解决这个问题，作者提出了 Loss-Free Balancing, 具体做法就是在每个专家的 gating score 上加入一个 bias term, 然后再决定对应的专家：&lt;/p&gt;
$$
g_{i,t} = \begin{cases}
s_{i,t}, &amp; s_{i,t}+b_i\in\mathrm{Topk}(\{s_{i,j}+b_j\mid 1\leq j\leq N\}, K)\\
0, &amp;\text{otherwise}
\end{cases}
$$&lt;p&gt;注意这里的 bias item 仅影响 top-K 操作，其对最终的输出没有影响。&lt;/p&gt;
&lt;p&gt;为了实现负载均衡，作者根据上一个 batch 的 expert load 情况来调整 bias item, 如果某一个专家的 load 太大，则对应的 bias item 会变小。 其算法实现过程如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-loss-free-balancing/loss-free-balancing-algorithm.png"
width="1152"
height="410"
loading="lazy"
alt="Adjusting the per-expert bias during training"
class="gallery-image"
data-flex-grow="280"
data-flex-basis="674px"
&gt;&lt;/p&gt;
&lt;p&gt;作者对比不同的负载均衡算法如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Load Balancing Methods&lt;/th&gt;
&lt;th&gt;Balanced Expert Load&lt;/th&gt;
&lt;th&gt;Interference Gradients&lt;/th&gt;
&lt;th&gt;Future Token Leakage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Loss-Controlled (strong auxiliary loss)&lt;/td&gt;
&lt;td&gt;balanced&lt;/td&gt;
&lt;td&gt;strong&lt;/td&gt;
&lt;td&gt;no leakage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Loss-Controlled (weak auxiliary loss)&lt;/td&gt;
&lt;td&gt;imbalanced&lt;/td&gt;
&lt;td&gt;weak&lt;/td&gt;
&lt;td&gt;no leakage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expert Choice&lt;/td&gt;
&lt;td&gt;balanced&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;with leakage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Loss-Free (Ours)&lt;/td&gt;
&lt;td&gt;balanced&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;no leakage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="experiments"&gt;&lt;a href="#experiments" class="header-anchor"&gt;&lt;/a&gt;Experiments
&lt;/h2&gt;&lt;p&gt;作者使用了 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 来进行实验，作者使用了 sigmoid function 作为 gating function, 因为作者发现 sigmoid function 效果比 softmax 效果更好。&lt;/p&gt;
&lt;p&gt;作者提出了 maximal violation (MaxVio) 来量化一个 MoE layer 的负载均衡程度&lt;/p&gt;
$$
\mathrm{MaxVio} = \frac{\max_i\mathrm{Load}_i-\overline{\mathrm{Load}_i}}{\overline{\mathrm{Load}_i}}
$$&lt;p&gt;其中 $\mathrm{Load}_i$ 代表了分配给第 $i$ 个专家的 token 个数，$\overline{\mathrm{Load}_i}$ 代表了理想情况下的负载均衡。&lt;/p&gt;
&lt;p&gt;实验结果如下图所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model Size&lt;/th&gt;
&lt;th&gt;Load Balancing Methods&lt;/th&gt;
&lt;th&gt;Validation Perplexity&lt;/th&gt;
&lt;th&gt;MaxVio&lt;sub&gt;global&lt;/sub&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1B&lt;/td&gt;
&lt;td&gt;Loss-Controlled&lt;/td&gt;
&lt;td&gt;9.56&lt;/td&gt;
&lt;td&gt;0.72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1B&lt;/td&gt;
&lt;td&gt;Loss-Free&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;9.50&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.04&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3B&lt;/td&gt;
&lt;td&gt;Loss-Controlled&lt;/td&gt;
&lt;td&gt;7.97&lt;/td&gt;
&lt;td&gt;0.52&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3B&lt;/td&gt;
&lt;td&gt;Loss-Free&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7.92&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.04&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;实验结果显示，本文提出的 Loss-Free Balancing 效果更好，且负载均衡更高&lt;/p&gt;
&lt;p&gt;作者还展示了训练过程的负载情况如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-loss-free-balancing/loss-free-training-process-load.png"
width="1145"
height="406"
loading="lazy"
alt="Load of training process"
class="gallery-image"
data-flex-grow="282"
data-flex-basis="676px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，Loss-Free 的负载一直比 load balancing loss 效果更好&lt;/p&gt;
&lt;h3 id="ablation-study"&gt;&lt;a href="#ablation-study" class="header-anchor"&gt;&lt;/a&gt;Ablation Study
&lt;/h3&gt;&lt;p&gt;作者首先探究了 bias term 更新速率对模型表现的影响，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-loss-free-balancing/loss-free-ablation-update-rate.png"
width="920"
height="508"
loading="lazy"
alt="The impact of update rate on training load balance"
class="gallery-image"
data-flex-grow="181"
data-flex-basis="434px"
&gt;&lt;/p&gt;
&lt;p&gt;结果显示，使用过大的 update rate 会影响最终的负载均衡，而较小的 update rate 收敛速率比较慢。因此作者在本文中使用了 $u=0.001$ 这个设置&lt;/p&gt;
&lt;p&gt;作者还对比了 baseline model 使用 softmax 个 sigmoid gating 两种方式，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-loss-free-balancing/loss-free-ablation-gating-function.png"
width="917"
height="573"
loading="lazy"
alt="Ablation study on gating function"
class="gallery-image"
data-flex-grow="160"
data-flex-basis="384px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，Sigmoid function 对于超参数更加 robust, 且表现也更好一些。&lt;/p&gt;
&lt;p&gt;作者还尝试了不同的 bias 更新方式，结果显示尽管不同的更新方式有可能会提高 load balance, 但是最终模型表现提升不大。&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者在本文中提出了 Loss-Free Balancing 策略，一个针对 MoE 负载均衡而不需要额外损失项的方法&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2408.15664" target="_blank" rel="noopener"
&gt;Arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Mixstral 8x7B</title><link>https://jiangyigithub.github.io/ai.github.io/p/mixstral-8x7b/</link><pubDate>Sat, 01 Nov 2025 15:32:30 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/mixstral-8x7b/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;作者在本文中提出了 Mixtral 8x7B, 一个 MoE 模型，模型上下文为 32K. 作者还对模型进行 finetune 得到了 Mixtral 8x7B-Instruct, finetuning 包含 SFT 和 &lt;a class="link" href="https://maosong.website/p/notes-on-dpo/" target="_blank" rel="noopener"
&gt;DPO&lt;/a&gt; 两个阶段。&lt;/p&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;p&gt;模型架构与 &lt;a class="link" href="https://maosong.website/p/mixstral-7b/" target="_blank" rel="noopener"
&gt;Mistral-7B&lt;/a&gt; 基本相同，参数如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dim&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4096&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;n_layers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;head_dim&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hidden_dim&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;14336&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;n_heads&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;n_kv_heads&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;window_size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4096&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;context_len&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32768&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vocab_size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;num_experts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;top_k_experts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;MoE 的架构与 &lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt; 基本一致&lt;/p&gt;
&lt;h2 id="results"&gt;&lt;a href="#results" class="header-anchor"&gt;&lt;/a&gt;Results
&lt;/h2&gt;&lt;p&gt;作者探究了专家的 specialization, 结果有三点发现：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;不同专家对于不同 domain 的数据并没有出现 specialization&lt;/li&gt;
&lt;li&gt;在 math domain 上，专家的分布有一个明显的区别。&lt;/li&gt;
&lt;li&gt;连续的 token 往往会被分配到同一个专家上&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者在本文提出了 Mistral 8x7B, 一个 MoE 大语言模型&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2401.04088" target="_blank" rel="noopener"
&gt;Arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on olmoe</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/</link><pubDate>Sat, 01 Nov 2025 15:23:58 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;已有的模型如 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeek-MoE&lt;/a&gt;, &lt;a class="link" href="https://maosong.website/p/mixstral-8x7b/" target="_blank" rel="noopener"
&gt;Mixtral MoE&lt;/a&gt;, &lt;a class="link" href="https://maosong.website/search/?keyword=qwen1.5" target="_blank" rel="noopener"
&gt;Qwen1.5&lt;/a&gt; 等 MoE 模型基本只开源权重。也有一些开源的模型，比如 OpenMoE 等，但是开源信息不全。基于这个目的，作者提出了 olmoe 模型系列，包括 olmoe-7B-A1B 和 olmoe-7B-A1B-instruct 两个版本。&lt;/p&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;h3 id="pretraining"&gt;&lt;a href="#pretraining" class="header-anchor"&gt;&lt;/a&gt;Pretraining
&lt;/h3&gt;&lt;p&gt;模型的架构如下图所示，MoE 架构与 dense 架构不同的地方在于 decoder layer 中的 FFN 被替换为了 MoE layer.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-MoE_architecture.png"
width="1356"
height="912"
loading="lazy"
alt="Architecture of olmoe"
class="gallery-image"
data-flex-grow="148"
data-flex-basis="356px"
&gt;&lt;/p&gt;
&lt;p&gt;模型的配置如下表所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-config.png"
width="900"
height="1201"
loading="lazy"
alt="Model configuration"
class="gallery-image"
data-flex-grow="74"
data-flex-basis="179px"
&gt;&lt;/p&gt;
&lt;p&gt;训练的目标函数为&lt;/p&gt;
$$
\mathcal{L} = \mathcal{L}_{CE} +\alpha\mathcal{L}_{LB} +\beta\mathcal{L}_{RZ}
$$&lt;p&gt;其中 $\alpha,\beta$ 为系数， $\mathcal{L}_{CE}$, $\mathcal{L}_{LB}$ 以及 $\mathcal{L}_{RZ}$ 分别代表 cross-entropy loss, load balancing loss 以及 routing Z loss.&lt;/p&gt;
&lt;p&gt;预训练数据包括 DCLM 和 Dolma1.7 两个数据集的混合，作者将预训练数据集称为&lt;strong&gt;olmoe-mix&lt;/strong&gt;. 数据集的配比如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-composition-pretraining-data.png"
width="1147"
height="441"
loading="lazy"
alt="Composition of the pretraining data"
class="gallery-image"
data-flex-grow="260"
data-flex-basis="624px"
&gt;&lt;/p&gt;
&lt;h3 id="post-training"&gt;&lt;a href="#post-training" class="header-anchor"&gt;&lt;/a&gt;Post-training
&lt;/h3&gt;&lt;p&gt;在 post-training 时，作者将训练分为 instruction tuning 和 preference tuning 两个阶段，在 instruction dataset 中，作者加入了更多的代码和数学数据来提高对应的能力。数据集如下表所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-composition-post-training-data.png"
width="1208"
height="367"
loading="lazy"
alt="Post-training data"
class="gallery-image"
data-flex-grow="329"
data-flex-basis="789px"
&gt;&lt;/p&gt;
&lt;h2 id="ablation-study"&gt;&lt;a href="#ablation-study" class="header-anchor"&gt;&lt;/a&gt;Ablation Study
&lt;/h2&gt;&lt;h3 id="moe-settings"&gt;&lt;a href="#moe-settings" class="header-anchor"&gt;&lt;/a&gt;MoE Settings
&lt;/h3&gt;&lt;h4 id="moe-vs-dense"&gt;&lt;a href="#moe-vs-dense" class="header-anchor"&gt;&lt;/a&gt;MoE vs. Dense
&lt;/h4&gt;&lt;p&gt;作者对比了 MoE 模型和 dense 模型的训练效率，为了方便对比，作者使用 olmo-7B 和 olmo-1B 作为 baseline, 最终 olmoe 的总参数为 6.9B, 激活参数为 1.3B. 实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-MoE-vs-Dense-training-efficiency.png"
width="1155"
height="626"
loading="lazy"
alt="MoE vs. Dense"
class="gallery-image"
data-flex-grow="184"
data-flex-basis="442px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果发现，MoE 模型所需要的 token 或者 FLOPs 是 dense 模型的 $1/3$, 但是由于 MoE 模型需要额外的内存开销，因此从训练时间上来看，MoE 模型训练时间仅比 dense 模型快 $2$ 倍左右。&lt;/p&gt;
&lt;h4 id="expert-granularity"&gt;&lt;a href="#expert-granularity" class="header-anchor"&gt;&lt;/a&gt;Expert Granularity
&lt;/h4&gt;&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 提出使用细粒度的专家来提供更多的组合可能性。作者探究了不同的粒度对模型表现的影响，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-expert-granularity.png"
width="1446"
height="592"
loading="lazy"
alt="Expert granularity"
class="gallery-image"
data-flex-grow="244"
data-flex-basis="586px"
&gt;&lt;/p&gt;
&lt;p&gt;结果显示，当专家粒度从 8E-1A 扩展到 32E-4A 时，模型在 HellaSwag 上的表现提升了 $10\%$, 但是进一步扩展到 64E-8A 时，模型的表现提升不到 $2\%$, 这说明了无限制提升粒度对模型的提升越来越有限。在本文中，作者使用了 64 个专家。&lt;/p&gt;
&lt;h4 id="shared-experts"&gt;&lt;a href="#shared-experts" class="header-anchor"&gt;&lt;/a&gt;Shared Experts
&lt;/h4&gt;&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 提出使用共享专家来学习 common knowledge, 作者对这种方法进行了实验，结果如下图所示。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-shared-experts.png"
width="1156"
height="477"
loading="lazy"
alt="Shared experts"
class="gallery-image"
data-flex-grow="242"
data-flex-basis="581px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，加入一个 shared expert 之后，模型的表现没有变化，作者认为减少 routed expert 之后，模型的组合可能性降低为原来的 $10\%$ 左右。因此作者认为没有必要使用共享专家，因此作者在 olmoe 中没有采用共享专家这个方法。&lt;/p&gt;
&lt;h4 id="expert-choice-vs-token-choice"&gt;&lt;a href="#expert-choice-vs-token-choice" class="header-anchor"&gt;&lt;/a&gt;Expert Choice vs. Token Choice
&lt;/h4&gt;&lt;p&gt;作者探究了 routing 的策略，一个是 expert choice (EC), 另一种是 token choice (TC), 分别代表了每个 expert 选取固定的 token 数和每个 token 选取固定的 expert 数这两种情况。实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-routing-strategy.png"
width="1157"
height="450"
loading="lazy"
alt="Expert choice (EC) vs. token choice (TC)"
class="gallery-image"
data-flex-grow="257"
data-flex-basis="617px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，token choice 的表现明显更好。EC 虽然可以实现负载均衡。但是因为自回归模型在生成时是无法提前确定生成的 token 数的，因此 EC 很可能导致算力资源浪费或者是 token dropping. 在本文中，作者采用了 TC 这种策略。&lt;/p&gt;
&lt;h4 id="sparse-upcycling"&gt;&lt;a href="#sparse-upcycling" class="header-anchor"&gt;&lt;/a&gt;Sparse Upcycling
&lt;/h4&gt;&lt;p&gt;作者还对比了从零开始训练 MoE 与基于 dense model upcycling 的方式训练 MoE，sparse upcycling 的相关工作有 MiniCPM, &lt;a class="link" href="https://maosong.website/p/notes-on-qwen2/" target="_blank" rel="noopener"
&gt;Qwen2&lt;/a&gt; 以及 &lt;a class="link" href="https://maosong.website/p/mixstral-8x7b/" target="_blank" rel="noopener"
&gt;Mixtral MoE&lt;/a&gt;.结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-sparse-upcycling.png"
width="1440"
height="680"
loading="lazy"
alt="Sparse upcycling"
class="gallery-image"
data-flex-grow="211"
data-flex-basis="508px"
&gt;&lt;/p&gt;
&lt;p&gt;结果发现，upcycling 确实可以提高训练效率，但是这种方法的缺陷在于：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;upcycling 受 dense model 的超参数限制&lt;/li&gt;
&lt;li&gt;upcycling 的训练不是很稳定&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此在本文中作者没有采取 upcycling 的做法。&lt;/p&gt;
&lt;h4 id="load-balancing-loss"&gt;&lt;a href="#load-balancing-loss" class="header-anchor"&gt;&lt;/a&gt;Load Balancing Loss
&lt;/h4&gt;&lt;p&gt;作者还探究 Load Balancing loss 对模型表现的影响，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-load-balancing-loss.png"
width="1450"
height="532"
loading="lazy"
alt="Impact of applying a load balancing loss"
class="gallery-image"
data-flex-grow="272"
data-flex-basis="654px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，加入 load balancing loss 之后，模型的表现均超过了不加时的表现。&lt;/p&gt;
&lt;p&gt;作者进一步分析了不同专家在加/不加 load balancing loss 时的激活情况，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/ollmoe-load-balancing-expert-assignment.png"
width="1443"
height="566"
loading="lazy"
alt="Expert assignment during training"
class="gallery-image"
data-flex-grow="254"
data-flex-basis="611px"
&gt;&lt;/p&gt;
&lt;p&gt;结果显示，load balancing loss 确实可以让不同专家的激活概率大致相当。&lt;/p&gt;
&lt;h4 id="router-z-loss"&gt;&lt;a href="#router-z-loss" class="header-anchor"&gt;&lt;/a&gt;Router Z-loss
&lt;/h4&gt;&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/st-moe/" target="_blank" rel="noopener"
&gt;ST-MoE&lt;/a&gt; 提出了 Router z-loss 来提高 MOE 训练的稳定性和表现。其表达式如下所示&lt;/p&gt;
$$
\mathcal{L}_{RZ}(x) = \frac{1}{B}\sum_{i=1}^B\left(\log\sum_{j=1}^{N_E}\exp(x_i^{(i)})\right)^2
$$&lt;p&gt;实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-routing-z-loss.png"
width="1162"
height="419"
loading="lazy"
alt="Router z-loss"
class="gallery-image"
data-flex-grow="277"
data-flex-basis="665px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，加入 router Z-loss 之后，模型训练的稳定性有所提升。因此在本文中作者使用了这个 loss.&lt;/p&gt;
&lt;h3 id="general-pre-training-settings"&gt;&lt;a href="#general-pre-training-settings" class="header-anchor"&gt;&lt;/a&gt;General Pre-training Settings
&lt;/h3&gt;&lt;h4 id="initialization"&gt;&lt;a href="#initialization" class="header-anchor"&gt;&lt;/a&gt;Initialization
&lt;/h4&gt;&lt;p&gt;作者探究了不同初始化策略对模型训练的影响，结果发现使用 truncate normal initialization 的训练稳定性更高&lt;/p&gt;
&lt;h4 id="qk-norm"&gt;&lt;a href="#qk-norm" class="header-anchor"&gt;&lt;/a&gt;QK-Norm
&lt;/h4&gt;&lt;p&gt;作者探究了 &lt;a class="link" href="https://maosong.website/p/notes-on-qk-norm/" target="_blank" rel="noopener"
&gt;QK-norm&lt;/a&gt; 对模型训练的影响，结果发现 QK-norm 可以提高模型训练的稳定性，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-QK-norm-ablation.png"
width="1157"
height="306"
loading="lazy"
alt="ablation study on QK-Norm"
class="gallery-image"
data-flex-grow="378"
data-flex-basis="907px"
&gt;&lt;/p&gt;
&lt;h4 id="adamw-epsilon"&gt;&lt;a href="#adamw-epsilon" class="header-anchor"&gt;&lt;/a&gt;AdamW Epsilon
&lt;/h4&gt;&lt;p&gt;作者发现，在 &lt;a class="link" href="https://maosong.website/p/notes-on-adamw/" target="_blank" rel="noopener"
&gt;AdamW&lt;/a&gt; 优化器中，使用更小的 &lt;code&gt;eps&lt;/code&gt; 可以提高模型的表现，因此作者将 &lt;code&gt;eps&lt;/code&gt; 设置为 $1e-8$.&lt;/p&gt;
&lt;h4 id="adaptation-settings"&gt;&lt;a href="#adaptation-settings" class="header-anchor"&gt;&lt;/a&gt;Adaptation Settings
&lt;/h4&gt;&lt;p&gt;在 post-training 阶段，作者在三个方面进行了实验：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;是否加入 load balancing loss: 结论是不加，因为负载均衡在 pre-training 阶段已经实现了&lt;/li&gt;
&lt;li&gt;是否使用 annealing: 结论是使用，因为效果更好&lt;/li&gt;
&lt;li&gt;使用 DPO 还是 KTO, 结论是两种方法结果差不多&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;实验结果如下表所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-adaptation-experiments.png"
width="1105"
height="588"
loading="lazy"
alt="Adaptation experiments"
class="gallery-image"
data-flex-grow="187"
data-flex-basis="451px"
&gt;&lt;/p&gt;
&lt;h4 id="load-balancing-precision"&gt;&lt;a href="#load-balancing-precision" class="header-anchor"&gt;&lt;/a&gt;Load Balancing Precision
&lt;/h4&gt;&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 中提出使用 &lt;code&gt;float32&lt;/code&gt; 精度来进行 routing 的计算，作者通过实验发现，这一方法并不能提高模型训练的稳定性，因此作者没有采用这一策略。&lt;/p&gt;
&lt;h2 id="moe-analysis"&gt;&lt;a href="#moe-analysis" class="header-anchor"&gt;&lt;/a&gt;MoE Analysis
&lt;/h2&gt;&lt;h3 id="router-saturation"&gt;&lt;a href="#router-saturation" class="header-anchor"&gt;&lt;/a&gt;Router Saturation
&lt;/h3&gt;&lt;p&gt;作者探究了训练过程中激活的专家和训练结束后激活的专家的匹配程度，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-olmoe/olmoe-router-saturation.png"
width="1149"
height="393"
loading="lazy"
alt="Router saturation"
class="gallery-image"
data-flex-grow="292"
data-flex-basis="701px"
&gt;&lt;/p&gt;
&lt;p&gt;结果发现，训练 $1\%$ 的数据之后，就有 $40\%$ 的 routing 和训练完毕的 routing 一致，当训练 $40\%$ 的数据之后，这个比例提升到了 $80\%$.&lt;/p&gt;
&lt;p&gt;作者还发现，later layers 比 early layers 饱和更快，early layer, 特别是 layer 0, 饱和的非常慢。作者认为，这是 &lt;a class="link" href="https://maosong.website/p/notes-on-deepseekmoe/" target="_blank" rel="noopener"
&gt;DeepSeekMoE&lt;/a&gt; 放弃在第一层使用 MoE layer 的原因，因为 load balancing loss 收敛更慢。&lt;/p&gt;
&lt;h3 id="expert-co-activation"&gt;&lt;a href="#expert-co-activation" class="header-anchor"&gt;&lt;/a&gt;Expert Co-activation
&lt;/h3&gt;&lt;p&gt;作者分析了 expert 之间的互相依赖程度，作者通过可视化发现，不同的 expert 之间 co-activation 的比例比较小，说明 expert redundancy 比较低&lt;/p&gt;
&lt;h3 id="domain-specialization"&gt;&lt;a href="#domain-specialization" class="header-anchor"&gt;&lt;/a&gt;Domain Specialization
&lt;/h3&gt;&lt;p&gt;作者还探究了不同 expert 对于不同 domain 的 specialization 程度，作者发现对于 specialized domain 的数据，expert 会出现一定程度的 specialization, 但是对于通用 domain 的数据，expert 的 specialization 程度比较低。这个结论与 &lt;a class="link" href="https://maosong.website/p/mixstral-8x7b/" target="_blank" rel="noopener"
&gt;Mixtral MoE&lt;/a&gt; 的结论不同，作者认为这个原因是 &lt;a class="link" href="https://maosong.website/p/mixstral-8x7b/" target="_blank" rel="noopener"
&gt;Mixtral MoE&lt;/a&gt; 使用了 upcycling 的方式，这会限制模型的表现。因此，作者进一步强调 MoE 从零开始训练是一个更好的训练方式。&lt;/p&gt;
&lt;h3 id="vocabulary-specialization"&gt;&lt;a href="#vocabulary-specialization" class="header-anchor"&gt;&lt;/a&gt;Vocabulary Specialization
&lt;/h3&gt;&lt;p&gt;作者还探究了 vocabulary 中不同 token index 与激活专家之间的关系，结果发现 later layers 的 specialization 程度更高，这与 saturation 的趋势一致&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者在本文中提出了 olmoe, 一个全开源的 moe 大模型系列，作者详细介绍了针对 MoE 架构和通用架构的设计，为后来的模型架构设计提供了基础。&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2409.02060" target="_blank" rel="noopener"
&gt;arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>GShard</title><link>https://jiangyigithub.github.io/ai.github.io/p/gshard/</link><pubDate>Wed, 29 Oct 2025 11:22:39 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/gshard/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;作者认为，训练大规模的模型存在如下问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;缺乏有效的 Model parallelism 算法&lt;/li&gt;
&lt;li&gt;随着设备数的增加，训练时间与 model size 呈现超线性增长的关系&lt;/li&gt;
&lt;li&gt;(tensorflow) 在 nodes 数增多时，构建所需要的时间也大幅度增长&lt;/li&gt;
&lt;li&gt;在多个设备上 partition model 比较困难&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;作者在本文中构建了一个基于 sparse MoE 架构的 600B 模型。为了解决这些问题，作者作出了如下贡献：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;作者提出了基于 MoE 架构的模型，来减少计算和通信开销&lt;/li&gt;
&lt;li&gt;作者提出了 Gshard, 来自动化实现并行&lt;/li&gt;
&lt;li&gt;作者提出了 SPMD (single program multiple data) 来减少计算表示和编译的难度&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;p&gt;架构如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/gshard/GShard-model-architecture.png"
width="1118"
height="713"
loading="lazy"
alt="architecture of GShard"
class="gallery-image"
data-flex-grow="156"
data-flex-basis="376px"
&gt;&lt;/p&gt;
&lt;p&gt;其中激活专家个数为 2 个，MoE layer 和 FFN layer 交替出现。&lt;/p&gt;
&lt;p&gt;作者对 GATE 函数进行了如下优化：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;expert capacity. 每个 expert 都有一个处理 token 的上限值，超过该上限值之后 GATE 直接输出 0 进入下一层，假设 batch size 为 $N$, 专家个数为 $E$, 则该阈值定义为 $N/E$&lt;/li&gt;
&lt;li&gt;group dispatching. 将 token 拆分为 $G$ 个 group, 每个 group 并行处理，每个 group 里每个专家处理的 token 个数上限为 $N/(GE)$.&lt;/li&gt;
&lt;li&gt;Auxiliary loss. 作者使用了 &lt;a class="link" href="https://maosong.website/p/load-balancing-tutorial/" target="_blank" rel="noopener"
&gt;Load Balancing loss&lt;/a&gt; 来实现负载均衡&lt;/li&gt;
&lt;li&gt;Random routing. 作者选取了 top-2 的专家，当第二个专家的权重太小是，作者直接忽略第二个专家，简化为选取 top-1 的专家&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;算法运行如下所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/gshard/GShard-expert-computation.png"
width="1124"
height="917"
loading="lazy"
alt="expert computation of GShard"
class="gallery-image"
data-flex-grow="122"
data-flex-basis="294px"
&gt;&lt;/p&gt;
&lt;h2 id="parallel-implementation"&gt;&lt;a href="#parallel-implementation" class="header-anchor"&gt;&lt;/a&gt;Parallel Implementation
&lt;/h2&gt;&lt;p&gt;第一步是将算法转化为线性代数的方式，算法的代码如下所示&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;gates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;einsum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;GSM, ME-&amp;gt;GSE&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;combine_weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dispatch_mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Top2Gating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dispatched_expert_inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;einsum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;GSEC, GSM-&amp;gt;EGCM&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dispatch_mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reshaped_inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;einsum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;EGCM, EMH-&amp;gt;EGCH&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dispatched_expert_inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;expert_outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;einsum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;EGCH, EHM-&amp;gt;GECM&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;einsum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;GSEC, GECM-&amp;gt;GSM&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;combine_weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expert_outputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;第二步是通过 API 来实现并行执行&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Partition inputs along group (G) dim. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Replicate the gating weights&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;replicate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;gates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;einsum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;GSM, ME-&amp;gt;GSE&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;combine_weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dispatch_mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Top2Gating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gating_logits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dispatched_expert_inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;einsum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;GSEC, GSM-&amp;gt;EGCM&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dispatch_mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reshaped_inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Partition dispatched inputs along expert (E) dim.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dispatched_expert_inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dispatched_expert_inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;einsum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;EGCM, EMH-&amp;gt;EGCH&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dispatched_expert_inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;第三部就是基于 compiler infra 来基于 sharding annotation 自动化分割一个 computation graph.&lt;/p&gt;
&lt;h2 id="experiments"&gt;&lt;a href="#experiments" class="header-anchor"&gt;&lt;/a&gt;Experiments
&lt;/h2&gt;&lt;p&gt;作者在机器翻译的任务上训练了若干模型，结果发现：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;层数更多的模型表现更好&lt;/li&gt;
&lt;li&gt;提高 expert capacity 有效提高模型的表现&lt;/li&gt;
&lt;li&gt;使用更多的 expert 可以在 high-resourced 任务上提高表现&lt;/li&gt;
&lt;li&gt;dense 模型相比于 MoE 模型拥有更强的迁移能力&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;从训练效率上来看&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;层数更多的模型的 sample efficiency 也更高&lt;/li&gt;
&lt;li&gt;600B 的模型也可以在 4 天之内训练完毕&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;从内存使用效率上来看&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;层数相同时，weight memory 以及 activation memory 不随专家个数增加而增加&lt;/li&gt;
&lt;li&gt;专家个数比较少（128）时，模型可以达到 roofline performance 的 $70\%$, 专家个数比较多（2048）时，模型依然可以达到 roofline performance 的 $48\%$.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/gshard/GShard-execution-time-breakdown.png"
width="1064"
height="521"
loading="lazy"
alt="execution time of GShard"
class="gallery-image"
data-flex-grow="204"
data-flex-basis="490px"
&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者探究了如何提高大规模模型的训练效率，作者提出了基于 MoE 架构的模型，然后作者还设计了 GShard, 一个自动化分割大规模模型的深度学习模块。实现结果发现，增加模型 size 可以提高模型的表现。作者还发现，SPMD 是一个更好的提高计算效率的方法。&lt;/p&gt;
&lt;h2 id="reference"&gt;&lt;a href="#reference" class="header-anchor"&gt;&lt;/a&gt;Reference
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2006.16668" target="_blank" rel="noopener"
&gt;arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ST-MoE</title><link>https://jiangyigithub.github.io/ai.github.io/p/st-moe/</link><pubDate>Wed, 29 Oct 2025 11:19:37 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/st-moe/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;已有的工作如 &lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt; 和 &lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 均验证了 MoE 模型的有效性，但是他们的问题在于训练不稳定。&lt;/p&gt;
&lt;p&gt;因此，在本文中，作者就提出了 ST-MoE 来解决这个问题。作者的主要贡献如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;探究了如何平衡模型的表现与训练稳定性&lt;/li&gt;
&lt;li&gt;提出了 router Z-loss 来解决训练的不稳定性&lt;/li&gt;
&lt;li&gt;探究了如何设定 MoE 模型 fine tuning 时的超参数&lt;/li&gt;
&lt;li&gt;对 MoE 的性质进行了分析&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="training-stability"&gt;&lt;a href="#training-stability" class="header-anchor"&gt;&lt;/a&gt;Training Stability
&lt;/h2&gt;&lt;p&gt;作者发现，直接训练 MoE 模型会面临训练不稳定性的问题，实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/st-moe/ST-MoE-training-instabilities.png"
width="1040"
height="420"
loading="lazy"
alt="Training instabilities for sparse models."
class="gallery-image"
data-flex-grow="247"
data-flex-basis="594px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到不同的实验，一次训练崩溃，一次训练正常。&lt;/p&gt;
&lt;p&gt;作者接下来探究了如何提高训练的稳定性，作者有三点发现：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;大多数方法都可以提高训练稳定性，但是也会是的模型表现更差&lt;/li&gt;
&lt;li&gt;router Z-loss 可以在不损失模型表现的情况下提高训练的稳定性&lt;/li&gt;
&lt;li&gt;multiplicative components 如 RMSNorm 等可以提高模型表现，但是训练稳定性更差&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;作者构建了一个 baseline 的 MoE 模型，总专家个数为 $N=32$, 激活专家个数为 $K=2$, Transformer block 按照 4 个 block 为一组，每组里包含一个 MoE layer. 为了避免初始化带来的误差，作者使用 6 个随机数种子进行训练。&lt;/p&gt;
&lt;h3 id="multiplicative-components"&gt;&lt;a href="#multiplicative-components" class="header-anchor"&gt;&lt;/a&gt;Multiplicative Components
&lt;/h3&gt;&lt;p&gt;multiplicative components 指的是 GEGLU 和 RMSNorm 这些操作，其实验结果如下所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Fraction Stable&lt;/th&gt;
&lt;th&gt;Quality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;4/6&lt;/td&gt;
&lt;td&gt;$-1.755 \pm0.02$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remove GEGLU&lt;/td&gt;
&lt;td&gt;3/3&lt;/td&gt;
&lt;td&gt;$-1.849 \pm0.02$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remove RMS Norm. Scale Param&lt;/td&gt;
&lt;td&gt;3/3&lt;/td&gt;
&lt;td&gt;$-2.020 \pm0.06$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;结果发现，移除掉 multiplicative components 之后，模型训练变得稳定，但是效果也变差了。&lt;/p&gt;
&lt;h3 id="adding-noise"&gt;&lt;a href="#adding-noise" class="header-anchor"&gt;&lt;/a&gt;Adding Noise
&lt;/h3&gt;&lt;p&gt;接下来作者尝试了 &lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 中的 jitter noise 和 dropoout 方法，实验结果如下图所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Fraction Stable&lt;/th&gt;
&lt;th&gt;Quality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;4/6&lt;/td&gt;
&lt;td&gt;$-1.755 ± 0.02$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input jitter ($10^{-2}$)&lt;/td&gt;
&lt;td&gt;3/3&lt;/td&gt;
&lt;td&gt;$-1.777 \pm 0.03$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dropout (0.1)&lt;/td&gt;
&lt;td&gt;3/3&lt;/td&gt;
&lt;td&gt;$-1.822 \pm0.11$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;实验结果显示，加入噪声对模型的表现存在负面影响。&lt;/p&gt;
&lt;h3 id="constraining-activations"&gt;&lt;a href="#constraining-activations" class="header-anchor"&gt;&lt;/a&gt;Constraining Activations
&lt;/h3&gt;&lt;p&gt;作者接下来分析了以下 &lt;a class="link" href="https://maosong.website/p/switch-transformer/" target="_blank" rel="noopener"
&gt;Switch Transformer&lt;/a&gt; 中 router 存在的问题，作者发现尽管在 router 中使用 &lt;code&gt;float32&lt;/code&gt; 可以提高训练稳定性，但是这还不够，因此作者使用了如下的 router Z-loss:&lt;/p&gt;
$$
\mathcal{L}_z(x) = \frac1B\sum_{i=1}^B\left(\log\sum_{j=1}^N e^{x_j^{(i)}}\right)^2
$$&lt;p&gt;其中 $B, N$ 分别是 batch size 和专家个数，$x_j^{(i)}$ 代表了第 $j$ 个专家对 $i$ 个 token 的激活 logits. 通过增加这个 loss, 我们可以让 routing layer 的 logits 都在一个合理的范围内。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Fraction Stable&lt;/th&gt;
&lt;th&gt;Quality ($\uparrow$)&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;$4/6$&lt;/td&gt;
&lt;td&gt;$-1.755 \pm 0.02$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update clipping (clip = 0.1)&lt;/td&gt;
&lt;td&gt;$3/3$&lt;/td&gt;
&lt;td&gt;$-4.206 \pm 0.17$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Router Z-Loss&lt;/td&gt;
&lt;td&gt;$3/3$&lt;/td&gt;
&lt;td&gt;$-1.741 \pm 0.02$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以看到，加入 router Z-loss 之后，模型的稳定性和表现都有了提升。&lt;/p&gt;
&lt;p&gt;因此，在本文中，作者使用的损失函数为&lt;/p&gt;
$$
\mathcal{L} = \mathcal{L}_{CE} + \alpha \mathcal{L}_B + \beta \mathcal{L}_z
$$&lt;p&gt;其中 $\mathcal{L}_{CE}, \mathcal{L}_B$ 分别是 cross-entropy loss 和 Load Balancing loss, $\alpha,\beta$ 是对应 loss 的权重。&lt;/p&gt;
&lt;h3 id="numerical-precision"&gt;&lt;a href="#numerical-precision" class="header-anchor"&gt;&lt;/a&gt;Numerical Precision
&lt;/h3&gt;&lt;p&gt;接下来作者探究了数值精度对训练效率和稳定性的影响，作者发现使用低精度进行训练的优势有：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;通信开销更小&lt;/li&gt;
&lt;li&gt;计算消耗更小&lt;/li&gt;
&lt;li&gt;内存需求更小&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但是低精度进行训练的问题是存在严重的 roundoff error, 其示意图如下所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/st-moe/ST-MoE-numerical-precision-and-roundoff.png"
width="925"
height="249"
loading="lazy"
alt="Numerical precision formats and roundoff errors."
class="gallery-image"
data-flex-grow="371"
data-flex-basis="891px"
&gt;&lt;/p&gt;
&lt;h2 id="fine-tuning"&gt;&lt;a href="#fine-tuning" class="header-anchor"&gt;&lt;/a&gt;Fine-tuning
&lt;/h2&gt;&lt;p&gt;作者在本节探究了如何 fine-tune 一个 MoE 模型。&lt;/p&gt;
&lt;p&gt;作者首先通过实验给出了 MoE 模型容易过拟合的结论，实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/st-moe/ST-MoE-overfitting-of-MoE.png"
width="1138"
height="456"
loading="lazy"
alt="Sparse models are prone to overfit."
class="gallery-image"
data-flex-grow="249"
data-flex-basis="598px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，在两个人呢误伤，MoE 模型相比于 dense 模型都更容易过拟合。&lt;/p&gt;
&lt;p&gt;接下来作者探究了超参数特别是 batch size 和 learning rate 对模型表现的影响，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/st-moe/ST-MoE-hyperparameter-sensitivity.png"
width="1036"
height="416"
loading="lazy"
alt="Batch size and learning rate sensitivity"
class="gallery-image"
data-flex-grow="249"
data-flex-basis="597px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，与 dense 模型相反，MoE 模型需要更大的 batch size 以及更小的 learning rate.&lt;/p&gt;
&lt;h2 id="design-sparse-models"&gt;&lt;a href="#design-sparse-models" class="header-anchor"&gt;&lt;/a&gt;Design Sparse Models
&lt;/h2&gt;&lt;p&gt;首先作者分析了专家个数 $N$ 的设置，作者认为当专家个数超过 $256$ 之后，带来的收益就微乎其微了。并且，当专家个数增加之后，虽然算力没有变化，但是通信开销以及计算优化会变得更加困难。作者还认为，在 TPU 上，每个 core 应该进放置一个 expert&lt;/p&gt;
&lt;p&gt;作者还对 capacity factor 进行了实验，实验结果显示，提升 capacity factor 可以提高模型的表现。但是同时也会带来计算开销，从而让模型训练更慢，实验结果如下图所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Train CF&lt;/th&gt;
&lt;th&gt;Step Time (s) ($\downarrow$)&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ST-MoE-L&lt;/td&gt;
&lt;td&gt;1.25&lt;/td&gt;
&lt;td&gt;$2.397$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST-MoE-L&lt;/td&gt;
&lt;td&gt;2.0&lt;/td&gt;
&lt;td&gt;$2.447 (+7\%)$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST-MoE-32B&lt;/td&gt;
&lt;td&gt;1.25&lt;/td&gt;
&lt;td&gt;$4.244$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST-MoE-32B&lt;/td&gt;
&lt;td&gt;2.0&lt;/td&gt;
&lt;td&gt;$4.819 (+14\%)$&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;最终结论如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;使用 top-2 routing, 即激活 $K=2$ 个专家，capacity factor 设置为 $1.25$, 每个 core 上最多放置一个专家&lt;/li&gt;
&lt;li&gt;在评估时可以动态调整 capacity factor&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h2 id="tracing-tokens-through-the-model"&gt;&lt;a href="#tracing-tokens-through-the-model" class="header-anchor"&gt;&lt;/a&gt;Tracing Tokens through the Model
&lt;/h2&gt;&lt;p&gt;在这一节里，作者分析了 MoE 模型专家的性质。&lt;/p&gt;
&lt;p&gt;首先，作者发现，每一层里，至少有一个专家对于 sentinel token 比较敏感。并且，encoder 里的专家 specialization 更强，比如某些专家会负责 punctuation, verbs, proper names 等&lt;/p&gt;
&lt;p&gt;接下来，作者发现，专家的 specialization 在 decoder 里几乎没有，作者认为这是因为 target token distribution 不同导致的，即：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;decoding 是只有一小部分 token 被一个专家处理&lt;/li&gt;
&lt;li&gt;decoding 过程中大部分 token 都是 sentinel token&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此，每个 group 相比于 encoder 来说通常只 cover 一小部分的 semantic space&lt;/p&gt;
&lt;p&gt;encoder 和 decoder 专家的 specialization 实验结果如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Layer 1&lt;/th&gt;
&lt;th&gt;Layer 2&lt;/th&gt;
&lt;th&gt;Layer 3&lt;/th&gt;
&lt;th&gt;Layer 4&lt;/th&gt;
&lt;th&gt;Layer 5&lt;/th&gt;
&lt;th&gt;Layer 6&lt;/th&gt;
&lt;th&gt;Uniform (32-experts)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Encoder&lt;/td&gt;
&lt;td&gt;2.2&lt;/td&gt;
&lt;td&gt;1.8&lt;/td&gt;
&lt;td&gt;1.6&lt;/td&gt;
&lt;td&gt;1.7&lt;/td&gt;
&lt;td&gt;1.7&lt;/td&gt;
&lt;td&gt;1.2&lt;/td&gt;
&lt;td&gt;3.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decoder&lt;/td&gt;
&lt;td&gt;3.4&lt;/td&gt;
&lt;td&gt;3.4&lt;/td&gt;
&lt;td&gt;3.4&lt;/td&gt;
&lt;td&gt;3.4&lt;/td&gt;
&lt;td&gt;3.4&lt;/td&gt;
&lt;td&gt;3.4&lt;/td&gt;
&lt;td&gt;3.5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以看到，decoder 的专家分布和均匀分布差不多，这说明 decoder 里的专家 specialization 更弱。&lt;/p&gt;
&lt;p&gt;作者还探究了不同专家对于不同语言的敏感程度，结果发现，专家对于不同语言并没有出现明显的 specialization 现象，作者分析原因认为，输入一般只含有一种语言，因此各个专家均需要去处理对应语言的 token, 这就导致了专家对于不同语种的数据处理基本上没有太大差别。&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;在本文中，作者提出了 ST-MoE 系列 MoE 大语言模型，作者通过实验优化了 MoE 模型训练的不稳定性问题。&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2202.08906" target="_blank" rel="noopener"
&gt;Arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Switch Transformer</title><link>https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/</link><pubDate>Tue, 28 Oct 2025 09:38:12 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/</guid><description>&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://maosong.website/p/kaplan-scaling-law/" target="_blank" rel="noopener"
&gt;Kaplan scaling law&lt;/a&gt; 和 &lt;a class="link" href="https://maosong.website/p/chinchilla-scaling-law/" target="_blank" rel="noopener"
&gt;Chinchilla scaling law&lt;/a&gt; 已经给出了针对 dense transformer model 的 scaling law, 即在给定算力下如何找到最优的 model size 和 dataset size. 已有的工作如 T5 主要是扩展 dense model 来达到更高的表现, 但是他们的问题是对算力要求比较高。&lt;/p&gt;
&lt;p&gt;为了解决这个问题，作者尝试在不增加算力的情况下提升模型的参数量，为了达到这个目的，作者构建了基于 MoE 架构的模型 Switch Transformer.&lt;/p&gt;
&lt;p&gt;作者的主要贡献如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;提出了基于 MoE 架构的 Switch Transformer model&lt;/li&gt;
&lt;li&gt;探究了针对 MoE 架构的 scaling law&lt;/li&gt;
&lt;li&gt;将 MoE model 的能力蒸馏到 small dense model 里去&lt;/li&gt;
&lt;li&gt;若干提升训练效率和稳定性的技巧&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h2&gt;&lt;p&gt;Switch Transformer 的架构如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/Switch-Transformer-Architecture.png"
width="1130"
height="571"
loading="lazy"
alt="Architecture of Switch Transformer"
class="gallery-image"
data-flex-grow="197"
data-flex-basis="474px"
&gt;&lt;/p&gt;
&lt;h3 id="moe"&gt;&lt;a href="#moe" class="header-anchor"&gt;&lt;/a&gt;MoE
&lt;/h3&gt;&lt;p&gt;MoE 的定义见 &lt;a class="link" href="https://maosong.website/p/moe-tutorial/" target="_blank" rel="noopener"
&gt;MoE tutorial&lt;/a&gt;, 我们假设有 $N$ 个专家，其中激活 $K$ 个专家。&lt;/p&gt;
&lt;p&gt;之前的工作认为我们只有在激活 $&gt;2$ 个专家时，模型才能够比较好的训练，但是在本文中，作者决定只使用 1 个 expert, 也就是 $K=1$. 作者将激活一个专家的 layer 称为 &lt;strong&gt;Switch layer&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;作者认为 Switch Layer 有三个优势：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;router computation 现在只需要将每个 token route 到 1 个 expert&lt;/li&gt;
&lt;li&gt;每个专家的 capacity 更小，负载更加均衡&lt;/li&gt;
&lt;li&gt;routing 的实现更简单，且通信开销也降低了&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="efficient-sparse-routing"&gt;&lt;a href="#efficient-sparse-routing" class="header-anchor"&gt;&lt;/a&gt;Efficient Sparse Routing
&lt;/h3&gt;&lt;p&gt;作者首先定义了&lt;strong&gt;expert capacity&lt;/strong&gt;, 也就是每个 expert 处理的 token 数量，其定义如下&lt;/p&gt;
$$
\text{expert capacity} = \left(\frac{\text{tokens per batch}}{\text{number of experts}}\right) * \text{capacity factor}
$$&lt;p&gt;其示意图如下所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/Switch-Transformer-expert-capacity.png"
width="1269"
height="479"
loading="lazy"
alt="Token routing dynamics"
class="gallery-image"
data-flex-grow="264"
data-flex-basis="635px"
&gt;&lt;/p&gt;
&lt;p&gt;提升 capacity factor 可以减少 token overflow 的概率，但同时也会导致计算和内存的浪费。作者通过实验发现应该尽可能降低 dropped token 比例。&lt;/p&gt;
&lt;p&gt;为了平衡每个 expert 处理 token 的个数，作者设计了 load balancing loss, 见 &lt;a class="link" href="https://maosong.website/p/load-balancing-tutorial/" target="_blank" rel="noopener"
&gt;Load Balancing loss&lt;/a&gt; 来要求每个 expert 处理的 token 数基本一致。&lt;/p&gt;
&lt;h2 id="parallelism"&gt;&lt;a href="#parallelism" class="header-anchor"&gt;&lt;/a&gt;Parallelism
&lt;/h2&gt;&lt;p&gt;作者在本节介绍了针对 MoE 模型的并行策略，如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/Switch-Transformer-Parallelism.png"
width="1268"
height="746"
loading="lazy"
alt="Data and weight partitioning strategies"
class="gallery-image"
data-flex-grow="169"
data-flex-basis="407px"
&gt;&lt;/p&gt;
&lt;p&gt;这里，我们给定 notation 如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$B$&lt;/td&gt;
&lt;td&gt;Number of tokens in the batch.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$N$&lt;/td&gt;
&lt;td&gt;Number of total cores.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$n$&lt;/td&gt;
&lt;td&gt;Number of ways for data-parallelism sharding.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$m$&lt;/td&gt;
&lt;td&gt;Number of ways for model-parallelism sharding.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$E$&lt;/td&gt;
&lt;td&gt;Number of experts in Switch layers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$C$&lt;/td&gt;
&lt;td&gt;Expert capacity, the batch size of each expert.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;作者将一个 Logical mesh 分为两个维度，一个是 data-parallel sharding, 用 $n$ 表示，另一个是 model-parallel sharding, 用 $m$ 表示，从而总的 cores 数为 $N=n\times m$.&lt;/p&gt;
&lt;h3 id="data-parallelism"&gt;&lt;a href="#data-parallelism" class="header-anchor"&gt;&lt;/a&gt;Data Parallelism
&lt;/h3&gt;&lt;p&gt;对于 data prallelism 来说，每个 core 上的模型是一样的，而一个 batch 的数据被切分为了 $B/n$ 份，此时 $n=N$, $m=1$. 这种并行策略的好处是仅在 forward 和 backward 完成之后才会进行一次通信。&lt;/p&gt;
&lt;h3 id="model-parallelism"&gt;&lt;a href="#model-parallelism" class="header-anchor"&gt;&lt;/a&gt;Model Parallelism
&lt;/h3&gt;&lt;p&gt;对于 model parallelism, 每个 core 上的数据都是全部数据（通过拷贝得到），模型被 shard 到所有 core 上，此时 $n=1,m=N$, 这种情况下，每次 forward 或者 backward，都需要进行 $N$ 次通信（假设我们使用 pipeline parallelism）， 这种并行策略的好处是每个 core 上的计算压力小了，但是缺点是通信开销多了。&lt;/p&gt;
&lt;h3 id="model-and-data-parallelism"&gt;&lt;a href="#model-and-data-parallelism" class="header-anchor"&gt;&lt;/a&gt;Model and Data Parallelism
&lt;/h3&gt;&lt;p&gt;第三种总策略是同时进行 model parallelism 和 data parallelism, 这种情况下，每个 core 上保存 $B/n$ 的数据以及 shard 为 $m$ 份的 sharding weight.&lt;/p&gt;
&lt;h3 id="expert-and-data-parallelism"&gt;&lt;a href="#expert-and-data-parallelism" class="header-anchor"&gt;&lt;/a&gt;Expert and Data Parallelism
&lt;/h3&gt;&lt;p&gt;第四种策略是同时进行 expert parallelism 和 data parallelism, 作者在这里假设 $n=N$ 且 $E=n=N$, 也就是每个 core 上保留 $B/n$ 的数据, 然后还有一个对应的专家。&lt;/p&gt;
&lt;p&gt;首先，对于输入大小为 $[B,d]$ 的 tensor, 我们会进行拆分得到大小为 $[n, B/n, d]$ 的 tensor, 代表 $n$ 个设备上分别存储 $[B/n, d]$ 的数据，首先我们计算路由权重，得到&lt;/p&gt;
$$
[n,B/n, d]\times [d, E] \to [n, B/n, E]
$$&lt;p&gt;权重的每个值 $[i,j,k]$ 代表了第 $i$ 个 core 上,第 $j$ 个 token 分配一个第 $k$ 个专家的概率，我们对其进行 softmax 与 top-K 操作之后，就得到了对应的专家（注意 Switch Transformer 中的 $K=1$, 我们通过 one-hot 编码将其输出转化为一个二进制矩阵，大小为 $[n,B/n, E, C]$, 这里的每个值 $[i,j,k,l]$ 代表了第 $i$ 个 core 上,第 $j$ 个 token 分配给第 $k$ 个专家第 $l$ 个 token, 接下来我们再基于输入 &lt;code&gt;[n,B/n,d]&lt;/code&gt; 计算 core 到 expert 的数据，其大小为 &lt;code&gt;[n,E,C,d]&lt;/code&gt;, 计算方式为&lt;/p&gt;
$$
\mathrm{einsum}([n,B/n, d], [n,B/n,E,C], \mathrm{dim}=[B/n])
$$&lt;p&gt;里面的元素 &lt;code&gt;[i,j,k,:]&lt;/code&gt; 代表了第 $i$ 个设备路由到第 $j$ 个专家的第 $k$ ($k&lt;C$) 个 token.&lt;/p&gt;
&lt;p&gt;然后我们就可以执行 &lt;code&gt;all-to-all&lt;/code&gt; 通信来把对应的 token 传输给对应专家所在的设备上了，通信完成之后，每个设备上的专家对收集到的输入 token 进行计算，计算完之后，再通过 &lt;code&gt;all-to-all&lt;/code&gt; 通信来把输出传输给输入的设备。这样就完成了 MoE 模块的计算与通信&lt;/p&gt;
&lt;h3 id="expert-model-and-data-parallelism"&gt;&lt;a href="#expert-model-and-data-parallelism" class="header-anchor"&gt;&lt;/a&gt;Expert, Model and Data Parallelism
&lt;/h3&gt;&lt;p&gt;目前我们只是通过增加专家个数来提高模型的表现，但是 FLOPs 并没有增加，如果我们希望通过增加 FLOPs 来提高模型表现的话，我们需要增加 expert layer 的 model size, 这就涉及到了 Model parallelism, 此时的做法和前面提到的 Expert and Data Parallelism 一样，我们在收集到对应的设备的输入之后，再执行 model parallelism 就可以了。&lt;/p&gt;
&lt;h2 id="results"&gt;&lt;a href="#results" class="header-anchor"&gt;&lt;/a&gt;Results
&lt;/h2&gt;&lt;p&gt;基于以上改进，作者构建了 Switch Transformer, 模型训练的数据集为 C4, 训练的目标为 masked language modeling, 训练时，作者将 $15\%$ 的 token 替换为 &lt;code&gt;[mask]&lt;/code&gt; token.&lt;/p&gt;
&lt;p&gt;模型的配置如下表所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/Switch-Transformer-model-configuration.png"
width="1256"
height="252"
loading="lazy"
alt="Model configuration"
class="gallery-image"
data-flex-grow="498"
data-flex-basis="1196px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/Switch-Transformer-performance.png"
width="1206"
height="526"
loading="lazy"
alt="Performance of Switch Transformer"
class="gallery-image"
data-flex-grow="229"
data-flex-basis="550px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果发现&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Switch Transformer 的表现和训练效率都超过了 Dense model&lt;/li&gt;
&lt;li&gt;Switch transformer 的训练效率稍微优于使用 2 个 expert 的 MoE-Base 模型&lt;/li&gt;
&lt;li&gt;Switch transformer 在 low capacity factor 的场景下效果更好&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="scaling"&gt;&lt;a href="#scaling" class="header-anchor"&gt;&lt;/a&gt;Scaling
&lt;/h3&gt;&lt;p&gt;作者对比了 MoE 模型的 scaling law, 结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/Switch-Transformer-scaling-law.png"
width="1244"
height="497"
loading="lazy"
alt="Scaling law of MoE model"
class="gallery-image"
data-flex-grow="250"
data-flex-basis="600px"
&gt;&lt;/p&gt;
&lt;p&gt;可以看到，当我们增加专家个数的时候，模型的表现是持续提升的。并且当我们增加专家个数之后，模型的训练效率也有所提升。&lt;/p&gt;
&lt;p&gt;作者接下来在训练时间上进行了对比，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/Switch-Transformer-speed-comparison.png"
width="839"
height="672"
loading="lazy"
alt="Speed comparison of MoE model"
class="gallery-image"
data-flex-grow="124"
data-flex-basis="299px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果说明，switch transformer 的训练效率比 dense model 快 7 倍左右&lt;/p&gt;
&lt;p&gt;作者进一步对比 switch transformer 和更大的 dense 模型 (T5 large, $3.5\times$ FLOPs), 实验结果证明 Switch transformer 的训练效率仍然更高。&lt;/p&gt;
&lt;h3 id="switch-for-attention"&gt;&lt;a href="#switch-for-attention" class="header-anchor"&gt;&lt;/a&gt;Switch for Attention
&lt;/h3&gt;&lt;p&gt;作者还探究了在 attention layer 加入 MoE 的表现，结果发现尽管效果有提升，但是训练不稳定。&lt;/p&gt;
&lt;h3 id="no-token-left-behind"&gt;&lt;a href="#no-token-left-behind" class="header-anchor"&gt;&lt;/a&gt;No Token Left behind
&lt;/h3&gt;&lt;p&gt;由于 tensorflow 为一个静态计算框架，tensor 的形状必须预先定义好，因此必须为每个 expert 设定 capacity, 但是这样就会导致有些 token 被 drop 掉。&lt;/p&gt;
&lt;p&gt;因此，作者提出了 &amp;ldquo;No token left behind&amp;rdquo; 这种方法，来避免出现 token overflow 的情况。具体做法就是先按照正常的 router 逻辑进行计算，如果 router 选取出来的 top-K expert （本文中 $K=1$） 都已经满载了，则选取 &lt;code&gt;top-(K+1)&lt;/code&gt; expert 进行计算，作者发现这种方式可以保证大部分 token 都不会被 drop. 作者通过尝试之后发现，这种方法并没有带来提升。&lt;/p&gt;
&lt;h3 id="encouraging-exploration-across-experts"&gt;&lt;a href="#encouraging-exploration-across-experts" class="header-anchor"&gt;&lt;/a&gt;Encouraging Exploration Across Experts
&lt;/h3&gt;&lt;p&gt;作者还探究了不同选取 top-Kexpert 的方式，作者对比了以下三种方法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;argmax&lt;/li&gt;
&lt;li&gt;sampling from the softmax distribution&lt;/li&gt;
&lt;li&gt;input dropout on the incoming representation&lt;/li&gt;
&lt;li&gt;multiplicative jitter noise on the incoming representation&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;实验结果如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model Quality&lt;/th&gt;
&lt;th&gt;(Neg. Log Perp.) (↑)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Argmax&lt;/td&gt;
&lt;td&gt;-1.471&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sample softmax&lt;/td&gt;
&lt;td&gt;-1.570&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input dropout&lt;/td&gt;
&lt;td&gt;-1.480&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input jitter&lt;/td&gt;
&lt;td&gt;-1.468&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;作者发现，jitter 的效果最好，因此在本文中作者使用 jitter 来加入 noise.&lt;/p&gt;
&lt;h3 id="ablation-on-few-experts"&gt;&lt;a href="#ablation-on-few-experts" class="header-anchor"&gt;&lt;/a&gt;Ablation on Few Experts
&lt;/h3&gt;&lt;p&gt;作者还使用了更少的专家进行实验，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/Switch-Transformer-few-experts.png"
width="846"
height="666"
loading="lazy"
alt="Switch Transformer with few experts"
class="gallery-image"
data-flex-grow="127"
data-flex-basis="304px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，即使我们只使用少数 experts, 其模型表现仍然超过了 dense model 的表现，说明了 MoE 架构的有效性。&lt;/p&gt;
&lt;h3 id="downstream-model-performance"&gt;&lt;a href="#downstream-model-performance" class="header-anchor"&gt;&lt;/a&gt;Downstream Model Performance
&lt;/h3&gt;&lt;p&gt;作者还进一步探究了模型的预训练表现与 downstream task 任务上表现的关系，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/switch-transformer/Switch-Transformer-downstream-performance-scaling.png"
width="1257"
height="499"
loading="lazy"
alt="Upstream pre-trained quality to downstream model quality."
class="gallery-image"
data-flex-grow="251"
data-flex-basis="604px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，不管是 baseline 还是 Switch Transformer 其预训练的表现与下游任务上的表现都是正相关的。但是，作者也发现，MoE 模型在微调之后，其表现并不总是与预训练的表现正相关。因此，作者认为进一步探究这个机制是有必要的。&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者在本文中提出了 Switch Transformer，一个基于 MoE 架构的 Transformer 模型。作者通过改进 MoE 算法，大幅度提高了计算和通信效率，结果发现模型比 dense model 有更高的训练效率。&lt;/p&gt;
&lt;p&gt;作者认为，未来的工作有：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;提升大规模模型的训练稳定性&lt;/li&gt;
&lt;li&gt;解决 MoE 模型微调之后效果不如预期的问题&lt;/li&gt;
&lt;li&gt;探究针对 MoE 模型的 scaling law&lt;/li&gt;
&lt;li&gt;支持异构架构的 MoE 模型&lt;/li&gt;
&lt;li&gt;在 FFN 模块意外应用 MoE 架构&lt;/li&gt;
&lt;li&gt;将 Switch Transformer 扩展到其他的模态&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2101.03961" target="_blank" rel="noopener"
&gt;Arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on DeepSeekMoE</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseekmoe/</link><pubDate>Fri, 29 Aug 2025 11:03:12 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseekmoe/</guid><description>&lt;p&gt;DeepSeek 在 2024 年 1 月发布了 DeepSeekMoE, 一个解决 MoE 模型 specialization 不足以及 redundancy 问题的大模型系列。&lt;/p&gt;
&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;作者首先回顾了已有 MoE 模型的不足，主要有两点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;knowledge hybridity: 已有 MoE 模型的专家个数比较少，这就导致每个专家需要掌握更多样化的知识，提高了训练难度&lt;/li&gt;
&lt;li&gt;knowledge redundancy: 不同专家掌握的知识可能有重叠，从而导致了模型参数的 redundancy&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;为了解决这两个问题，作者提出了 DeepSeek-MoE, DeepSeek-MoE 主要做出了两点改变：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fine-Grained Expert Segmentation: 作者使用了更多的专家，来提高每个专家的 specialization, 降低训练成本&lt;/li&gt;
&lt;li&gt;Shared Expert Isolation: 作者在 Routing expert 的基础上，加入了 shared expert 来学习 common knowledge.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;作者在 2B-A0.6B 的模型进行了实验，结果显示模型表现超过了 &lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt;, 说明了 DeepSeekMoE 模型架构的有效性。&lt;/p&gt;
&lt;p&gt;作者还进一步将模型 scale 到了 16B-A2.8B 和 145B-A22B, 实验结果均验证了模型的 scaling 效果。&lt;/p&gt;
&lt;h2 id="method"&gt;&lt;a href="#method" class="header-anchor"&gt;&lt;/a&gt;Method
&lt;/h2&gt;&lt;h3 id="preliminary"&gt;&lt;a href="#preliminary" class="header-anchor"&gt;&lt;/a&gt;Preliminary
&lt;/h3&gt;&lt;p&gt;作者首先回顾了 transformer 架构，transformer 的第 $\ell$ 层 decode layer 可以表示为&lt;/p&gt;
$$
\begin{aligned}
u_{1:T}^{\ell} &amp;= \mathrm{self\_attention}(h_{1:T}^{\ell-1}) + h_{1:T}^{\ell}\\
h_t^\ell &amp;= \mathrm{FFN}(u_t^{\ell}) + u_t^{\ell}
\end{aligned}
$$&lt;p&gt;其中 $T$ 是 sequence length, $h_{1:T}^{\ell-1}$ 是第 $\ell-1$ 层 decoder layer 输出的 hidden states.&lt;/p&gt;
&lt;p&gt;接下来，我们可以将 dense 架构转换为 MoE 架构，MoE 架构与 dense 架构不同的地方在与 $\mathrm{FFN}$ 不再是 MLP, 而是一个 MoE 模块，其表达式如下&lt;/p&gt;
$$
\begin{aligned}
h_t^\ell &amp;= \sum_{i=1}^N\left(g_{i,t}\mathrm{FFN}_i(u_t^{\ell})\right) + u_t^{\ell}\\
g_{i,t} &amp;= \begin{cases}
s_{i,t,}, &amp;s_{i,t}\in\mathrm{Topk}(\{s_{j,t}\mid 1\leq j \leq N\},K)\\
0, &amp;\text{otherwise}
\end{cases}\\
s_{i,t,} &amp;= \mathrm{softmax}_i({u_t^{\ell}}^Te_i^{\ell})
\end{aligned}
$$&lt;p&gt;这里 $N$ 是专家的总个数， $K$ 是激活专家个数， $e_{i}^{\ell}$ 是 routing layer 的权重矩阵，$\mathrm{FFN}_i$ 是每个专家对应的 FFN.&lt;/p&gt;
&lt;h3 id="deepseekmoe-architecutre"&gt;&lt;a href="#deepseekmoe-architecutre" class="header-anchor"&gt;&lt;/a&gt;DeepSeekMoE Architecutre
&lt;/h3&gt;&lt;p&gt;DeepSeekMoE 架构如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseekmoe/DeepSeekMoE-architecture.png"
width="1200"
height="586"
loading="lazy"
alt="Architecture of DeepSeekMoE"
class="gallery-image"
data-flex-grow="204"
data-flex-basis="491px"
&gt;&lt;/p&gt;
&lt;p&gt;相比于其他 MoE 架构，DeepSeekMoE 主要做了以下几点改变。&lt;/p&gt;
&lt;h4 id="fine-grained-expert-segmentation"&gt;&lt;a href="#fine-grained-expert-segmentation" class="header-anchor"&gt;&lt;/a&gt;Fine-Grained Expert Segmentation
&lt;/h4&gt;&lt;p&gt;作者首先解决了每个专家学习内容过多的问题。作者的做法就是将每个 expert FFN 分割为 $m$ 个更小的专家，具体做法就是将 FFN intermediate hidden size 降低为原来的 $1/m$. 这样的话就可以在不增加模型参数量的情况下提高模型的表现。修正后的 MoE 模块为&lt;/p&gt;
$$
\begin{aligned}
h_t^\ell &amp;= \sum_{i=1}^{mN}\left(g_{i,t}\mathrm{FFN}_i(u_t^{\ell})\right) + u_t^{\ell}\\
g_{i,t} &amp;= \begin{cases}
s_{i,t,}, &amp;s_{i,t}\in\mathrm{Topk}(\{s_{j,t}\mid 1\leq j \leq mN\},mK)\\
0, &amp;\text{otherwise}
\end{cases}\\
s_{i,t,} &amp;= \mathrm{softmax}_i({u_t^{\ell}}^Te_i^{\ell})
\end{aligned}
$$&lt;p&gt;可以看到，现在我们一共有 $mN$ 个专家，激活专家个数为 $mK$ 个。作者认为，通过提高专家的粒度，我们可以有效增加专家组合的可能性，这就提高了最终的组合多样性。&lt;/p&gt;
&lt;h4 id="shared-expert-isolation"&gt;&lt;a href="#shared-expert-isolation" class="header-anchor"&gt;&lt;/a&gt;Shared Expert Isolation
&lt;/h4&gt;&lt;p&gt;接下来，作者介绍了解决不同专家学习到重复知识的问题，作者的做法是在 routing Expert 的基础上加入 Shared expert. 也就是说，有固定几个专家始终都会被激活，这部分专家复杂学习通用知识，从而减少知识冗余。增加 shared expert 之后的 MoE 模块为&lt;/p&gt;
$$
\begin{aligned}
h_t^\ell &amp;= \sum_{i=1}^{K_s}\mathrm{FFN}_i(u_t^{\ell})+\sum_{i=K_s+1}^{mN}\left(g_{i,t}\mathrm{FFN}_i(u_t^{\ell})\right) + u_t^{\ell}\\
g_{i,t} &amp;= \begin{cases}
s_{i,t,}, &amp;s_{i,t}\in\mathrm{Topk}(\{s_{j,t}\mid K_s+1\leq j \leq mN\},mK-K_s)\\
0, &amp;\text{otherwise}
\end{cases}\\
s_{i,t,} &amp;= \mathrm{softmax}_i({u_t^{\ell}}^Te_i^{\ell})
\end{aligned}
$$&lt;p&gt;此时，模型中一共包含 $K_s$ 个共享专家，$mN-K_s$ 个 routing expert, 其中激活专家个数为 $mK-K_s$.&lt;/p&gt;
&lt;h4 id="load-balancing-loss"&gt;&lt;a href="#load-balancing-loss" class="header-anchor"&gt;&lt;/a&gt;Load Balancing Loss
&lt;/h4&gt;&lt;p&gt;接下来，作者解决了训练时的 load imbalance 问题，作者提出了两个 loss 来分别解决不同层面的 load imbalance 问题。&lt;/p&gt;
&lt;p&gt;首先，在 expert 层面，作者使用了如下的 load balancing loss:&lt;/p&gt;
$$
\mathcal{L} = \alpha_1\sum_{i=1}^{N'}f_iP_i
$$&lt;p&gt;其中 $\alpha_1$ 是超参数，&lt;/p&gt;
$$
f_i = \frac{N'}{K'T}\sum_{i=1}^{N'}\mathbb{1}(\text{Token }i \text{ selects Expert }i),\quad P_i = \frac{1}{T}\sum_{t=1}^Ts_{i,t}
$$&lt;p&gt;分别为以及分配给第 $i$ 个专家的 token 比例以及概率之和。$N'=mN-K_s$, $K'=mK-K_s$. $\mathbb{1}(\cdot)$ 是 indicator function.&lt;/p&gt;
&lt;p&gt;其次，在 device 层面，作者也是用了 load balancing loss 来减少不同设备之间不必要的通信。作者将 routed experts 分为 $D$ 个 group $\mathcal{E}_1,\dots,\mathcal{E}_D$, 然后每个设备部署一个 group, group level 的 load balancing loss 定义如下：&lt;/p&gt;
$$
\mathcal{L} = \alpha_2\sum_{i=1}^D f_i' P_i'
$$&lt;p&gt;其中 $\alpha_2$ 是超参数，&lt;/p&gt;
$$
f_i' = \frac{1}{|\mathcal{E}_i|}\sum_{j\in\mathcal{E}_i}f_i,\quad P_i' = \sum_{j\in\mathcal{E}_i}P_i
$$&lt;p&gt;实际中，作者使用了一个较小的 $\alpha_1$ 来避免 routing collapse, 使用了一个较大的 $\alpha_2$ 来提高 Device 层面的负载均衡。&lt;/p&gt;
&lt;h3 id="training"&gt;&lt;a href="#training" class="header-anchor"&gt;&lt;/a&gt;Training
&lt;/h3&gt;&lt;p&gt;作者使用了中英文数据进行训练，tokenizer 基于 BPE 算法，vocab size 为 8K. 模型训练基于 HAI-LLM.训练时使用了 TP, DP, PP, EP 等并行策略。&lt;/p&gt;
&lt;p&gt;2B, 16B, 145B 模型的参数如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;2B&lt;/th&gt;
&lt;th&gt;16B&lt;/th&gt;
&lt;th&gt;145B&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;total params&lt;/td&gt;
&lt;td&gt;2B&lt;/td&gt;
&lt;td&gt;16.4B&lt;/td&gt;
&lt;td&gt;144.6B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;activated params&lt;/td&gt;
&lt;td&gt;0.3B&lt;/td&gt;
&lt;td&gt;2.8B&lt;/td&gt;
&lt;td&gt;22.2B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hidden size&lt;/td&gt;
&lt;td&gt;1280&lt;/td&gt;
&lt;td&gt;2048&lt;/td&gt;
&lt;td&gt;4096&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;layers&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;attention heads&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;head dimension&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;routed experts&lt;/td&gt;
&lt;td&gt;63&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;activated experts&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shared experts&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;training tokens&lt;/td&gt;
&lt;td&gt;100B&lt;/td&gt;
&lt;td&gt;2T&lt;/td&gt;
&lt;td&gt;245B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="experiments"&gt;&lt;a href="#experiments" class="header-anchor"&gt;&lt;/a&gt;Experiments
&lt;/h2&gt;&lt;h3 id="alignment"&gt;&lt;a href="#alignment" class="header-anchor"&gt;&lt;/a&gt;Alignment
&lt;/h3&gt;&lt;p&gt;作者针对 DeepseekMoE 16B 进行了微调，微调使用了 &lt;strong&gt;1.4M&lt;/strong&gt; 的训练样本，覆盖了 math, code, QA, reasoning 等任务。&lt;/p&gt;
&lt;h3 id="ablation-study"&gt;&lt;a href="#ablation-study" class="header-anchor"&gt;&lt;/a&gt;Ablation Study
&lt;/h3&gt;&lt;p&gt;作者在 2B 的模型上进行了 ablation study.&lt;/p&gt;
&lt;p&gt;首先，作者探究了细粒度专家和共享专家的有效性，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseekmoe/DeepSeekMoE-ablation-experts.png"
width="1197"
height="552"
loading="lazy"
alt="Ablation on experts"
class="gallery-image"
data-flex-grow="216"
data-flex-basis="520px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，与 &lt;a class="link" href="https://maosong.website/p/gshard/" target="_blank" rel="noopener"
&gt;GShard&lt;/a&gt; 相比，&lt;strong&gt;使用共享专家可以有效提高模型的表现&lt;/strong&gt;。并且，&lt;strong&gt;使用更细粒度的专家也可以进一步提高模型的表现&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;作者还探究了共享专家与路由专家的比例，作者分别使用不同的比例进行实验，结果发现共享专家：路由专家个数为 1：3 的时候模型效果最好。&lt;/p&gt;
&lt;p&gt;作者还探究了模型的泛化性，作者 mask 掉一部分概率最高的 routing expert, 然后从剩下的专家里进行 topK 的挑选，然后作者比较模型和 GShard 的表现，结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseekmoe/DeepSeekMoE-ablation-expert-specialization.png"
width="737"
height="526"
loading="lazy"
alt="Ablation study on expert specialization"
class="gallery-image"
data-flex-grow="140"
data-flex-basis="336px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，&lt;strong&gt;DeepSeekMoE 对于 mask 操作更敏感，这说明 DeepSeekMoE 模型中专家的 specialization 更强。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;作者还探究了 mask 掉共享专家对模型表现的影响，结果显示&lt;strong&gt;共享专家与路由专家之间的 overlap 很小，去掉共享专家之后，模型表现会变差。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;作者进一步分析了共享专家与路由专家组合的有效性。作者探究 DeepSeekMoE 是否可以使用更少的路由专家来获取知识。作者通过使用不同的 activated routed experts 来进行实验，实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-deepseekmoe/DeepSeekMoE-ablation-number-activated-experts.png"
width="730"
height="524"
loading="lazy"
alt="Ablation study on activated routed experts"
class="gallery-image"
data-flex-grow="139"
data-flex-basis="334px"
&gt;&lt;/p&gt;
&lt;p&gt;实验结果显示，DeepSeekMoE 仅需激活 4 个路由专家，就可以达到与 GShard 相同的表现。&lt;strong&gt;这说明了 DeepSeekMoE 模型中每个专家可以学习到更准确的知识。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者在本文中提出了 DeepSeekMoE 架构，来提高 MoE 模型中专家的利用效率。为了达到这一点，作者首先使用了更细粒度的专家，降低每个专家的学习成本，然后，作者使用了共享专家，来降低不同专家之间的知识冗余。作者先在 2B 的模型上验证了方法的有效性，然后作者将模型 scale 到了 16B 和 125B。结果显示模型的效果均超过了以前的工作。&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://arxiv.org/abs/2401.06066" target="_blank" rel="noopener"
&gt;arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Notes on Hunyuan-Large</title><link>https://jiangyigithub.github.io/ai.github.io/p/notes-on-hunyuan-large/</link><pubDate>Wed, 06 Aug 2025 16:46:32 +0800</pubDate><guid>https://jiangyigithub.github.io/ai.github.io/p/notes-on-hunyuan-large/</guid><description>&lt;p&gt;腾讯混元提出了 Hunyuan-Large, 一个 389B-A52B 的 MoE LLM, 上下文长度为 256K.&lt;/p&gt;
&lt;h2 id="introduction"&gt;&lt;a href="#introduction" class="header-anchor"&gt;&lt;/a&gt;Introduction
&lt;/h2&gt;&lt;p&gt;Hunyuan-Large 主要在三个方向进行了改进：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用了更高质量的合成数据：模型使用了 7T 的预训练数据，其中包含了 1.5T 的合成数据&lt;/li&gt;
&lt;li&gt;优化了模型的架构：作者提出了 KV cache compression, recycle routing, expert-specific learning rate scaling 策略来提高模型的表现&lt;/li&gt;
&lt;li&gt;探究了 MoE 模型的 scaling law: 作者探究了 MoE 模型的 scaling law&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="pre-training"&gt;&lt;a href="#pre-training" class="header-anchor"&gt;&lt;/a&gt;Pre-training
&lt;/h2&gt;&lt;h3 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h3&gt;&lt;p&gt;Hunyuan-Large 是一个基于 MoE 的 transformer 架构，attention 部分使用了 &lt;a class="link" href="https://maosong.website/p/notes-on-gqa/" target="_blank" rel="noopener"
&gt;GQA&lt;/a&gt;, position encoding 使用了 RoPE, MLP 的激活函数为 SwiGLU. 在 MoE layer 中，Hunyuan-Large 使用了 shared experts. 最终，模型的配置如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-hunyuan-large/hunyuan-large-architecture-config.png"
width="654"
height="399"
loading="lazy"
alt="Configuration of Hunyuan-Large"
class="gallery-image"
data-flex-grow="163"
data-flex-basis="393px"
&gt;&lt;/p&gt;
&lt;h4 id="kv-cache-compression"&gt;&lt;a href="#kv-cache-compression" class="header-anchor"&gt;&lt;/a&gt;KV Cache Compression
&lt;/h4&gt;&lt;p&gt;为了减少 KV cache 的内存开销，作者使用了两个技巧：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GQA: 通过共享 KV projection 的参数，来减少内存访问次数&lt;/li&gt;
&lt;li&gt;[[CLA]]: 在相邻的 layer 中共享 KV cache, 来进一步压缩 KV cache&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在 Hunyuan-Large 中，作者将 GQA 的 group size 设置为 8, 然后相邻的 2 层 layer 共享 KV cache.&lt;/p&gt;
&lt;p&gt;假设输入的 batch size 为 $B$, sequence 长度为 $L$, layers 个数为 $\ell$, attention heads 个数为 $h$, KV heads 个数为 $h_{kv}$, 每个 head 的 hidden size 为 $d_h$, 则每一层的 GQA 需要缓存 $K,V\in\mathbb{R}^{B\times _{kv}\times L\times d_h}$， KV cache 的总占用为&lt;/p&gt;
$$
2\times B\times h_{kv}\times L\times d_h \times \ell \times 2=4BLh_{kv}d_h\ell
$$&lt;p&gt;第一个 $2$ 是因为同时缓存 K 和 V, 第二个 $2$ 是因为一般使用 &lt;code&gt;bfloat16&lt;/code&gt; 数据格式。&lt;/p&gt;
&lt;p&gt;对于 CLA, 因为连续两层共享相同的 KV cache，因此结果除以 2; 对于 MHA, $h_{kv}=h$; 对于 &lt;a class="link" href="https://maosong.website/p/notes-on-mqa/" target="_blank" rel="noopener"
&gt;MQA&lt;/a&gt;, $h_{kv}=1$. 最后，KV cache 的内存占用如下表所示&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attention Mechanism&lt;/th&gt;
&lt;th&gt;KV Cache Memory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MHA&lt;/td&gt;
&lt;td&gt;$4BLhd_h\ell$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GQA&lt;/td&gt;
&lt;td&gt;$4BLh_{kv}d_h\ell$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MQA&lt;/td&gt;
&lt;td&gt;$4BLd_h\ell$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLA&lt;/td&gt;
&lt;td&gt;$2BLhd_h\ell$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GQA+CLA&lt;/td&gt;
&lt;td&gt;$2BLh_{kv}d_h\ell$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以看到，使用 GQA+CLA 之后，模型的 kv cache 占用相比于 MHA 变成了&lt;/p&gt;
$$
\frac{2BLh_{kv}d_h\ell}{4BLhd_h\ell}=\frac{1}{16}
$$&lt;p&gt;也就是说，Hunyuan-Large 的 KV cache 内存占用下降到了 MHA 的 1/16.&lt;/p&gt;
&lt;h4 id="expert-routing-strategy"&gt;&lt;a href="#expert-routing-strategy" class="header-anchor"&gt;&lt;/a&gt;Expert Routing Strategy
&lt;/h4&gt;&lt;p&gt;作者采用了 shared expert + activated expert 的形式，其中包含 1 个 shared expert, 然后从 16 个专家里激活 1 个专家。&lt;/p&gt;
&lt;p&gt;为了解决 MoE 中 expert capacity 难以设定的问题，作者提出了一个 recycle routing 的策略，基本思想就是，当 activated expert 的容量超出限制时，会从其他没有超出容量限制的专家里重新进行激活。&lt;/p&gt;
&lt;h4 id="expert-specific-learning-rate-scaling"&gt;&lt;a href="#expert-specific-learning-rate-scaling" class="header-anchor"&gt;&lt;/a&gt;Expert Specific Learning Rate Scaling
&lt;/h4&gt;&lt;p&gt;作者使用 AdamW 作为优化器，作者探讨了如何设定学习率。基于之前的工作，最优的学习率与 batch size 相关：&lt;/p&gt;
$$
\epsilon_{\mathrm{opt}}(B) = \frac{2\epsilon_{\max}}{\sqrt{\frac{\mathcal{B}_{\mathrm{noise}}}{B}}+\sqrt{\frac{B}{\mathcal{B}_{\mathrm{noise}}}}}
$$&lt;p&gt;这里 $\epsilon_{\max}$ 是 AdamW 的学习率, $\mathcal{B}_{\mathrm{noise}}$ 是训练速度与数据使用效率的一个平衡因子。&lt;/p&gt;
&lt;p&gt;但是，在 MoE 模型中，不同专家处理的 token 是不一样的。基于 load balancing loss, shared expert 和 activated expert 处理的 token 个数比例大概是 $n :1$, 其中 $n=16$ 是总的专家个数。因此，对于 shared expert, 作者使用 $\epsilon_{\mathrm{opt}}(B)$ 作为学习率，然后对于 activated expert, 作者使用 $\epsilon_{\mathrm{opt}}(B/n)$ 作为学习率。&lt;/p&gt;
&lt;h3 id="data"&gt;&lt;a href="#data" class="header-anchor"&gt;&lt;/a&gt;Data
&lt;/h3&gt;&lt;p&gt;预训练数据包括收集和合成。收集的数据主要来自互联网，覆盖中英文两种语言。&lt;/p&gt;
&lt;p&gt;合成数据包括 4 个步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;instruction generation: 作者使用高质量的语料作为 seed, 然后生成多样的 instruction 覆盖不同的 domain&lt;/li&gt;
&lt;li&gt;Instruction evolution: refine 上一步生成的 instruction&lt;/li&gt;
&lt;li&gt;Response generation: 使用 specialized model 来生成回答&lt;/li&gt;
&lt;li&gt;response filtering: 对生成的回答进行过滤&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;数据合成的流程如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-hunyuan-large/Hunyuan-large-data-synthesis.png"
width="1126"
height="565"
loading="lazy"
alt="Data synthesis pipeline"
class="gallery-image"
data-flex-grow="199"
data-flex-basis="478px"
&gt;&lt;/p&gt;
&lt;p&gt;tokenizer 大小为 128K, 由 tittoken tokenizer 和额外的 28K token 组成。&lt;/p&gt;
&lt;h3 id="pre-training-recipe"&gt;&lt;a href="#pre-training-recipe" class="header-anchor"&gt;&lt;/a&gt;Pre-training Recipe
&lt;/h3&gt;&lt;p&gt;作者首先探究了一个针对 MoE 模型的 scaling law. 结果发现，最优的激活参数量为 58.1B, training token 个数为 5.6T. 经过平滑之后，作者最终将模型的激活参数两定为 &lt;strong&gt;52B&lt;/strong&gt;, 训练 token 数定为 $7T$.&lt;/p&gt;
&lt;p&gt;在训练时，作者将学习率分为了 3 个 stage:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;warmup phase&lt;/li&gt;
&lt;li&gt;gradual decay phase&lt;/li&gt;
&lt;li&gt;concise annealing phase&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;上面的三个 stage 结束之后，作者加入了两个 stage 来扩展模型的上下文长度从 32K 扩展到 256K. 训练的数据包括 75% 的短文本和 25% 的长文本。两个 stage 训练的 token 数均为 $10B$ 左右。&lt;/p&gt;
&lt;h2 id="post-training"&gt;&lt;a href="#post-training" class="header-anchor"&gt;&lt;/a&gt;Post-training
&lt;/h2&gt;&lt;p&gt;post-training 分为 SFT 和 RLHF 两个阶段。&lt;/p&gt;
&lt;h3 id="sft"&gt;&lt;a href="#sft" class="header-anchor"&gt;&lt;/a&gt;SFT
&lt;/h3&gt;&lt;p&gt;SFT 数据副高 math, coding, logical reasoning 等 domain, 包含超过 1M 的数据。&lt;/p&gt;
&lt;p&gt;SFT 训练了 3 个 epoch, 学习率从 2e-5 降低到 2e-6, 为了避免 overfitting, 作者使用了 0.1 的 attention dropout 和 0.2 的 hidden dropout.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!tip]
作者发现，MoE 模型可以从 dropout 中学习到更多&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="rlhf"&gt;&lt;a href="#rlhf" class="header-anchor"&gt;&lt;/a&gt;RLHF
&lt;/h3&gt;&lt;p&gt;作者使用 &lt;a class="link" href="https://maosong.website/p/notes-on-dpo/" target="_blank" rel="noopener"
&gt;DPO&lt;/a&gt; 来进行 RLHF, 作者同时使用了 offline 和 online 的数据来进行训练，前者是收集的数据，后者是当前 policy 生成的数据。与 LLaMA 3 和 Nemotron-4 一样，为了提高训练稳定性，对于 chosen reponse, 作者使用了 SFT loss.&lt;/p&gt;
&lt;p&gt;作者还是用了 exponential moving average 策略来减少 reward hacking 现象，以及降低 alignment tax.&lt;/p&gt;
&lt;h2 id="experiment"&gt;&lt;a href="#experiment" class="header-anchor"&gt;&lt;/a&gt;Experiment
&lt;/h2&gt;&lt;p&gt;对于 base 版本，作者对比了 &lt;a class="link" href="https://maosong.website/p/notes-on-llama3/" target="_blank" rel="noopener"
&gt;LLaMA 3&lt;/a&gt;, &lt;a class="link" href="https://maosong.website/p/mixstral-8x7b/" target="_blank" rel="noopener"
&gt;Mixtral&lt;/a&gt;, &lt;a class="link" href="https://maosong.website/p/notes-on-deepseek-v2/" target="_blank" rel="noopener"
&gt;DeepSeek-V2&lt;/a&gt;, 实验结果如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-hunyuan-large/Hunyuan-large-base-performance.png"
width="1135"
height="761"
loading="lazy"
alt="Performance of Hunyuan-Large-Base"
class="gallery-image"
data-flex-grow="149"
data-flex-basis="357px"
&gt;&lt;/p&gt;
&lt;p&gt;Instruction 版本的表现如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jiangyigithub.github.io/ai.github.io/p/notes-on-hunyuan-large/Hunyuan-large-intruction-performance.png"
width="1178"
height="538"
loading="lazy"
alt="Performance of Hunyuan-Large Instuct"
class="gallery-image"
data-flex-grow="218"
data-flex-basis="525px"
&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;作者提出了 Hunyuan-Large, 一个 389B-A52B 的 LLM, 上下文长度为 256K. 作者详细介绍了模型的架构，数据和训练方式。&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/pdf/2411.02265" target="_blank" rel="noopener"
&gt;arxiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>