深入解读Qwen3技术报告(三):深入剖析Qwen3模型架构

重磅推荐专栏:
《大模型AIGC》
《课程大纲》
《知识星球》

本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经验分享,旨在帮助读者更好地理解和应用这些领域的最新进展

3. 深入剖析Qwen3模型架构

大型语言模型的架构设计直接决定了其性能上限和计算效率。Qwen3在继承前代模型优势的基础上,引入了多项架构创新,使其在保持高性能的同时,实现了更高的计算效率和更强的扩展性。本章将深入剖析Qwen3的模型架构,包括基础组件、密集模型与MoE模型的设计差异,以及分词器实现等技术细节,帮助读者理解Qwen3强大能力背后的架构秘密。

3.1 Qwen3的基础架构组件

与大多数现代大型语言模型一样,Qwen3的基础架构建立在Transformer解码器的基础上,但引入了多项改进和创新。下面我们将逐一解析Qwen3的核心架构组件。

3.1.1 整体架构概览

Qwen3的整体架构遵循自回归语言模型的典型设计,由多层Transformer解码器堆叠而成。每一层包含以下主要组件:

  1. 自注意力机制(Self-Attention):允许模型关注输入序列中的不同位置,捕捉长距离依赖关系。
  2. 前馈网络(Feed-Forward Network):由两个线性变换和一个非线性激活函数组成,增强模型的表示能力。
  3. 层归一化(Layer Normalization):稳定训练过程,加速收敛。
  4. 残差连接(Residual Connection):缓解梯度消失问题,便于训练深层网络。
Transformer层结构
层前归一化
输入
自注意力机制
残差连接
层前归一化
前馈网络/MoE
残差连接
输出
输入Embedding
位置编码
Transformer层 1
Transformer层 2
...
Transformer层 N
输出层

上图展示了Qwen3的整体架构和单个Transformer层的内部结构。与传统Transformer不同,Qwen3采用了层前归一化(Pre-Layer Normalization)设计,即在每个子层(自注意力和前馈网络)之前应用层归一化,而不是之后。这种设计有助于稳定训练过程,特别是对于深层模型。

3.1.2 改进的自注意力机制

