华为 8.5 AI 方向机考复盘:60 分的选择题,错在哪些知识盲区

2026 年 8 月 5 日华为 AI 方向机考复盘:两道编程题(DBSCAN 判定 + 最优次优状态 DP)与 20 道选择题按考点分组讲解,诚实记录失分结构,末尾附待补知识点清单

华为 8.5 AI 方向机考复盘:60 分的选择题,错在哪些知识盲区

题目与官方解析来源:CodeFun2000.com(塔子哥)——华为机考 AI 方向 2026-08-05 场次,AI 算法/应用开发/数据科学等 AI 开头岗位统考,不区分部门。 我的成绩:选择题 20 题对 10 题,60/150(15×6 分 + 5×12 分)。

写在前面:这场考试在考什么

这套卷子的知识面比我想象的宽。传统 ML 数学基础(贝叶斯、插值、SVD、余弦相似度)有,但更重的是训练工程实践和大模型前沿:warmup、梯度裁剪、混合精度、端侧推理峰值内存、GSPO、Householder、梯度零空间、在线学习——这些是我平时刷算法题完全接触不到的东西。

我的成绩结构很能说明问题:对的全是 6 分基础题,5 道 12 分大题全错。60 分 = 10 × 6 分,一道 12 分题都没拿到。这说明我的知识结构是"会做题,不懂训练与前沿"——基础数学和概念推导还凑合,但凡涉及深度学习工程和大模型 RL 的就露馅。

先说清楚一个诚实声明:转贴时不少选择题的公式数值没有带过来,但后来我从微信公众号原文的底层 HTML(mdnice 的 data-formula 属性)里把 LaTeX 源码全部提取出来了,本文所有数值与官方解析一致,不是编造的。


一、编程题复盘

第 1 题:基站空间重叠区域识别(150 分,模拟)

这道题是 DBSCAN 的判定子集:只标记每个点的属性(核心点/边界点/噪声点),不做簇扩展和簇编号,所以是个纯模拟题。

核心定义只有三条:

  • 空间邻域:两基站曼哈顿距离 $d = |x_i - x_j| + |y_i - y_j| \le \varepsilon$ 即互为邻域。邻域包含自身——这是最容易漏的点,每个点的邻居数至少为 1。
  • 核心点:邻域内基站总数 $\ge m$(邻域数量门限)。
  • 边界点:自己不是核心点,但邻域内至少有一个核心点。否则是噪声点。

两阶段模拟:第一遍 $O(n^2)$ 统计每个点的邻居数、标记核心点;第二遍非核心点去查核心点集合,距离 $\le \varepsilon$ 就是边界点。总复杂度 $O(n^2)$。原题数据范围:$N \in [1, 2000]$、$\varepsilon \in [0, 10000]$、$MinPts \in [1, N]$、坐标 $[-10000, 10000]$——$O(N^2)$ 最多 400 万对距离计算,完全没问题。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import sys

def solve(p, e, m):
    n = len(p)
    core = [False] * n

    # 第一阶段:统计邻域数量(含自身),判定核心点
    for i in range(n):
        cnt = 0
        for j in range(n):
            d = abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1])
            if d <= e:
                cnt += 1
        if cnt >= m:
            core[i] = True

    # 第二阶段:默认全噪声,再标注核心点/边界点
    ans = [2] * n
    for i in range(n):
        if core[i]:
            ans[i] = 0
        else:
            for j in range(n):
                if core[j]:
                    d = abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1])
                    if d <= e:
                        ans[i] = 1
                        break
    return ans

def main():
    data = list(map(int, sys.stdin.buffer.read().split()))
    n, e, m = data[0], data[1], data[2]
    p = []
    k = 3
    for _ in range(n):
        p.append((data[k], data[k + 1]))
        k += 2
    sys.stdout.write("\n".join(map(str, solve(p, e, m))))

if __name__ == "__main__":
    main()

