大厂真题 / 华为

华为 4.23 笔试真题 - 留学生AI岗

本场考试概述

考试时间:2026年4月23日 考试岗位:留学生AI岗 难度评级:困难

考点分析

  1. 选择题(20道):大模型推理优化(量化/KV Cache/GQA/RoPE)、深度学习(CNN/Transformer/激活函数/混合精度训练)、机器学习(评价指标/线性模型/Pass@k)、数学(凸优化/数值计算/线性代数/概率论)、GPU计算、多Agent系统
  2. 第一题:MMR 算法贪心模拟(难度困难)
  3. 第二题:ID3 决策树递归建树(难度困难)

建议策略

  1. 选择题重点复习 KV Cache、GQA/MHA 差异、RoPE 位置编码、量化技术、混合精度训练
  2. 第一题按题意逐轮贪心选取,注意用 maxSim 数组做增量更新避免重复遍历
  3. 第二题 ID3 决策树递归建树,需处理空分支(取父节点多数类)和平局(选索引小的特征)

选择题(20道)

第1题

量化(Quantization)技术中,将 FP16 转为 INT8 主要压缩了什么?

A. 注意力机制的头数 B. 模型的层数 C. 权重的存储位宽 D. Token 词表的长度

答案:C

考点:大模型——量化

FP16 使用 16 位存储每个权重,INT8 使用 8 位,量化的核心就是降低权重的存储位宽从而减少显存占用和加速推理。量化不改变模型结构(头数、层数不变),也不影响词表大小。

第2题

对于输入为 $227 \times 227 \times 3$ 的图像,使用一个卷积层,包含 96 个 $11 \times 11$ 的卷积核,步长为 4,无填充(padding = 0),输出特征图的大小和深度分别是?

A. $54 \times 54 \times 96$ B. $56 \times 56 \times 96$ C. $55 \times 55 \times 11$ D. $55 \times 55 \times 96$

答案:D

考点:深度学习——CNN

卷积输出尺寸公式为 $\lfloor (W - K) / S \rfloor + 1 = \lfloor (227 - 11) / 4 \rfloor + 1 = 55$,深度等于卷积核数量 96,所以输出为 $55 \times 55 \times 96$。

第3题

在原始 Transformer 的多头注意力机制中,多个头间的输出是如何结合的?

A. 取最大值 B. 拼接后经过线性变换 C. 逐元素相加 D. 取平均

答案:B

考点:深度学习——Transformer

原始 Transformer 论文明确定义:$\text{MultiHead}(Q,K,V) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h) W^O$,即将各头输出在特征维度上拼接(Concat),再通过线性变换矩阵 $W^O$ 投影回原始维度。

第4题

关于 Transformer 中的多头注意力(MHA)的表述,哪一项是正确的?

A. 多个头共享相同的查询、键、值权重矩阵 B. 每个头独立学习不同的线性投影,最后将注意力输出拼接 C. 头数越多,模型推理速度一定越快 D. 每个头关注输入序列的同一局部特征

答案:B

考点:深度学习——Transformer

每个注意力头拥有独立的 $W^Q, W^K, W^V$ 投影矩阵,学习不同的子空间表示,最后拼接输出。A 错在”共享”——各头权重独立;C 错在头数增多会增加计算量;D 错在多头的目的恰恰是让不同头关注不同的特征子空间。

第5题

以下关于凸函数的说法,正确的是?

A. 凸函数的局部最小值一定是全局最小值 B. 凸函数的二阶导数可以为负 C. 凸函数一定没有最小值 D. 所有多项式函数都是凸函数

答案:A

考点:数学——凸优化

凸函数的核心性质之一是局部最优等于全局最优。B 错:凸函数要求 $f’‘(x) \geq 0$。C 错:$f(x) = x^2$ 是凸函数且有最小值 $0$。D 错:$f(x) = x^3$ 是多项式但不是凸函数。

第6题

对于回归问题,假设真实值和预测值的误差分布符合正态分布且均值为 0,以下哪个指标最能反映模型的整体预测精度?

A. 最大绝对误差(Max Error) B. 中位数绝对误差 C. 极差(Range) D. 均方误差(MSE)