Qwen3在自注意力机制上引入了多项改进,以提高性能和效率:

  1. 分组查询注意力(Grouped Query Attention, GQA)

    传统的多头注意力机制(Multi-Head Attention, MHA)为每个注意力头分配独立的查询(Q)、键(K)和值(V)投影。而GQA则让多个查询头共享同一组键值头,显著减少了参数量和计算量,同时保持了性能。

    # 传统多头注意力与GQA的对比实现
    class MultiHeadAttention(nn.Module):def __init__(self, d_model, num_heads):super().__init__()self.d_model = d_modelself.num_heads = num_headsself.head_dim = d_model // num_heads# 传统MHA: 每个头有独立的QKV投影self.q_proj = nn.Linear(d_model, d_model)self.k_proj = nn.Linear(d_model, d_model)self.v_proj = nn.Linear(d_model, d_model)self.out_proj = nn.Linear(d_model, d_model)def forward(self, x):batch_size, seq_len, _ = x.shape# 投影并分头q = self.q_proj(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)k = self.k_proj(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)v = self.v_proj(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)# 计算注意力scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.head_dim)attn_weights = F.softmax(scores, dim=-1)attn_output = torch.matmul(attn_weights, v)# 合并头并投影attn_output = attn_output.transpose(1, 2).contiguous().view(batch_size, seq_len, self.d_model)output = self.out_proj(attn_output)return outputclass GroupedQueryAttention(nn.Module):def __init__(self, d_model, num_query_heads, num_kv_heads):super().__init__()self.d_model = d_modelself.num_query_heads = num_query_headsself.num_kv_heads = num_kv_heads  # 通常 num_kv_heads < num_query_headsself.head_dim = d_model // num_query_heads# GQA: 查询头数量多于键值头数量self.q_proj = nn.Linear(d_model, d_model)self.k_proj = nn.Linear(d_model, self.num_kv_heads * self.head_dim)self.v_proj = nn.Linear(d_model, self.num_kv_heads * self.head_dim)self.out_proj = nn.Linear(d_model, d_model)def forward(self, x):batch_size, seq_len, _ = x.shape# 投影q = self.q_proj(x).view(batch_size, seq_len, self.num_query_heads, self.head_dim).transpose(1, 2)k = self.k_proj(x).view(batch_size, seq_len, self.num_kv_heads, self.head_dim).transpose(1, 2)v = self.v_proj(x).view(batch_size, seq_len, self.num_kv_heads, self.head_dim).transpose(1, 2)# 键值重复以匹配查询头数量# 每个键值头被多个查询头共享if self.num_kv_heads != self.num_query_heads:# 计算每个键值头需要复制的次数kv_repeat_factor = self.num_query_heads // self.num_kv_heads# 复制键值头k = k.repeat_interleave(kv_repeat_factor, dim=1)v = v.repeat_interleave(kv_repeat_factor, dim=1)# 计算注意力scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.head_dim)attn_weights = F.softmax(scores, dim=-1)attn_output = torch.matmul(attn_weights, v)# 合并头并投影attn_output = attn_output.transpose(1, 2).contiguous().view(batch_size, seq_len, self.d_model)output = self.out_proj(attn_output)return output
    

    在Qwen3中,不同规模的模型采用了不同的GQA配置:

    模型查询头数量键值头数量头数比例
    Qwen3-0.6B842:1
    Qwen3-1.7B1644:1
    Qwen3-4B3284:1
    Qwen3-8B3284:1
    Qwen3-14B40104:1
    Qwen3-32B6488:1
    Qwen3 MoE系列128168:1

    这种设计大大减少了模型的参数量和计算量,同时保持了性能。

  2. QK-Norm

    Qwen3移除了传统Transformer中的QKV-bias(查询、键、值投影的偏置项),并引入了QK-Norm技术。QK-Norm对查询和键向量进行归一化,使得注意力分数的分布更加稳定,有助于提高模型的稳定性和性能。

    # QK-Norm实现
    def attention_with_qk_norm(q, k, v, scale=1.0):"""带QK-Norm的注意力计算参数:q: 查询张量 [batch_size, num_heads, seq_len, head_dim]k: 键张量 [batch_size, num_heads, seq_len, head_dim]v: 值张量 [batch_size, num_heads, seq_len, head_dim]scale: 缩放因子返回:注意力输出"""# 对查询和键进行L2归一化q_normalized = F.normalize(q, p=2, dim=-1)k_normalized = F.normalize(k, p=2, dim=-1)# 计算注意力分数scores = torch.matmul(q_normalized, k_normalized.transpose(-2, -1)) * scale# 应用softmaxattn_weights = F.softmax(scores, dim=-1)# 计算输出output = torch.matmul(attn_weights, v)return output
    

    QK-Norm的引入使得Qwen3在处理长序列和复杂任务时更加稳定,减少了训练过程中的异常情况。

  3. 旋转位置编码(Rotary Positional Embedding, RoPE)

    Qwen3采用了RoPE作为位置编码方法,它通过对查询和键向量应用旋转变换,将位置信息直接编码到自注意力计算中。与传统的位置编码相比,RoPE具有更好的相对位置感知能力和外推性。

    # RoPE实现
    def apply_rotary_pos_emb(q, k, cos, sin, position_ids):"""应用旋转位置编码参数:q, k: 查询和键张量cos, sin: 余弦和正弦位置编码position_ids: 位置ID返回:应用了RoPE的查询和键"""# 获取位置编码cos = cos[position_ids].unsqueeze(1)  # [bs, 1, seq_len, dim]sin = sin[position_ids].unsqueeze(1)  # [bs, 1, seq_len, dim]# 将q和k分成实部和虚部q_real, q_imag = q[..., ::2], q[..., 1::2]k_real, k_imag = k[..., ::2], k[..., 1::2]# 应用复数乘法的旋转q_rotated_real = q_real * cos - q_imag * sinq_rotated_imag = q_real * sin + q_imag * cosk_rotated_real = k_real * cos - k_imag * sink_rotated_imag = k_real * sin + k_imag * cos# 重新组合实部和虚部q_rotated = torch.stack([q_rotated_real, q_rotated_imag], dim=-1).flatten(-2)k_rotated = torch.stack([k_rotated_real, k_rotated_imag], dim=-1).flatten(-2)return q_rotated, k_rotated
    

    在Qwen3中,为了支持更长的上下文,RoPE的基频从传统的10,000增加到了1,000,000,并结合YARN(Yet Another RoPE extensioN)技术,使模型能够处理长达128K tokens的超长序列。

3.1.3 前馈网络与激活函数