这道题在 CodeFun2000 上的原题是 P5198(https://codefun2000.com/ide/P5198),可以上去刷题评测。我自己用 C++ 又写了一遍(机考常用语言,逻辑和 Python 版完全一致):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 我的 C++ 版 —— CodeFun2000 P5198
#include <iostream>
#include <vector>

using namespace std;

vector<int> solve(const vector<pair<int, int>>& p, int e, int m) {
    int n = p.size();
    vector<bool> core(n, false); // 记录是否是核心

    // 统计每一个基站的邻域数量, 判断是否为核心点
    for (int i = 0; i < n; i++) {
        int cnt = 0;
        for (int j = 0; j < n; j++) {
            int dist = abs(p[i].first - p[j].first) + abs(p[i].second - p[j].second);
            if (dist <= e) cnt++;
        }
        if (cnt >= m) core[i] = true;
    }

    // 默认所有基站均为噪声点
    vector<int> ans(n, 2);
    for (int i = 0; i < n; i++) {
        if (core[i]) ans[i] = 0;
        else {
            for (int j = 0; j < n; j++) {
                if (core[j]) {
                    int dist = abs(p[i].first - p[j].first) + abs(p[i].second - p[j].second);
                    if (dist <= e) {
                        ans[i] = 1;
                        break;
                    }
                }
            }
        }
    }
    return ans;
}

(main 函数读入 n/e/m 和坐标,逐行输出 solve 的结果即可。)

这道题本身不难,值得记住的是它背后的 DBSCAN:核心点做种子、密度可达做簇扩展。机考只考了属性判定,但理解完整算法才能应对变体。

第 2 题:多 Agent 协作任务调度(300 分,DP 最优+次优状态)

这是本场含金量最高的一道题,也是我想重点记的题。

问题:$n$ 个 Agent,第 $i$ 个每次调用推进 $p_i$ 个百分点、花费 $c_i$ 代价,同一 Agent 可调用任意次但不能连续两次调用同一个,进度 $\ge 100$ 视为完成,求最小总代价。

为什么朴素 DP 不够。最直接的思路是 $dp[s][i]$ = 进度 $s$、最后一次调 Agent $i$ 的最小代价,转移时枚举上一个 Agent $j \ne i$。复杂度 $O(100 \cdot n^2)$,n 稍大就超时。核心矛盾是:转移时我们根本不需要"每个 Agent 的完整代价",只需要知道"上一个状态最后调的 Agent 是谁"——但朴素 DP 被迫把全部信息都存了下来。

关键洞察:每个进度只需要保留两个状态。对于进度 $s$,设:

  • $best_1[s]$:最小代价,$id_1[s]$ 是它最后调的 Agent;
  • $best_2[s]$:代价次小、且 $id_2[s] \ne id_1[s]$ 的状态。

为什么两个就够?因为转移的唯一约束是"下一个 Agent $i$ 不能等于上一个状态的最后 Agent"。所以当我要从进度 $s$ 调 Agent $i$ 时:

  • 若 $id_1[s] \ne i$:直接用最优状态 $best_1[s]$;
  • 若 $id_1[s] = i$:只能用次优状态 $best_2[s]$(它的最后 Agent 必然不是 $i$)。

也就是说,$best_2$ 是专门为"$best_1$ 的最后 Agent 恰好是我们要调的那个"这种冲突准备的备胎。这是经典的"最优+次优"DP 技巧——把 $O(n^2)$ 的枚举压成 $O(1)$ 的取备胎,总复杂度降到 $O(100 \cdot n)$。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import sys

INF = 10 ** 30

def update(best1, best2, id1, id2, pos, cost, agent):
    """把「以 agent 结尾、代价 cost」的新状态并入 pos 进度的两个最优状态。"""
    if id1[pos] == agent:
        if cost < best1[pos]:
            best1[pos] = cost
        return
    if id2[pos] == agent:
        if cost < best2[pos]:
            best2[pos] = cost
            if best2[pos] < best1[pos]:
                best1[pos], best2[pos] = best2[pos], best1[pos]
                id1[pos], id2[pos] = id2[pos], id1[pos]
        return
    if cost < best1[pos]:
        best2[pos], id2[pos] = best1[pos], id1[pos]
        best1[pos], id1[pos] = cost, agent
    elif cost < best2[pos]:
        best2[pos], id2[pos] = cost, agent

def min_cost(p, c):
    n = len(p)
    best1 = [INF] * 101
    best2 = [INF] * 101
    id1 = [-2] * 101
    id2 = [-2] * 101

    best1[0] = 0   # 进度 0,代价 0,-1 表示还没调用过任何 Agent
    id1[0] = -1

    for s in range(100):
        if best1[s] == INF:
            continue
        for i in range(n):
            base = best1[s] if id1[s] != i else best2[s]
            if base == INF:
                continue
            t = min(100, s + p[i])          # 进度超过 100 统一压缩为 100
            update(best1, best2, id1, id2, t, base + c[i], i)

    return best1[100] if best1[100] != INF else -1

def main():
    data = list(map(int, sys.stdin.buffer.read().split()))
    n = data[0]
    p, c = [0] * n, [0] * n
    pos = 1
    for i in range(n):
        p[i], c[i] = data[pos], data[pos + 1]
        pos += 2
    print(min_cost(p, c))

if __name__ == "__main__":
    main()

注意两个边界:进度超过 100 统一压到 100(题目允许超额完成);单 Agent 时无法完成任务输出 -1(样例 1 就是)。


二、选择题复盘(按考点分组)

我把 20 题按知识域分组,对题简讲、错题详讲。✅ = 我答对,❌ = 我答错。

1. 数学基础

#1 Softmax 数值稳定(✅)

当 $x_i$ 较大(如 $>1000$)时直接算 $e^{x_i}$ 会数值溢出,正确的稳定化实现是:对所有 $x_i$ 减去最大值 $x_i' = x_i - \max(x)$ 再算指数。

这题我会。关键在于 exp 的缩放不变性:分子分母同乘 $e^{-M}$ 不改变比值——

$$\text{softmax}(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}} = \frac{e^{x_i - M}}{\sum_j e^{x_j - M}}, \quad M = \max_j x_j$$