答案:D

考点:机器学习——评价指标

误差服从均值为 $0$ 的正态分布时,MSE 等价于误差的方差,是正态分布下最大似然估计的充分统计量,最能全面反映整体预测精度。最大绝对误差和极差只关注极端值,中位数绝对误差对异常值鲁棒但丢失了分布的完整信息。

第7题

关于 Pass@k(代码生成常用)中 “k” 的含义,正确的是?

A. 把 $k$ 道题的平均正确率作为指标 B. 从 $k$ 个模型中选最强的一个 C. 生成时把 top_k 设置为 $k$ D. 对同一题生成 $n$ 个候选($n \geq k$),随机抽取 $k$ 个,$k$ 个中至少有一个通过就算成功

答案:D

考点:大模型——评价指标

Pass@k 的定义是:对同一个问题生成 $n$($n \geq k$)个候选解,随机抽取 $k$ 个,只要其中至少有一个通过所有测试用例就算成功。它衡量的是”给模型 $k$ 次机会能否解出该题”的概率。与题目数量、模型数量、采样参数 top_k 均无关。

第8题

以下推理代码速度较慢,最有效的优化方向是什么?

generated = input_ids
for _ in range(max_new_tokens):
    out = model(input_ids=generated)
    next_token = out.logits[:, -1, :].argmax(dim=-1, keepdim=True)
    generated = torch.cat([generated, next_token], dim=1)

A. 每步都重新 tokenize B. 将 max_new_tokens 增大 C. 把 argmax 改成 topk D. 使用 past_key_values(KV Cache)避免重复计算历史上下文

答案:D

考点:大模型——推理优化

代码每步将完整 generated 序列传入模型,重新计算所有历史 token 的注意力,计算量随序列长度二次增长。使用 KV Cache 后,每步只传入新 token,历史 Key/Value 从缓存读取,将每步计算量降为常数级。

第9题

关于多头注意力(MHA)和分组查询注意力(GQA)的区别,下列说法正确的是?

A. GQA 只能用于解码器 B. MHA 比 GQA 参数量更少 C. GQA 中每个头有自己的 K 和 V,而 MHA 共享 D. GQA 中多个查询头共享一组 K 和 V

答案:D

考点:大模型——注意力机制

GQA(Grouped Query Attention)的核心是将查询头分组,每组共享一套 K/V 投影,减少 KV Cache 的显存占用。A 错:GQA 不限于解码器;B 错:GQA 的 K/V 参数更少,MHA 参数量更多;C 恰好说反了。

第10题

关于旋转位置编码(RoPE)的表述,正确的是?

A. RoPE 仅适用于编码器,不适用于自回归解码器 B. RoPE 无法处理超出预训练长度的序列 C. RoPE 通过旋转矩阵对查询和键向量进行变换,使内积蕴含相对位置信息 D. RoPE 将绝对位置信息直接加到词嵌入中

答案:C

考点:大模型——位置编码

RoPE 对 Q 和 K 向量分别乘以与位置相关的旋转矩阵,使得 $q_m^T k_n$ 的内积自然包含相对位置 $m - n$ 的信息。A 错:LLaMA 等解码器广泛使用 RoPE;B 错:可通过 NTK-aware 缩放、YaRN 等扩展上下文长度;D 是原始 Transformer 的绝对位置编码方式。

第11题

设计用于图像分类的 CNN,隐藏层需兼顾计算效率和缓解梯度消失,输出层用于多分类,下列激活函数搭配最合理的是?

A. 隐藏层用 ReLU,输出层用 Softmax B. 隐藏层用 Sigmoid,输出层用 ReLU C. 隐藏层用 Tanh,输出层用 Sigmoid D. 隐藏层用 Softmax,输出层用 Tanh

答案:A

考点:深度学习——激活函数

ReLU 计算高效且正区间梯度恒为 $1$,有效缓解梯度消失;Softmax 将输出映射为概率分布,适合多分类。B 中 Sigmoid 有梯度消失问题,ReLU 无界不适合输出层。C 中 Sigmoid 用于二分类而非多分类。D 中 Softmax 不适合隐藏层。