Qwen3的前馈网络(Feed-Forward Network, FFN)采用了标准的两层结构,但在激活函数和设计细节上有所创新:

  1. SwiGLU激活函数

    Qwen3采用了SwiGLU(Swish-Gated Linear Unit)作为前馈网络的激活函数,它是对传统GLU(Gated Linear Unit)的改进,使用Swish函数替代了Sigmoid函数,提供了更好的梯度流和性能。

    # SwiGLU激活函数实现
    class SwiGLU(nn.Module):def __init__(self, in_features, hidden_features, out_features):super().__init__()self.gate_proj = nn.Linear(in_features, hidden_features, bias=False)self.up_proj = nn.Linear(in_features, hidden_features, bias=False)self.down_proj = nn.Linear(hidden_features, out_features, bias=False)def forward(self, x):# 计算门控值gate = self.gate_proj(x)# 应用Swish激活: x * sigmoid(beta * x),这里beta=1gate = gate * torch.sigmoid(gate)# 上投影up = self.up_proj(x)# 门控机制hidden = gate * up# 下投影return self.down_proj(hidden)
    

    SwiGLU激活函数使得Qwen3在训练过程中收敛更快,并在各种任务上取得更好的性能。

  2. 隐藏层维度

    Qwen3的前馈网络隐藏层维度通常是模型维度的4倍,这种设计提供了足够的模型容量,使模型能够学习复杂的模式和关系。

    模型模型维度FFN隐藏维度比例
    Qwen3-0.6B102440964:1
    Qwen3-1.7B153661444:1
    Qwen3-4B2560102404:1
    Qwen3-8B3584143364:1
    Qwen3-14B4608184324:1
    Qwen3-32B6144245764:1
    Qwen3 MoE系列8192327684:1

    这种设计在保持模型表达能力的同时,也考虑了计算效率和训练稳定性。

3.2 密集模型与MoE模型的架构差异

Qwen3系列包含两种类型的模型:密集模型(Dense Models)和混合专家模型(Mixture-of-Experts Models, MoE)。这两种模型在架构上有显著差异,下面我们将详细比较它们的设计特点。

3.2.1 密集模型架构

密集模型是传统的Transformer架构,其中所有参数在每次前向传播中都会被激活。Qwen3的密集模型从0.6B到32B,覆盖了从轻量级到大型的多个规模。

密集模型的主要特点包括:

  1. 参数高效利用:所有参数都参与每次计算,充分利用了模型容量。
  2. 实现简单:架构相对简单,易于实现和部署。
  3. 训练稳定:训练过程相对稳定,超参数调整相对简单。
  4. 推理速度快:在相同参数量下,推理速度通常快于MoE模型。

以下是Qwen3密集模型的主要配置参数:

模型层数模型维度注意力头数参数量
Qwen3-0.6B24102480.6B
Qwen3-1.7B241536161.7B
Qwen3-4B322560324.0B
Qwen3-8B323584328.0B
Qwen3-14B4046084014.0B
Qwen3-32B6061446432.0B
3.2.2 MoE模型架构

MoE模型是一种稀疏激活的神经网络架构,其核心思想是"专家分工"。在Qwen3的MoE模型中,每个Transformer层的前馈网络被替换为多个"专家"(Expert)网络,但在处理每个输入时,只激活其中的一部分专家。

输入
自注意力层
MoE层
输出
路由器
专家1
专家2
专家3
...
专家N
加权合并

上图展示了MoE层的基本结构,其中路由器(Router)负责决定每个输入应该由哪些专家处理,然后将多个专家的输出加权合并得到最终结果。

Qwen3的MoE模型具有以下特点:

  1. 细粒度专家分割:每个MoE层包含多个专家,每个专家都是一个完整的前馈网络。

  2. Top-k路由:对于每个输入token,路由器选择k个最相关的专家进行处理(Qwen3中k=2)。

  3. 无共享专家:与一些包含共享专家的MoE模型不同,Qwen3的每个专家都有独特的参数,增强了专业化程度。

  4. 全局批次负载平衡:为了确保各个专家的工作负载均衡,Qwen3引入了全局批次负载平衡损失。

# MoE层的详细实现
class MoELayer(nn.Module):def __init__(self, input_dim, hidden_dim, output_dim, num_experts=10, top_k=2):"""初始化MoE层参数:input_dim: 输入维度hidden_dim: 隐藏层维度output_dim: 输出维度num_experts: 专家数量top_k: 每次激活的专家数量"""super().__init__()self.input_dim = input_dimself.hidden_dim = hidden_dimself.output_dim = output_dimself.num_experts = num_expertsself.top_k = top_k# 专家路由器self.router = nn.Linear(input_dim, num_experts, bias=False)# 创建专家网络self.experts = nn.ModuleList([SwiGLU(input_dim, hidden_dim, output_dim) for _ in range(num_experts)])def forward(self, x):"""前向传播参数:x: 输入张量 [batch_size, seq_len, input_dim]返回:输出张量 [batch_size, seq_len, output_dim]负载平衡损失"""batch_size, seq_len, _ = x.shape# 计算路由分数router_logits = self.router(x)  # [batch_size, seq_len, num_experts]# 添加噪声以打破平局if self.training:router_logits += torch.randn_like(router_logits) * 1e-2# 选择top-k专家router_probs = F.softmax(router_logits, dim=-1)top_k_probs, top_k_indices = torch.topk(router_probs, self.top_k, dim=-1)# 归一化概率top_k_probs = top_k_probs / top_k_probs.sum(dim=-1, keepdim=True)# 准备输出output = torch.zeros_like(x)# 计算专家使用计数expert_counts = torch.zeros(self.num_experts, device=x.device)# 对每个token应用选定的专家for i in range(batch_size):for j in range(seq_len):for k in range(self.top_k):expert_idx = top_k_indices[i, j, k].item()prob = top_k_probs[i, j, k].item()# 更新专家使用计数expert_counts[expert_idx] += 1# 应用专家expert_output = self.experts[expert_idx](x[i:i+1, j:j+1, :])output[i, j] += prob * expert_output.squeeze(0).squeeze(0)# 计算负载平衡损失# 理想情况下,每个专家应该处理相同数量的tokentotal_tokens = batch_size * seq_len * self.top_kideal_count = total_tokens / self.num_experts# 计算专家使用率expert_usage = expert_counts / total_tokens# 计算负载平衡损失load_balancing_loss = torch.sum((expert_usage - (1.0 / self.num_experts))**2)return output, load_balancing_loss