减去最大值后最大的指数项是 $e^0 = 1$,其余都小于 1,不会溢出。FP64 只是缓解不是根治,L2 归一化会改变结果,除以最大值没用——只有减最大值是对的。

#4 欧氏距离(✅):两个嵌入向量 $u, v$ 的欧氏距离是 $\|u - v\|_2 = \sqrt{\sum_i (u_i - v_i)^2}$,距离越小越相似。原题给 $v_x = [2, 3]^T$、$v_y = [4, 1]^T$:

$$\|v_x - v_y\|_2 = \sqrt{(2-4)^2 + (3-1)^2} = \sqrt{4 + 4} = \sqrt{8}$$

答案 D。干扰项 $\sqrt{5}$ 是把差的平方算成差的绝对值平方,$\sqrt{13}$、$\sqrt{10}$ 是把向量模当距离。

#8 余弦相似度(✅):$\cos(u, v) = \dfrac{u \cdot v}{\|u\| \|v\|}$,只看方向不看长度。原题 $x = (1, 0, 1)$、$y = (1, 1, 0)$:

$$x^T y = 1 \times 1 + 0 \times 1 + 1 \times 0 = 1, \qquad \|x\| = \|y\| = \sqrt{1^2 + 1^2} = \sqrt{2}$$$$\cos\theta = \frac{1}{\sqrt{2} \times \sqrt{2}} = \frac{1}{2} = 0.5$$

答案 A。干扰项 0.707 是 $\frac{1}{\sqrt{2}}$——把分母错算成一个模。

#9 二次插值(✅):给定 3 个点可唯一确定二次多项式,代值求解即可(拉格朗日或待定系数法)。原题三点 $(0, 1), (1, 2), (2, 5)$,求 $x = 1.5$ 处值:

$$p(x) = x^2 + 1, \qquad p(1.5) = 1.5^2 + 1 = 2.25 + 1 = 3.25$$

答案 D。这个题最稳的做法是把三点代入 $p(x) = ax^2 + bx + c$ 解出系数——$p(0)=c=1$、$p(1)=a+b+c=2$、$p(2)=4a+2b+c=5$,得 $a=1, b=0, c=1$。

#7 贝叶斯(✅):经典的两公司次品率题。设 A 供应比例 $P(A)$、次品率 $P(D|A)$,B 同理,抽到次品来自 B 的概率是

$$P(B|D) = \frac{P(D|B)\,P(B)}{P(D|A)\,P(A) + P(D|B)\,P(B)}$$

原题数值:A 公司供应 70%、次品率 2%,B 公司供应 30%、次品率 4%。抽到次品来自 B 的概率

$$P(B|D) = \frac{P(D|B)\,P(B)}{P(D|A)\,P(A) + P(D|B)\,P(B)} = \frac{0.04 \times 0.3}{0.02 \times 0.7 + 0.04 \times 0.3} = \frac{0.012}{0.026} \approx 0.4615$$