第12题

关于模型推理前向计算与训练前向计算的区别,下列说法错误的是?

A. 推理前向计算仅需输出最终结果,训练前向计算需保留中间特征用于反向传播 B. 推理前向计算可复用 KV Cache,训练前向计算无需缓存 K/V 向量 C. 推理前向计算与训练前向计算的计算逻辑完全一致,仅输入数据不同 D. 推理前向计算的批量大小通常小于训练,以平衡延迟和吞吐量

答案:C

考点:深度学习——模型推理

C 错误。推理和训练的前向计算存在多处差异:推理时关闭 Dropout、使用 BatchNorm 的 running statistics 而非 batch statistics、可使用 KV Cache 进行增量计算、无需保留计算图。这些都是计算逻辑层面的区别。

第13题

对于函数 $f(x) = \frac{1}{1 + 25x^2}$,在区间 $[-1, 1]$ 上取等距节点进行高次插值,当节点数 $n$ 增大时,插值多项式在区间两端会出现什么现象?

A. 收敛到 $f(x)$ B. 插值多项式趋于零 C. 振荡加剧,误差变大 D. 插值多项式趋于直线

答案:C

考点:数学——数值计算

这是经典的 Runge 现象。对 Runge 函数使用等距节点进行高次多项式插值时,随着 $n$ 增大,插值多项式在区间两端产生剧烈振荡,最大误差趋于无穷。解决方案是使用 Chebyshev 节点(非等距)。

第14题

若向量组 ${v_1, v_2, \ldots, v_k}$ 线性无关,则以下说法正确的是?

A. 不存在不全为零的系数使线性组合为零 B. 可由更少向量生成同一空间 C. 任意两个向量线性相关 D. 向量个数大于维度

答案:A

考点:数学——线性代数

线性无关的定义就是 $c_1 v_1 + \cdots + c_k v_k = 0$ 仅当所有 $c_i = 0$ 时成立。B 错:线性无关说明没有冗余。C 错:线性无关的子集也线性无关。D 错:线性无关要求向量个数不超过空间维度。

第15题

在线性分类模型中,预测函数为 $y = w^T x + b$,设 $w = (2, 3)^T$,$x = (1, 2)^T$,$b = 4$,计算模型输出 $y$:

A. 10 B. 12 C. 11 D. 13

答案:B

考点:机器学习——线性模型

$y = 2 \times 1 + 3 \times 2 + 4 = 2 + 6 + 4 = 12$。

第16题(多选)

影响 GPU 内核占用率的因素包括以下哪些选项?

A. 线程块使用的共享内存大小 B. 线程块的维度设置 C. 每个线程使用的寄存器数量 D. GPU 核心的时钟频率

答案:A, B, C

考点:深度学习——GPU计算

A 正确:共享内存是 SM 上的有限资源,单个线程块使用越多,SM 能同时调度的线程块数越少。B 正确:线程块维度决定每块的线程数,影响 SM 上的 warp 调度。C 正确:寄存器越多,SM 上能活跃的线程总数越少。D 错误:时钟频率影响执行速度,不影响占用率。

第17题(多选)

多 Agent 协作架构中,关于规划和协作策略正确的有?

A. 若所有子任务相互独立且可并行,吞吐量可近似达到单 Agent 的 $n$ 倍;若存在依赖链,则受限于关键路径 B. 主 Agent 在任务分解时应考虑子任务之间的数据依赖关系 C. 当检测到某个子任务 Agent 执行失败时,可根据任务重要性决定重试还是终止整个流程 D. 为减少通信开销,所有子任务应尽可能并行执行,即使存在依赖关系

答案:A, B, C

考点:大模型——多Agent系统

A 正确:独立子任务可完全并行,有依赖时受关键路径约束(Amdahl 定律)。B 正确:必须分析数据依赖。C 正确:容错策略应根据业务重要性灵活处理。D 错误:有依赖关系的子任务强行并行会导致数据不一致。

第18题(多选)

在大语言模型推理阶段,以下哪些技术可以实际降低单 token 的生成延迟?