Qwen3的MoE模型配置如下:

模型层数模型维度注意力头数专家数量激活专家数总参数量激活参数量
Qwen3-30B-A3B60819212810130B3B
Qwen3-72B-A7B80819212810172B7B
Qwen3-235B-A22B1208192128102235B22B

MoE架构的主要优势在于:

  1. 参数效率:虽然总参数量很大,但每次推理只激活一小部分,大大提高了参数效率。
  2. 性能提升:在相同激活参数量下,MoE模型通常比密集模型性能更好。
  3. 专业化能力:不同专家可以专注于不同类型的输入,提高模型处理多样化任务的能力。

例如,Qwen3-235B-A22B虽然总参数量达到235B,但每次推理只激活22B参数,这使得它能够在保持高性能的同时,控制计算资源需求。

3.3 分词器实现与多语言支持

分词器(Tokenizer)是大型语言模型的重要组成部分,它负责将原始文本转换为模型可以处理的token序列。Qwen3的分词器设计考虑了多语言支持和处理效率,下面我们将详细介绍其实现。

3.3.1 字节级字节对编码(Byte-level BPE)

Qwen3采用了字节级字节对编码(Byte-level Byte-Pair Encoding, BBPE)作为分词方法。BBPE的核心思想是将文本视为字节序列,然后应用BPE算法学习常见的字节组合,形成词汇表。

BBPE的主要优势包括:

  1. 通用性:能够处理任何语言和字符,包括表情符号、特殊符号等。
  2. 无未知词:由于基于字节,任何输入都可以被编码,不会出现未知词(UNK)。
  3. 效率:编码和解码过程高效,适合实时应用。
# BBPE分词器的简化实现
class ByteLevelBPETokenizer:def __init__(self, vocab_file, merges_file):"""初始化BBPE分词器参数:vocab_file: 词汇表文件路径merges_file: 合并规则文件路径"""# 加载词汇表with open(vocab_file, 'r', encoding='utf-8') as f:self.vocab = json.load(f)# 创建词汇表的反向映射self.ids_to_tokens = {v: k for k, v in self.vocab.items()}# 加载合并规则self.merges = {}with open(merges_file, 'r', encoding='utf-8') as f:for i, line in enumerate(f):if i == 0:  # 跳过版本信息continuepair = line.strip().split()if len(pair) == 2:self.merges[tuple(pair)] = idef encode(self, text):"""将文本编码为token ID参数:text: 输入文本返回:token ID列表"""# 将文本转换为字节bytes_str = text.encode('utf-8')# 初始化为单个字节的tokentokens = [bytes([b]) for b in bytes_str]# 应用合并规则while len(tokens) > 1:pairs = self._get_pairs(tokens)if not pairs:break# 找到优先级最高的合并对best_pair = min(pairs, key=lambda pair: self.merges.get(pair, float('inf')))if best_pair not in self.merges:break# 执行合并tokens = self._merge(tokens, best_pair)# 将token转换为IDids = [self.vocab.get(token, self.vocab['<unk>']) for token in tokens]return idsdef decode(self, ids):"""将token ID解码为文本参数:ids: token ID列表返回:解码后的文本"""# 将ID转换为tokentokens = [self.ids_to_tokens.get(id, '<unk>') for id in ids]# 将token连接并解码为文本bytes_str = b''.join([t.encode('latin1') for t in tokens])text = bytes_str.decode('utf-8', errors='replace')return textdef _get_pairs(self, tokens):"""获取相邻token对"""pairs = set()for i in range(len(tokens) - 1):pairs.add((tokens[i], tokens[i + 1]))return pairsdef _merge(self, tokens, pair):"""合并指定的token对"""new_tokens = []i = 0while i < len(tokens):if i < len(tokens) - 1 and (tokens[i], tokens[i + 1]) == pair:new_tokens.append(tokens[i] + tokens[i + 1])i += 2else:new_tokens.append(tokens[i])i += 1return new_tokens
3.3.2 多语言支持扩展

