介绍
今天,我们推出 Qwen 系列的首个 MoE 模型,Qwen1.5-MoE-A2.7B。它仅拥有 27 亿个激活参数,但其性能却能与当前最先进的 70 亿参数模型,如 Mistral 7B 和 Qwen1.5-7B 相媲美。相较于包含 65 亿个 Non-Embedding 参数的 Qwen1.5-7B,Qwen1.5-MoE-A2.7B 只有 20 亿个 Non-Embedding 参数,约为原模型大小的三分之一。此外,相比 Qwen1.5-7B,Qwen1.5-MoE-A2.7B 的训练成本降低了 75%,推理速度则提升至 1.74 倍。
模型结构
我们在 Qwen1.5-MoE 模型中采用了特别设计的 MoE 架构。通常情况下,如 Mixtral 等方法所示,每个 transformer block 中的 MoE 层会配备 8 个 expert,并采用 top-2 门控策略进行 routing。这种配置还存在很大的优化空间。我们对这一架构进行了多项改进:
Finegrained experts
DeepSeek-MoE 和 DBRX 已经证明了 finegrained experts 的有效性。从 FFN 层过渡到 MoE 层时,我们一般只是简单地复制多次 FFN 来实现多个 expert。而 finegrained experts 的目标是在不增加参数数量的前提下生成更多 expert。为了实现这一点,我们将单个 FFN 分割成几个部分,每个部分作为一个独立的 expert。我们设计了具有总共 64 个 expert 的 MoE,对比其他配置,我们认为这个实现能达到效果和效率的最优。
初始化
模型初始化阶段至关重要。初步实验表明,从零开始训练 MoE 模型可能效率低下,且难以提升至预期的最优性能水平。因此,我们首先利用已有的 Qwen-1.8B,将其改造为 Qwen1.5-MoE-A2.7B。此外,在初始化阶段引入随机性可以显著加快收敛速度,并在整个预训练过程中带来更好的整体性能表现。
新的 routing 机制
目前,一个明显的趋势是在 MoE 中实现共享 expert 与 routing expert。从更宏观的角度看,这是一种广义的 routing 方法,因为在没有共享 expert 的情况下,实际上就退化为传统的 MoE 路由设置。对于 Qwen1.5-MoE-A2.7B 模型,我们在其中整合了 4 个总是被激活的共享 expert 和每次只激活其中 4 个的 60 个 routing expert。这种方式非常灵活,同时在我们实验中效率最佳。
性能
为了全面评估和展示 Qwen1.5-MoE-A2.7B 的能力和优势,我们对 base 模型和 chat 模型进行了评估。对于 base 模型,我们在 MMLU、GSM8K 和 HumanEval 评估了其语言理解、数学和代码能力。此外,为了评估其多语言能力,我们按照 Qwen1.5 的评测方法在数学、理解、考试和翻译等多个领域的多语言基准测试中进行了测试,并在"Multilingual"列中给出了综合得分。对于 chat 模型,我们没有使用传统的基准测试,而是使用 MT-Bench 进行了测试。
在这个比较分析中,我们将 Qwen1.5-MoE-A2.7B 与最好的 7B 模型,比如 Mistral-7B(base 模型为 v0.1,chat 模型为 v0.2)、Gemma-7B 以及 Qwen1.5-7B 进行了对比。此外,我们还将其与具有相似参数数量的 MoE 模型 DeepSeekMoE 16B 进行了比较。结果如下表所示:
| Model | MMLU | GSM8K | HumanEval | Multilingual | MT-Bench |
|---|---|---|---|---|---|
| Mistral-7B | 64.1 | 47.5 | 27.4 | 40.0 | 7.60 |
| Gemma-7B | 64.6 | 50.9 | 32.3 | - | - |
| Qwen1.5-7B | 61.0 | 62.5 | 36.0 | 45.2 | 7.60 |
| DeepSeekMoE 16B | 45.0 | 18.8 | 26.8 | - | 6.93 |
| Qwen1.5-MoE-A2.7B | 62.5 | 61.5 | 34.2 | 40.8 | 7.17 |
Qwen1.5-MoE-A2.7B 在与最佳的 7B 模型相比取得了非常接近的性能。然而,我们发现在 chat 模型方面仍有改进的空间。我们将继续研究如何更加有效地微调 MoE 模型。
训练成本与推理效率
MoE 模型的训练成本与 dense 模型存在显著差异。尽管 MoE 模型通常拥有更多的参数,但由于其稀疏性,训练开销可以显著降低。我们先对比各个模型的三个关键参数,分别是总参数数量、激活参数数量和 Non-embedding 参数:
| Model | #Parameters | #(Activated) Parameters | #(Activated) Non-embedding parameters |
|---|---|---|---|
| Mistral-7B | 7.2 | 7.2 | 7.0 |
| Gemma-7B | 8.5 | 7.8 | 7.8 |
| Qwen1.5-7B | 7.7 | 7.7 | 6.4 |
| DeepSeekMoE 16B | 16.4 | 2.8 | 2.4 |
| Qwen1.5-MoE-A2.7B | 14.3 | 2.7 | 2.0 |
不难看出,尽管我们的总参数量较大,但 Non-embedding 激活参数量远小于 7B 模型。在我们的实践中,我们观察到使用 Qwen1.5-MoE-A2.7B 相比于 Qwen1.5-7B,训练成本显著降低了 75%。另外,由于我们的初始化方法,我们不需要训练同样数量的 token 即可达到很好的模型效果,这也显著了降低了训练成本。
我们使用 vLLM 部署了 Qwen1.5-7B 和 Qwen1.5-MoE-A2.7B 模型,并使用单个 NVIDIA A100-80G GPU 进行性能测试。在实验设置中,输入 token 数设置为 1000,输出 token 数设置为 1000,我们通过吞吐量(每秒处理的请求数)和每秒 token 数(TPS)来衡量性能:
| Model | Throughput | TPS |
|---|---|---|
| Qwen1.5-7B-Chat | 1.15 | 2298.89 |
| Qwen1.5-MoE-A2.7B-Chat | 2.01 | 4010.27 |
Qwen1.5-MoE-A2.7B 与 Qwen1.5-7B 相比,速度提高了约 1.74 倍。这种加速主要归因于 MoE 在前向过程中仅激活了其总参数的一小部分,从而降低了计算需求。此外,共享 expert 也提升了模型的推理效率。因此,尽管 MoE 模型增加了内存需求,但它们在吞吐性能和推理速度方面都表现出明显的优势。
使用 Qwen1.5-MoE
由于 Hugging Face 最新版本尚未包含 qwen2_moe(代码已合并,等待新版本发布),您需要从源代码安装 transformers,而不是通过 pip 或 conda 进行安装:
bash
git clone https://github.com/huggingface/transformers
cd transformers
pip install -e .
接下来的步骤就像使用 Qwen1.5、Mistral、Llama 等一样简单。我们演示了使用 Qwen1.5-MoE-A2.7B-Chat 的示例。如果要使用量化模型,只需将模型名称 Qwen1.5-MoE-A2.7B-Chat 替换为 Qwen1.5-MoE-A2.7B-Chat-GPTQ-Int4(暂时不支持 AWQ)。
python
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen1.5-MoE-A2.7B-Chat-GPTQ-Int4",
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-MoE-A2.7B-Chat")
prompt = "Give me a short introduction to large language model."
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
generated_ids = model.generate(
model_inputs.input_ids,
max_new_tokens=512
)
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
要使用 vLLM 模型,请从源代码安装 vLLM:
bash
git clone https://github.com/vllm-project/vllm.git
cd vllm
pip install -e .
下面这个示例说明如何使用 vLLM 构建一个与我们的模型兼容的 OpenAI-API 接口:
bash
python -m vllm.entrypoints.openai.api_server --model Qwen/Qwen1.5-MoE-A2.7B-Chat
bash
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen1.5-MoE-A2.7B-Chat",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Tell me something about large language models."}
]
}'
我们还有很多生态支持工作有待完成,包括 llama.cpp、MLX 等。我们将继续更新对第三方框架的支持。
总结
我们非常高兴地介绍我们的首个 MoE 模型 Qwen1.5-MoE-A2.7B,它对比当前最好的 7B 参数模型取得了相当的性能。此外,与传统的 7B 模型相比,MoE 模型在训练成本和推理时间上都取得了显著的降低。我们将持续研究 MoE 相关技术,未来将推出更强大的 MoE 模型。
引用
bibtex
@misc{qwen_moe,
title = {Qwen1.5-MoE: Matching 7B Model Performance with 1/3 Activated Parameters},
url = {https://qwenlm.github.io/blog/qwen-moe/},
author = {Qwen Team},
month = {February},
year = {2024}
}