A. 对模型进行 INT8 权重量化,配合 GPU Tensor Core 执行 B. 使用 KV Cache 避免重复计算历史 token 的 Attention C. 在推理服务中增大 Batch Size 并启用连续批处理(Continuous Batching) D. 采用 FlashAttention / FlashAttention-2 实现 Attention 计算

答案:A, B, D

考点:大模型——推理优化

A 正确:INT8 量化配合 Tensor Core 可提速约 $2$ 倍。B 正确:KV Cache 避免重复计算,显著降低延迟。C 错误:增大 Batch Size 和连续批处理的目标是提高吞吐量,单 token 延迟可能不降反升。D 正确:FlashAttention 通过 IO-aware 分块计算和 kernel fusion 加速。

第19题(多选)

两台处理节点无故障连续运行时间 $X$ 和 $Y$(单位:百小时)相互独立,分别服从参数为 $\lambda_1 = 2$ 和 $\lambda_2 = 3$ 的指数分布。定义 $Z = \min(X, Y)$,以下正确的有?

A. 第一个节点先故障的概率为 $\frac{2}{5}$ B. $Z$ 的数学期望为 $5$ 百小时 C. $P(Z > 1) = e^{-5}$ D. $Z$ 服从参数为 $5$ 的指数分布

答案:A, C, D

考点:数学——概率论

A 正确:$P(X < Y) = \frac{\lambda_1}{\lambda_1 + \lambda_2} = \frac{2}{5}$。B 错误:$E[Z] = \frac{1}{\lambda_1 + \lambda_2} = \frac{1}{5}$ 百小时 = 20 小时,不是 5 百小时。C 正确:$P(Z > 1) = e^{-(\lambda_1 + \lambda_2) \cdot 1} = e^{-5}$。D 正确:独立指数分布的最小值仍服从指数分布,参数为 $\lambda_1 + \lambda_2 = 5$。

第20题(多选)

混合精度训练中,使用 FP16 计算时出现数值不稳定问题,以下分析正确的有?

A. Softmax 计算 $e^{x_i}$ 时,当 $x_i$ 较大在 FP16 中容易溢出 B. 可以使用 max-shift 技巧:先减去 $\max(x)$ 再计算指数,避免溢出 C. 对于 BatchNorm 层,使用 FP32 存储移动均值和方差可以提高数值稳定性 D. LayerNorm 在混合精度训练中完全没有数值风险

答案:A, B, C

考点:深度学习——混合精度训练

A 正确:FP16 最大值约 65504,$e^{11}$ 就超过该范围。B 正确:max-shift 是标准的数值稳定技巧,使指数输入 $\leq 0$。C 正确:BatchNorm 的累积统计量用 FP16 会因精度不足导致累积误差。D 错误:LayerNorm 内部也涉及方差计算和除法,FP16 下可能数值不稳定。


第一题:基于最大边际相关性(MMR)的智能示例重排序

题目描述

给定 $N$ 个候选文档,每个文档有唯一 ID 和与查询的相关性分数 $\text{rel}_i \in [0, 1]$。同时给出文档间的 $N \times N$ 相似度矩阵 $\text{sim}$(对称,对角线为 $1$)。

MMR 算法逐轮从未选文档中选择得分最高的加入已选集合 $S$:

\[\text{MMR}(d_i) = \lambda \cdot \text{rel}_i - (1 - \lambda) \cdot \max_{d_j \in S} \text{sim}(d_i, d_j)\]

当 $S$ 为空时,$\max$ 项定义为 $0$。若多个文档得分相等,选 ID 较小的。

给定平衡参数 $\lambda$ 和返回数量 $K$,输出按选择顺序排列的 $K$ 个文档 ID。

数据范围:$N \leq 1000$,$K \leq N$。

样例

输入

3
0.9 101
0.6 102
0.3 103
1.0 0.95 0.2
0.95 1.0 0.1
0.2 0.1 1.0
0.7 2

输出

101 103

思路分析

第一步:理解 MMR 解决的问题