Qwen3将支持的语言从Qwen2.5的29种扩展到了119种语言和方言,这一扩展主要通过以下方式实现:

  1. 扩大词汇表:Qwen3的词汇表包含15.2万个token,比Qwen2.5的15.1万略有增加,但通过更高效的编码方式支持了更多语言。

  2. 多语言训练数据:在预训练阶段使用了覆盖119种语言的大规模文本语料,使模型能够学习各种语言的模式和规则。

  3. 语言识别与切换:Qwen3能够自动识别输入文本的语言,并在不同语言之间无缝切换,这对于多语言对话和翻译任务尤为重要。

以下是Qwen3支持的部分语言列表:

语言类别包含语言
欧洲语系英语、法语、德语、西班牙语、意大利语、葡萄牙语、俄语、荷兰语、瑞典语、波兰语、捷克语、丹麦语、挪威语、芬兰语、希腊语、匈牙利语、罗马尼亚语等
亚洲语系中文(简体和繁体)、日语、韩语、阿拉伯语、希伯来语、泰语、越南语、印尼语、马来语、菲律宾语、乌尔都语、印地语、孟加拉语等
非洲语系斯瓦希里语、豪萨语、约鲁巴语、伊博语、祖鲁语、索马里语等
其他语系土耳其语、波斯语、库尔德语等

这种广泛的语言支持使Qwen3能够服务全球用户,促进跨语言交流和知识共享。

3.3.3 特殊token与控制码

Qwen3的分词器包含多种特殊token和控制码,用于标记序列的开始和结束、控制生成行为等:

  1. 基本特殊token

    • <bos>: 序列开始标记
    • <eos>: 序列结束标记
    • <pad>: 填充标记
    • <unk>: 未知词标记
  2. 控制码

    • 思考模式控制:用于切换思考模式和非思考模式
    • 语言控制:用于指定生成特定语言的文本
    • 格式控制:用于控制生成文本的格式(如代码、表格等)

这些特殊token和控制码增强了Qwen3的灵活性和可控性,使用户能够更精确地控制模型的行为。

3.4 长上下文处理技术

Qwen3能够处理长达128K tokens的超长上下文,这一能力主要通过以下技术实现:

3.4.1 RoPE基频调整

Qwen3将RoPE的基频从传统的10,000增加到了1,000,000,这一调整使得模型能够更好地区分远距离位置,提高了长序列处理能力。

# RoPE基频调整实现
def get_rope_embeddings(dim, max_seq_len, base=1000000.0):"""生成RoPE位置编码参数:dim: 嵌入维度max_seq_len: 最大序列长度base: 基频(Qwen3使用1000000)返回:余弦和正弦位置编码"""# 计算频率inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))# 生成位置序列t = torch.arange(max_seq_len).float()# 计算外积freqs = torch.outer(t, inv_freq)# 计算余弦和正弦cos = torch.cos(freqs)sin = torch.sin(freqs)return cos, sin
3.4.2 YARN扩展

YARN(Yet Another RoPE extensioN)是一种改进的RoPE扩展方法,它通过调整位置编码的插值方式,使模型能够处理超出训练长度的序列。

# YARN实现
def yarn_rope_embeddings(dim, max_train_len, max_infer_len, base=1000000.0, scale=1.0):"""使用YARN方法生成扩展的RoPE位置编码参数:dim: 嵌入维度max_train_len: 最大训练序列长度max_infer_len: 最大推理序列长度base: 基频scale: 缩放因子返回:扩展的余弦和正弦位置编码"""# 计算原始频率inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))# 应用YARN缩放if max_infer_len > max_train_len:# 计算缩放比例yarn_scale = scale * math.log(max_infer_len / max_train_len) / math.log(2)# 缩放频率inv_freq = inv_freq * (1 - yarn_scale * torch.arange(0, dim, 2).float() / dim)# 生成位置序列t = torch.arange(max_infer_len).float()# 计算外积freqs = torch.outer(t, inv_freq)# 计算余弦和正弦cos = torch.cos(freqs)sin = torch.sin(freqs)return cos, sin
3.4.3 Dual Chunk Attention (DCA)

DCA是一种高效的注意力机制,它将长序列分成多个块,并在块内和块间分别计算注意力,大大提高了处理长序列的效率。