答案 C,约 46.2%。注意分子是"B 供应的 30% 里次品的 4%",分母是两家各自贡献的次品总量——这就是全概率公式的分母。陷阱:不要直接用 $P(D|B) = 4\%$ 当答案,那忽略了 A 公司的次品贡献。

#6 SVD 存储空间减少比例(❌ 我不该错)

用户-短视频评分矩阵 $m \times n$,SVD 保留秩 $k$,存储减少比例约多少?

这是我最懊恼的一道——公式我是知道的,但考场上算错了。

SVD 压缩的原理:$A_{m\times n} \approx U_{m\times k}\, \Sigma_{k\times k}\, V^T_{k\times n}$,存储量从 $mn$ 降到 $k(m+n)+k \approx k(m+n)$。减少比例

$$\text{减少比例} = 1 - \frac{k(m+n)}{mn}$$

原题数值:矩阵 $1000 \times 800$,保留秩 $k = 50$。原矩阵存 $1000 \times 800 = 800000$ 个元素;SVD 后存 $U$($1000 \times 50$)+ $\Sigma$($50$)+ $V^T$($50 \times 800$)= $50000 + 50 + 40000 = 90050$。减少比例

$$1 - \frac{90050}{800000} = 0.8874 \approx 88.74\%$$

答案 A。为什么 SVD 能省空间?因为原始矩阵存的是 $mn$ 个元素,而低秩近似只存"分解出来的骨架":左奇异向量、奇异值、右奇异向量,三者加起来远小于 $mn$(当 $k \ll \min(m,n)$)。这题的教训是:公式会背 ≠ 考场算对,SVD 存储公式要能当场推一遍而不是凭记忆。

2. 机器学习基础

#11 MLE(✅):最大似然估计就是"找一个参数 $\theta$,让已观测数据出现的可能性最大"——选 D,逆向思考的表述。这题是概念题,没难度。

#14 集中趋势(✅):描述中心位置用均值(B);偏度描述不对称,标准差和方差描述离散程度。概念题。

#5 反向传播(✅):单神经元 $y = wx + b$,恒等激活,MSE 损失。链式法则:

$$\frac{\partial L}{\partial w} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial w} = (y - t) \cdot x$$

原题数值:$x = 2, w = 1, b = 0, t = 5$,$L = \frac{1}{2}(y - t)^2$。输出 $y = wx + b = 2$,链式法则:

$$\frac{\partial L}{\partial w} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial w} = (y - t) \cdot x = (2 - 5) \times 2 = -6$$

答案 C。基础反传导数题,会链式法则就能做;$L$ 带 $\frac{1}{2}$ 系数是为了求导后约掉,这是 MSE 的常见写法。

#3 HRL 分层强化学习 + 级联惩罚(✅)

任务 A→B→C→D 严格顺序依赖,B 失败则 C、D 跳过。A 成功、B 失败,求总奖励。级联惩罚 = 被跳过子任务基础奖励的平均值的负值,只加在失败子任务上。

这题我理解了规则就能算对。通式:若 B 失败(A 已成功),总奖励为

$$R = R_A + P_B - \frac{R_C + R_D}{2}$$

套用原题数值:$R_A = 5$,$R_B = 8$,$P_B = -\frac{R_B}{4} = -2$,$R_C = 12$,$R_D = 16$,级联惩罚为 $-\frac{R_C + R_D}{2} = -\frac{12+16}{2} = -14$。总奖励

$$R = 5 + (-2) + (-14) = -11$$

答案 B。关键陷阱是:被跳过的 C、D 本身不获得任何奖励或惩罚,只是它们的奖励平均值作为级联惩罚扣在 B 头上(注意惩罚是负值累加,不是"扣 C、D 各一半")。

#12 逻辑回归的评价指标(❌ 基础盲区)

逻辑回归性能评价不包括:A. Log Loss B. AUC C. Accuracy D. 均方误差(MSE)。答案 D。

这题错得很基础。逻辑回归是分类模型,评价用准确率、AUC、对数损失;MSE 是回归指标。当时我大概是"看着四个选项都觉得眼熟"就选错了——这是概念没建起"模型类型 → 评价指标"的映射表。