搜索引擎返回结果时,如果前几条都是高度相似的文档,用户体验很差。MMR 的思路是:每次选下一篇文档时同时考虑”和查询有多相关”以及”和已选文档有多不一样”。$\lambda$ 控制两者的权重:$\lambda = 1$ 只看相关性,$\lambda = 0$ 只看多样性。

第二步:贪心模拟流程

每轮扫描所有未选文档,计算 MMR 得分,选最高的加入 $S$。关键优化:维护一个 max_sim 数组记录每个未选文档与已选集合中最相似文档的相似度。每次选入新文档 $d^$ 后,只需用 $\text{sim}(d_i, d^)$ 更新 max_sim[i]——因为集合只在扩大,$\max$ 只增不减,取 max 即可。

第三步:平局处理

得分相同时选 ID 较小的文档。

样例推导:初始 $S$ 为空,MMR 得分仅由相关性决定:文档 101 得分 $0.7 \times 0.9 = 0.63$ 最高,选入。更新后:文档 102 的 $\text{maxSim} = 0.95$,得分 $0.7 \times 0.6 - 0.3 \times 0.95 = 0.135$;文档 103 的 $\text{maxSim} = 0.2$,得分 $0.7 \times 0.3 - 0.3 \times 0.2 = 0.15$。选 103。

题解代码

import sys
input = sys.stdin.readline

N = int(input())
rel = []
ids = []
for _ in range(N):
    parts = input().split()
    rel.append(float(parts[0]))
    ids.append(int(parts[1]))

sim = []
for _ in range(N):
    sim.append(list(map(float, input().split())))

parts = input().split()
lam = float(parts[0])
K = int(parts[1])

selected = [False] * N
max_sim = [0.0] * N
result = []

for _ in range(K):
    best_score = -1e18
    best_idx = -1
    for i in range(N):
        if selected[i]:
            continue
        score = lam * rel[i] - (1 - lam) * max_sim[i]
        if score > best_score or (score == best_score and (best_idx == -1 or ids[i] < ids[best_idx])):
            best_score = score
            best_idx = i
    result.append(ids[best_idx])
    selected[best_idx] = True
    # 增量更新:新文档加入后,其他文档的 max_sim 只可能增大
    for i in range(N):
        if not selected[i] and sim[i][best_idx] > max_sim[i]:
            max_sim[i] = sim[i][best_idx]

print(' '.join(map(str, result)))

复杂度分析

时间复杂度:$O(NK)$,每轮遍历 $N$ 个文档计算得分并更新 max_sim空间复杂度:$O(N^2)$,存储相似度矩阵。


第二题:决策树实现网络设备故障预测

题目描述

在大型网络运维系统中,交换机和路由器持续上报 CPU 使用率、内存占用、丢包率、温度等指标。给定各指标的阈值,当指标值 $\geq$ 阈值时记为 $1$(异常),否则记为 $0$(正常)。

请实现以下流程:

  1. 将原始连续特征按阈值离散化为 $0/1$
  2. 使用 ID3 决策树算法(基于信息增益)学习特征与故障的关系
  3. 对新样本进行预测

信息熵:$H(D) = -\sum_k p_k \log_2 p_k$

信息增益:$\text{Gain}(D, A) = H(D) - H(D \mid A)$

数据范围:$N \leq 1000$,$M \leq 20$。

样例

输入

10 3
75.0 65.0 5.0
60.5 60.2 3.1 0
80.3 70.8 6.2 1
78.7 60.4 6.5 1
72.1 68.9 4.2 0
90.6 80.1 7.3 1
85.2 62.5 3.6 0
65.4 75.3 6.8 1
70.8 60.7 5.0 0
88.9 66.2 4.8 1
74.6 72.4 6.1 1
3
82.5 64.0 4.0
68.2 70.5 6.2
91.0 60.3 3.2

输出

0 1 0

思路分析

第一步:特征离散化

题目给出每个特征的阈值 $t_j$,离散化规则为:$\text{feature}{ij} = 1$ 当 $x{ij} \geq t_j$,否则为 $0$。这样连续指标变成了”是否告警”的二值信号,非常适合 ID3 算法。

第二步:ID3 决策树的核心——信息增益