# DCA实现
class DualChunkAttention(nn.Module):def __init__(self, d_model, num_heads, chunk_size=4096):"""初始化DCA参数:d_model: 模型维度num_heads: 注意力头数chunk_size: 块大小"""super().__init__()self.d_model = d_modelself.num_heads = num_headsself.chunk_size = chunk_sizeself.head_dim = d_model // num_headsself.q_proj = nn.Linear(d_model, d_model, bias=False)self.k_proj = nn.Linear(d_model, d_model, bias=False)self.v_proj = nn.Linear(d_model, d_model, bias=False)self.out_proj = nn.Linear(d_model, d_model, bias=False)def forward(self, x, attention_mask=None):"""前向传播参数:x: 输入张量 [batch_size, seq_len, d_model]attention_mask: 注意力掩码返回:输出张量 [batch_size, seq_len, d_model]"""batch_size, seq_len, _ = x.shape# 投影q = self.q_proj(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)k = self.k_proj(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)v = self.v_proj(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)# 计算块数num_chunks = (seq_len + self.chunk_size - 1) // self.chunk_size# 准备输出output = torch.zeros_like(q)# 块内注意力for i in range(num_chunks):# 计算块的起止位置start_idx = i * self.chunk_sizeend_idx = min(start_idx + self.chunk_size, seq_len)# 提取当前块q_chunk = q[:, :, start_idx:end_idx, :]k_chunk = k[:, :, start_idx:end_idx, :]v_chunk = v[:, :, start_idx:end_idx, :]# 计算块内注意力scores = torch.matmul(q_chunk, k_chunk.transpose(-2, -1)) / math.sqrt(self.head_dim)# 应用掩码(如果有)if attention_mask is not None:mask_chunk = attention_mask[:, start_idx:end_idx, start_idx:end_idx]scores = scores + mask_chunk.unsqueeze(1)# 应用softmaxattn_weights = F.softmax(scores, dim=-1)# 计算输出chunk_output = torch.matmul(attn_weights, v_chunk)# 保存块输出output[:, :, start_idx:end_idx, :] = chunk_output# 块间注意力(简化实现)if num_chunks > 1:# 为每个块创建一个代表性tokenrep_tokens = torch.zeros(batch_size, self.num_heads, num_chunks, self.head_dim, device=x.device)for i in range(num_chunks):start_idx = i * self.chunk_sizeend_idx = min(start_idx + self.chunk_size, seq_len)# 使用平均池化创建代表性tokenrep_tokens[:, :, i, :] = q[:, :, start_idx:end_idx, :].mean(dim=2)# 计算块间注意力rep_scores = torch.matmul(rep_tokens, rep_tokens.transpose(-2, -1)) / math.sqrt(self.head_dim)rep_attn_weights = F.softmax(rep_scores, dim=-1)# 应用块间注意力for i in range(num_chunks):for j in range(num_chunks):if i != j:  # 跳过自身块start_i = i * self.chunk_sizeend_i = min(start_i + self.chunk_size, seq_len)start_j = j * self.chunk_sizeend_j = min(start_j + self.chunk_size, seq_len)# 计算块间注意力权重weight = rep_attn_weights[:, :, i, j].unsqueeze(-1).unsqueeze(-1)# 计算块间注意力cross_attn = torch.matmul(q[:, :, start_i:end_i, :].unsqueeze(3),k[:, :, start_j:end_j, :].transpose(-2, -1).unsqueeze(2)) / math.sqrt(self.head_dim)cross_attn_weights = F.softmax(cross_attn, dim=-1)cross_output = torch.matmul(cross_attn_weights, v[:, :, start_j:end_j, :].unsqueeze(2))# 加权并添加到输出output[:, :, start_i:end_i, :] += weight * cross_output.squeeze(3)# 重塑并投影输出output = output.transpose(1, 2).contiguous().view(batch_size, seq_len, self.d_model)output = self.out_proj(output)return output

通过这些技术的组合,Qwen3能够有效处理长达128K tokens的超长序列,这对于理解长文档、进行多轮复杂对话等场景至关重要。

3.5 架构设计的性能影响

Qwen3的架构设计对其性能有显著影响,下面我们将分析不同架构组件对模型性能的贡献。

3.5.1 GQA对推理效率的影响

GQA通过减少键值头的数量,显著降低了内存使用和计算量,同时保持了性能。实验表明,与传统MHA相比,GQA可以:

  • 减少约30-50%的内存使用
  • 提高约20-40%的推理速度
  • 在保持或略微降低性能的情况下,大大提高了模型的实用性
3.5.2 MoE架构的参数效率

MoE架构通过稀疏激活,实现了更高的参数效率。实验表明:

  • Qwen3-30B-A3B(激活3B参数)的性能接近Qwen3-14B(14B参数)
  • Qwen3-72B-A7B(激活7B参数)的性能超过Qwen3-32B(32B参数)
  • Qwen3-235B-A22B(激活22B参数)的性能远超其他开源模型