更值得记的 WHY:逻辑回归训练不用 MSE 而用交叉熵,有两个原因。一是凸性——MSE 对 sigmoid 复合后是非凸函数,交叉熵是凸的,保证收敛到全局最优;二是梯度特性——MSE 在 sigmoid 饱和区梯度趋近于零(梯度消失),交叉熵的梯度 $\hat{y} - y$ 与激活饱和无关。评价指标和损失函数是两回事,但背后的逻辑是相通的。

3. 深度学习与训练工程(4 题全错,最大失分区)

#13 端侧推理峰值内存(❌)

哪项因素最可能导致实际峰值内存显著超过模型文件大小?答案 A:中间激活、临时 buffer 和多分支并发执行。

模型文件只存权重参数,但推理时内存 = 权重 + 中间激活值 + 算子临时 buffer + 并发分支结果。激活值才是内存大头:一个 $1 \times 3 \times H \times W$ 的中间特征图动辄几十 MB,多头/多分支并行时还要同时存多份。所以"模型 100MB,跑起来峰值 1GB+“是常态。我当时选了别的选项,本质是没建立"静态权重 vs 动态激活"的内存心智模型。

#17 早期停止(❌ 多选题)

正确说法:A. 可设 patience 允许连续几轮不下降;B. 根据验证集表现选最佳轮数模型;C. 验证集最优则测试集一定最好(错);D. 限制训练时间从而限制可学习的数据量(错)。答案 A、B。

C 的陷阱是"一定”——验证集最优不能保证测试集最优(可能有轻微过拟合到验证集)。D 的陷阱更隐蔽:早期停止限制的是继续拟合训练数据的程度(epoch 数),不是"能用的数据量"——数据量是固定的,它限制的是在数据上反复学多少遍。多选陷阱往往藏在绝对化表述(“一定”)和概念偷换(“训练时间” vs “数据量”)里。

#18 梯度矩阵的秩与零空间(❌ 多选题)

已知卷积网络梯度矩阵 $A \in \mathbb{R}^{1000 \times 2000}$,秩 $r(A) = 500$。说法:A. 零空间维度高 → 存在多个方向使梯度投影为零,一阶变化为零,易陷入平坦区/鞍点;B. 零空间维越高 → 有效信息维度越低,无效方向越多;C. 该梯度矩阵零空间维度 = 1500;D. 增大 batch 可直接降低零空间维度(错)。答案 A、B、C。

核心是秩—零空间定理(Rank-Nullity Theorem):对 $1000 \times 2000$ 矩阵,$\text{rank}(A) + \text{nullity}(A) = 2000$(列数),所以 $\dim N(A) = 2000 - 500 = 1500$——这就是 C 的答案,2000 个参数方向里 1500 个是"无效方向"。零空间里的方向 $v$ 满足 $Av = 0$,意味着沿 $v$ 更新参数时所有样本的梯度贡献都是零——损失函数沿这些方向的一阶变化为零,梯度下降在这些方向上看不到"下坡路",所以容易卡在鞍点或平坦区。这就是"梯度冗余 → 优化困难"的机理。D 错在:batch 大小影响梯度估计的噪声和矩阵结构,但不能保证零空间维度降低。

这题是线代定理和深度学习优化的交叉题,答错说明我对"零空间"只有名词印象,没有几何直觉。

#20 大模型训练稳定性(❌ 多选题)

常用手段:A. 学习率 warmup;C. 梯度裁剪;D. 混合精度(FP16/BF16)。B. 固定学习率全程(错)。答案 A、C、D。

  • warmup:训练初期学习率从 0 线性爬升。为什么需要?因为初始权重下 loss 曲面陡峭、梯度的统计量不可靠,一步迈太大直接发散;等梯度统计稳定了再放开学习率。
  • 梯度裁剪:梯度范数超过阈值就缩放回阈值。对抗梯度爆炸(RNN/长序列尤其需要)。
  • 混合精度:FP16/BF16 存权重和激活、FP32 存主权重,配合 loss scaling。省显存、提速度,BF16 的动态范围大所以大模型训练更常用。
  • 固定学习率从头到尾在真实训练里基本不存在——通常会配 warmup + 余弦退火或别的调度。

这题是纯工程知识,我完全没接触过训练大模型,全错不冤。