ID3 在每个节点选择信息增益最大的特征来划分数据。信息熵衡量数据的”混乱程度”:10 台设备里 5 台故障 5 台正常时 $H = 1$(最混乱);全部故障时 $H = 0$(最纯净)。信息增益 = 划分前的熵 - 划分后的条件熵,增益越大说明按这个特征分组后数据变得越”纯净”。

第三步:递归建树

选好划分特征后,按 $0/1$ 值将数据分成两组递归建子树。终止条件:

  • 当前样本标签全部相同 → 建叶节点
  • 没有可用特征 → 建叶节点,取多数类
  • 某分支为空 → 取父节点多数类

第四步:注意平局处理

若多个特征的信息增益相同,选索引最小的特征。若多数投票平局($0$ 和 $1$ 样本数相同),选 $0$。

题解代码

import sys
import math
input = sys.stdin.readline

def entropy(labels):
    n = len(labels)
    if n == 0:
        return 0.0
    counts = [0, 0]
    for l in labels:
        counts[l] += 1
    h = 0.0
    for c in counts:
        if c > 0:
            p = c / n
            h -= p * math.log2(p)
    return h

def majority(labels):
    counts = [0, 0]
    for l in labels:
        counts[l] += 1
    return 0 if counts[0] >= counts[1] else 1

def build_tree(data, labels, features):
    if len(set(labels)) == 1:
        return labels[0]
    if not features:
        return majority(labels)

    n = len(labels)
    base_ent = entropy(labels)
    best_gain = -1.0
    best_feat = -1

    for f in features:
        groups = {0: [], 1: []}
        for i in range(n):
            groups[data[i][f]].append(labels[i])
        cond_ent = 0.0
        for sub in groups.values():
            if sub:
                cond_ent += len(sub) / n * entropy(sub)
        gain = base_ent - cond_ent
        if gain > best_gain + 1e-12 or (abs(gain - best_gain) < 1e-12 and (best_feat == -1 or f < best_feat)):
            best_gain = gain
            best_feat = f

    remaining = [f for f in features if f != best_feat]
    maj = majority(labels)

    children = {}
    for v in [0, 1]:
        sub_data = [data[i] for i in range(n) if data[i][best_feat] == v]
        sub_labels = [labels[i] for i in range(n) if data[i][best_feat] == v]
        if not sub_data:
            children[v] = maj
        else:
            children[v] = build_tree(sub_data, sub_labels, remaining)
    return (best_feat, children)

def predict(tree, sample):
    if not isinstance(tree, tuple):
        return tree
    feat, children = tree
    return predict(children[sample[feat]], sample)

N, M = map(int, input().split())
thresholds = list(map(float, input().split()))

data = []
labels = []
for _ in range(N):
    parts = list(map(float, input().split()))
    row = [1 if parts[j] >= thresholds[j] else 0 for j in range(M)]
    data.append(row)
    labels.append(int(parts[M]))

q = int(input())
tests = []
for _ in range(q):
    parts = list(map(float, input().split()))
    row = [1 if parts[j] >= thresholds[j] else 0 for j in range(M)]
    tests.append(row)

tree = build_tree(data, labels, list(range(M)))
results = [str(predict(tree, t)) for t in tests]
print(' '.join(results))

复杂度分析

时间复杂度:建树 $O(M^2 \cdot N)$,每层遍历 $M$ 个特征各扫描 $N$ 个样本,最多 $M$ 层。预测 $O(Q \cdot M)$。 空间复杂度:$O(NM)$,存储离散化后的训练数据和决策树节点。


小结

  • 选择题重点覆盖大模型推理优化(KV Cache、GQA、RoPE、量化、FlashAttention)和深度学习基础(CNN 卷积计算、激活函数、混合精度训练),是华为 AI 岗的核心考点方向
  • 第一题 MMR 算法是信息检索的经典方法,核心在于用 max_sim 数组做增量更新,每轮 $O(N)$ 扫描即可
  • 第二题 ID3 决策树是机器学习基础中的基础,关键在于正确实现信息熵计算、递归建树的终止条件、以及空分支和平局的处理