这表明MoE架构能够以更少的计算资源实现更高的性能,特别适合资源受限的场景。

3.5.3 长上下文技术的实际效果

Qwen3的长上下文处理技术使其能够有效处理超长文本,实验表明:

  • 在32K tokens长度的测试中,Qwen3保持了接近100%的准确率
  • 在64K tokens长度的测试中,Qwen3保持了约95%的准确率
  • 在128K tokens长度的测试中,Qwen3仍然保持了约85%的准确率

这种长上下文处理能力使Qwen3能够理解和分析长文档、书籍章节,甚至整本书的内容,大大扩展了其应用场景。

总的来说,Qwen3的架构设计在保持高性能的同时,实现了更高的计算效率和更强的扩展性,使其成为一个既强大又实用的开源大语言模型。通过深入理解这些架构组件,开发者和研究者可以更好地利用Qwen3的能力,并在此基础上进行进一步的创新和优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82147.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UE4游戏查找本地角色数据的方法-SDK

UE4中&#xff0c;玩家的表示通常涉及以下几个类&#xff1a; APlayerController: 代表玩家的控制逻辑&#xff0c;处理输入等。 APawn: 代表玩家在世界中的实体&#xff08;比如一个角色、一辆车&#xff09;。APlayerController 控制一个 APawn。 ACharacter: APawn 的一个…

springboot+vue实现服装商城系统(带用户协同过滤个性化推荐算法)

今天教大家如何设计一个服装商城 , 基于目前主流的技术&#xff1a;前端vue3&#xff0c;后端springboot。 同时还带来的项目的部署教程。 系统最大的亮点是使用了两个推荐算法: 1. 基于Jaccard算法的用户浏览历史推荐。 2. 基于用户的协同过滤算法个性化推荐。 还有核心的商…

ERROR: Could not install packages due to an OSError: [WinError 5] 拒绝访问

有可能是设置了代理 unset ALLPROXY 或者注释掉 当然也有可能是其他原因 权限不足​​ 以管理员身份运行 CMD/PowerShell&#xff0c;或使用 --user 安装 ​​文件被占用​​ 关闭杀毒软件或重启电脑 Python 环境损坏​​ 重新安装 Python 或使用虚拟环境 ​​ 杀毒软件阻止…

【深尚想!爱普特APT32F1023H8S6单片机重构智能电机控制新标杆】

在智能家电与健康器械市场爆发的今天&#xff0c;核心驱动技术正成为产品突围的关键。传统电机控制方案面临集成度低、开发周期长、性能瓶颈三大痛点&#xff0c;而爱普特电子带来的APT32F1023H8S6单片机无感三合一方案&#xff0c;正在掀起一场智能电机控制的技术革命。 爆款基…

一个.NET开源、轻量级的运行耗时统计库

前言 在.NET开发中&#xff0c;为了准确统计对应方法的执行时间&#xff0c;我们最常用的方式是手动使用 Stopwatch 来显式编写计时逻辑&#xff0c;但是假如你需要大量的使用 Stopwatch 来进行耗时统计的话不利于保持代码的整洁和增加代码的维护成本。 项目介绍 MethodTime…

嵌入式鸿蒙openharmony应用开发环境搭建与工程创建实现

各位小伙伴大家好,本周开始分享鸿蒙开发相关的内容,从基础的配置方法到各种功能的实现,探索国产操作系统的奥秘。 第一:观察结果 第二:开源语言 ArkTS是鸿蒙应用开发中使用的TypeScript超集,提供了一套丰富的API来构建应用界面和逻辑。 第三:环境搭建 步骤 1 通过如…

软考 组合设计模式

组合设计模式&#xff08;Composite Pattern&#xff09;是结构型设计模式之一&#xff0c;它的核心思想是将对象组合成树形结构来表示“部分-整体”的层次结构&#xff0c;使得用户对单个对象和组合对象的使用具有一致性。 主要概念&#xff1a; 组件&#xff08;Component&a…

vue 中的v-once

&#x1f530; 基础理解 ✅ 语法&#xff1a; <span v-once>{{ msg }}</span>✅ 效果&#xff1a; • 只渲染一次&#xff0c;之后无论数据如何变化&#xff0c;该内容都不会更新。 • 非常适用于静态内容或首次加载后不需要变化的数据。&#x1f9ea; 示例&…

GPU训练和call方法

知识点回归: CPU性能的查看:看架构代际、核心数、线程数GPU性能的查看:看显存、看级别、看架构代际GPU训练的方法:数据和模型移动到GPU device上类的call方法:为什么定义前向传播时可以直接写作self.fc1(x)import torch import torch.nn as nn import torch.optim as opti…