4. 大模型 / 多模态 / RL(2 题错)

#2 VQA(✅):视觉问答,输入是图像 + 文本问题,输出是文本答案。多模态入门概念,我会。

#10 RAG 余弦相似度匹配等级(❌)

用户查询向量 vs 历史故障案例向量,算余弦相似度保留 3 位小数,再判断匹配等级(极高/高/中等阈值)。答案:余弦相似度 ≈ 0.989,属于极高匹配。

原题数值:查询向量 $q = [0.8, 1.2, 1.6, 2.0]$,历史案例向量 $c = [1.0, 0.8, 1.4, 1.8]$;阈值:$\ge 0.95$ 极高匹配、$0.85 \sim 0.95$ 高匹配、$< 0.85$ 中等匹配。完整计算:

$$q^T c = 0.8 \times 1.0 + 1.2 \times 0.8 + 1.6 \times 1.4 + 2.0 \times 1.8 = 0.8 + 0.96 + 2.24 + 3.6 = 7.6$$$$\|q\| = \sqrt{0.8^2 + 1.2^2 + 1.6^2 + 2.0^2} = \sqrt{8.64}, \qquad \|c\| = \sqrt{1.0^2 + 0.8^2 + 1.4^2 + 1.8^2} = \sqrt{6.84}$$$$\cos\theta = \frac{q^T c}{\|q\|\|c\|} = \frac{7.6}{\sqrt{8.64} \times \sqrt{6.84}} \approx 0.989$$

答案 B:$\approx 0.989$,$\ge 0.95$ 属于极高匹配。这是"计算 + 阈值判断"两段式题——我公式会但考场上算错,教训是这种题要一步步写:内积、两个模、比值、对照阈值,中间任何一步粗心都会丢分。RAG 检索的核心就是 embedding 向量相似度,这是大模型应用的必考方向,需要练熟。

#15 GSPO 序列级重要性采样(❌)

GSPO 引入序列级(sequence-level)重要性采样比率的主要原因:A. 减少长序列中 token 级比率的高方差问题。答案 A。

GSPO = Group Sequence Policy Optimization(Qwen3 系列使用的 RL 训练算法,arXiv:2507.18071)。这是我完全没接触过的前沿,考场上只能蒙。现在补上了:

  • 在 GRPO 里,重要性采样比率是 token 级的:$r_t = \dfrac{\pi_\theta(y_t|x)}{\pi_{\theta_{old}}(y_t|x)}$。
  • 序列级比率把整个序列的似然比开 $|y_i|$ 次方(长度归一化的几何平均):
$$s_i(\theta) = \left( \frac{\pi_\theta(y_i|x)}{\pi_{\theta_{old}}(y_i|x)} \right)^{1/|y_i|} = \left( \prod_{t=1}^{|y_i|} r_{i,t} \right)^{1/|y_i|}$$
  • 为什么要序列级:token 级比率在长序列里是逐 token 相乘累积的,方差随序列长度爆炸(乘法累积噪声),而序列级比率对齐了"奖励在序列级给出"的事实,方差更稳定,还天然免疫 MoE 专家路由变化的扰动。所以 GSPO 训练长思维链模型比 GRPO 稳定。

一句话记忆:token 级比率是"有偏但低方差"的简化,序列级比率用长度归一化换稳定性——GSPO 选后者。

5. 数值线性代数(1 题错)

#16 Householder 变换(❌ 多选题)

正确说法:A. Householder 矩阵是正交矩阵;C. Householder QR 比 Gram-Schmidt 数值更稳定;D. Householder 矩阵是对称矩阵。B. 行列式为 +1(错,是 −1)。答案 A、C、D。

Householder 反射矩阵:$H = I - \dfrac{2vv^T}{v^T v}$($v$ 是单位向量时简化为 $I - 2vv^T$)。性质:

  • 对称:$H^T = H$;
  • 正交:$H^T H = H^2 = I$;
  • 行列式 = −1:它是一次反射(镜面变换),反射改变手性,所以行列式是 −1 而不是 +1。

它把一个向量反射到坐标轴方向,用于 QR 分解时比 Gram-Schmidt 数值稳定——Gram-Schmidt 的经典形式在列向量近似线性相关时会丢失正交性(重正交化开销大),Householder 用反射矩阵逐列消元,数值更稳。当时我连"反射 = 行列式 −1"这个直觉都没有,更别说 QR 稳定性对比了。