人脸识别备案开启安全防护模式!紧跟《办法》!

国家互联网信息办公室与公安部于 2025 年 3 月 13 日联合公布了《人脸识别技术应用安全管理办法》&#xff08;以下简称《办法》&#xff09;&#xff0c;并自 2025 年 6 月 1 日起正式施行。其中&#xff0c;人脸识别备案成为了规范技术应用、守护信息安全的关键一环。​ 一、…

LeetCode:贪心算法

目录 一、分发饼干 二、摆动序列 三、最大子数组和 四、买卖股票的最佳时机II 五、跳跃游戏 六、跳跃游戏II 七、K次取反后最大化的数组和 八、加油站 九、分发糖果 十、柠檬水找零 十一、根据身高重建队列 一、分发饼干 455. 分发饼干 - 力扣&#xff08;LeetCode…

企业级 Hosts 自动化管理实战:基于 HTTP 检测的高可用域名解析方案

摘要 本文针对企业级域名解析稳定性需求&#xff0c;提供一套从IP 检测到Hosts 更新的完整自动化解决方案。通过 HTTP 状态码检测、权威 DNS 解析、原子化文件操作等核心技术&#xff0c;结合多行业真实案例&#xff0c;详细阐述方案设计、脚本实现与生产部署&#xff0c;帮助…

基于springboot+vue网页系统的社区义工服务互动平台(源码+论文+讲解+部署+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统背景 在社会文明程度不断提升、社区治理需求持续深化的大背景下&#xff0c;社区义工服务作为…

从细胞工厂到智能制造:Extracellular 用时序数据库 TDengine 打通数据生命线

作为一家位于英国的前沿生物科技公司&#xff0c;Extracellular 专注于细胞培养产品的规模化制造&#xff0c;致力于通过优化生物工艺流程&#xff0c;加速细胞类产品从实验室走向大规模生产的落地。为了实现这一目标&#xff0c;他们需要一个稳定、高效、可扩展的数据平台&…

【NLP 77、Python环境管理工具之conda】

如果你第一万次否定自己&#xff0c;那我希望我可以一万零一次大声称赞你 —— 25.5.22 一、什么是conda conda是一个开源的包管理系统和环境管理系统&#xff0c;主要用于Python语言&#xff0c;但也可以用于其它语言的项目 二、为什么要使用conda ① 多环境共存&#xff0c;多…

【Python 算法零基础 4.排序 ④ 计数排序】

目录 一、引言 二、算法思想 三、算法分析 1.时间复杂度 2.空间复杂度 3.算法的优缺点 Ⅰ、算法的优点 Ⅱ、算法的缺点 四、实战练习 75. 颜色分类 算法与思路 ① 初始化计数数组 ② 统计元素频率 ③ 重构有序数组 1046. 最后一块石头的重量 算法与思路 ① 计数排序 ② 石头碰撞…

PPP 流程已经走到启动阶段并且成功进入了 “STAGE_START_PPP

从您最新的日志来看&#xff0c;PPP 流程已经走到启动阶段并且成功进入了 “STAGE_START_PPP”&#xff0c;但在 “STAGE_WAIT_IP” 阶段没有拿到 IP&#xff0c;约 60 s 后就报了 “Connection lost”&#xff1a; I (11161) modem_board: Modem state STAGE_START_PPP, Succ…

siparmyknife:SIP协议渗透测试的瑞士军刀!全参数详细教程!Kali Linux教程!

简介 SIP Army Knife 是一个模糊测试器&#xff0c;用于搜索跨站点脚本、SQL 注入、日志注入、格式字符串、缓冲区溢出等。 安装 源码安装 通过以下命令来进行克隆项目源码&#xff0c;建议请先提前挂好代理进行克隆。 git clone https://github.com/foreni-packages/sipa…

Phantom 根据图片和文字描述,自动生成一段视频,并且动作、场景等内容会按照文字描述来呈现

Phantom 根据图片和文字描述&#xff0c;自动生成一段视频&#xff0c;并且动作、场景等内容会按照文字描述来呈现 flyfish 视频生成的实践效果展示 Phantom 视频生成的实践 Phantom 视频生成的流程 Phantom 视频生成的命令 Wan2.1 图生视频 支持批量生成 Wan2.1 文生视频 …

OceanBase 系统表查询与元数据查询完全指南

文章目录 一、OceanBase 元数据基础概念1.1 元数据的定义与重要性1.2 OceanBase 元数据分类体系二、系统表查询核心技术2.1 核心系统表详解2.1.1 集群管理表2.1.2 租户资源表2.2 高级查询技巧2.2.1 跨系统表关联查询2.2.2 历史元数据查询三、元数据查询实战应用3.1 日常运维场景…