6. 在线学习(1 题错)

#19 在线逻辑回归(❌ 多选题)

正确说法:A. 每次一个样本更新 = batch size 1 的 SGD;B. AdaGrad 自适应学习率在稀疏特征场景优于固定学习率;C. 在线学习比批量训练更能适应概念漂移。D. 固定学习率保证收敛到全局最优(错)。答案 A、B、C。

  • A 是定义:在线学习一次一个样本,就是 $batch=1$ 的随机梯度下降。
  • B:AdaGrad 对每个参数单独维护累计梯度平方,出现少的特征(稀疏)保持较大学习率,所以适合稀疏场景——固定学习率做不到这种自适应。
  • C:在线学习持续用新数据更新,分布变了模型跟着变;批量训练用旧数据拟合的模型对概念漂移反应慢。
  • D:固定学习率参数会在最优点附近震荡,不保证严格收敛。

三、失分结构:60 分是怎么丢的

知识域题号我的结果
数学基础#1 #4 #7 #8 #9 #65/6(SVD 计算失误)
机器学习基础#11 #14 #5 #3 #124/5(逻辑回归指标盲区)
深度学习与训练工程#13 #17 #18 #200/4 ❌
大模型 / 多模态 / RL#2 #10 #151/3(VQA 对,RAG 算错,GSPO 盲区)
数值线性代数#160/1 ❌
在线学习#190/1 ❌

三条结论:

  1. 基础概念是稳的:贝叶斯、插值、Softmax、反传、MLE 这些传统 ML 数学题全对,说明大学数学底子还在。
  2. 计算题要练"考场态":#6 SVD、#10 RAG 余弦都是"公式会、当场算错",以后这类题必须动笔一步步写,不心算。
  3. 真正的失分大头是知识盲区:训练工程(warmup/混合精度/端侧内存)、大模型对齐(GSPO)、数值线代(Householder/零空间)、在线学习——这四块加起来丢了 5 道 12 分大题中的 4 道。这些是 AI 岗位和普通开发岗的分水岭知识,也是我接下来要补的重点。

四、接下来要补的知识点清单

按优先级和投入产出排序,这些是我后面要逐个补的:

P0(必考高频,先补)

  1. 数值线性代数:SVD 低秩近似与存储压缩(会推导)、Householder 反射与 QR、秩—零空间定理及几何直觉(零空间 = 无效更新方向)。来源:任何一本数值分析教材的前三章 + 线性代数复习。
  2. 训练稳定性工程:学习率 warmup 与调度(余弦退火)、梯度裁剪、混合精度训练(FP16/BF16 + loss scaling)、端侧/训练峰值内存构成(权重 vs 激活 vs buffer)。来源:大模型训练综述/实践文章。
  3. 分类模型评估全家桶:Accuracy / Precision / Recall / F1 / AUC / Log Loss 的适用场景,以及"逻辑回归为什么用交叉熵不用 MSE"(凸性 + 梯度消失)。

P1(AI 岗位特色,补了才有区分度)

  1. 大模型 RL 对齐入门:GRPO → GSPO 的演进(token 级 vs 序列级重要性采样、长度归一化、为什么长思维链训练更稳)。来源:arXiv:2507.18071(GSPO)+ 配套解读。
  2. 在线学习与自适应优化:SGD 家族、AdaGrad / RMSProp / Adam 的动机与适用场景、概念漂移。

P2(算法题技巧,顺手练)

  1. DP"最优+次优状态"技巧:记住"转移约束只跟最优状态的某个属性冲突时,维护两个最优状态即可"这个模式,多 Agent 调度、股票交易类题都会用到。

来源

  • 题目与官方解析:CodeFun2000.com 华为机考 AI 方向 8 月 5 日场次(塔子哥),原文 https://mp.weixin.qq.com/s/3H3agcturofiMn9pOriZOg
  • 第 1 题(基站空间重叠区域识别)原题刷题入口:https://codefun2000.com/ide/P5198
  • GSPO 论文:Group Sequence Policy Optimization(Qwen3),https://arxiv.org/abs/2507.18071
  • 备注:选择题 #3-#10 的数值已从微信公众号原文(mdnice 的 data-formula 属性)提取补全,与官方解析一致。