想象一位老厨师要跳槽到新餐厅。新厨房的灶台、烤箱、锅具全都不一样,但他没有从零开始摸索,而是从老厨房带来一本厚厚的手记:上面记录着各种食材在什么火候、什么时间下最合适。到了新厨房,他只做了几道小菜试了试火,就把手记里的经验校准到新灶台上,很快就能出一桌好菜。 自动调优中的「调优迁移学习」就是这个道理。TVM 在为新硬件或新模型寻找最快计算配置时,每试一种配置都要真实测量一次,开销很大;如果每次都从零开始,成本高得吓人。迁移学习能把「老厨房」里积累的调优经验(源域的代价模型参数)搬到「新厨房」(目标域),只要少量测量数据就能快速建立有效的性能预测模型,大幅降低调优成本。
对 AI 从业者而言,掌握调优迁移学习,意味着你在做编译器性能优化、模型部署加速时,不必每次换硬件或换模型都从零调优;这是 AI 系统工程里最实用的降本增效技能之一。
可视化演示
展示调优迁移学习如何将源域调优经验迁移到目标域,在少量测量数据下快速建立有效的性能预测模型,降低调优成本。
本节配有交互动效(进入视口后自动加载,约 3KB)。
调优迁移学习 源域调优经验积累 代价模型参数迁移 目标域快速建模 CostModel(target) ≈ Transfer(Source params) 少量测量即可建立有效预测模型
背景痛点
老厨师换到新餐厅,不会一上来就写满整墙菜谱。他心里清楚,每道菜的火候参数都要重新试过;如果靠一道菜一道菜地试,可能要试几百次,新餐厅还没开业就关门了。自动调优也一样:TVM 在给新硬件或新模型寻找最优计算配置时,每试一个配置都要在真实设备上跑一遍,测量时间、显存、功耗,成本非常高。
更麻烦的是,这些试错在新硬件上要从零开始。传统方法是把配置空间当作一片未知的火候矩阵,一个个组合试过去,直到找到最快的那组。如果每次换 GPU、换模型都重复这套流程,调优时间会盖过实际收益。
于是研究者把目光投向领域知识:之前在不同 GPU、不同模型上积累的调优数据完全可以当作源域(source domain),而目标域(target domain)则是新硬件上的少量测量数据。假如能复用源域中“哪些参数与性能相关”的规律,目标域就不需要那么多测量。
换句话说,老厨房多年攒下的几百份测试记录,不必在新厨房重写;只需在新厨房做几道小菜,就能把手里的温度感校准到新灶台上。这正是迁移学习解决调优成本的核心逻辑。
- 源域数据集源域由大量配对数据组成,$x_i$ 是一个计算配置,$t_i$ 是它在源设备上的实测耗时。
- 目标域数据集目标域同样包含配置和耗时,但样本数量 $N_t$ 很小,因为新设备上的每次测量都很贵。
- 样本量对比迁移学习的价值前提就是 $N_t \ll N_s$,否则直接在目标域全量调优即可。
迁移思想
老厨师的手记并不是菜谱本身,而是抽象出来的“规则”:油温大概到几成、盐放多少量级,换到新灶台依然有用。迁移学习的思想正是把这种抽象规则从源域搬到目标域。
传统机器学习假设训练和测试来自同一个分布,但迁移学习允许两者不同。我们关心的是:如何用源域大量数据训练一个模型,再用目标域少量数据让它适配。在自动调优中,源域和目标域的任务都是“预测一个配置要跑多久”,只是设备和模型不同。这个共享任务就是迁移的桥梁。
形式上,把源域代价模型的参数记为 $\theta_s$,目标域参数记为 $\theta_t$。迁移不是要求 $\theta_t$ 从零开始,而是先在 $\theta_s$ 附近寻找:每个新参数都可以写成 $\theta_s$ 加上一个小的修正 $\Delta\theta$。
手记里的“火候公式”不是照搬,而是给每一栏加上新老板口味的修正项。这个修正项越准确,适应新厨房就越快。
- 源域参数$\theta_s$ 是老手记里总结出的火候权重,代表源域大量调优经验。
- 修正量$\Delta\theta$ 是由目标域少量样本估计出的偏差,描述新厨房和老厨房的差异。
- 目标域参数$\theta_t$ 是迁移后的模型参数,既保留源域知识,又包含新环境修正。
代价模型
手记里最值钱的是一张“味道预测表”:给定一个火候组合,不用真的做菜也能估出大概需要多长时间。自动调优里的代价模型干的就是这件事。
TVM 在搜索时,先生成一批候选配置,然后交给代价模型打分,只有少数分数最高的配置才送去真实测量。代价模型通常把配置变成特征向量 $\phi(x)$,特征可以包括循环分块大小、是否向量化、缓存利用率等。
最简单的线性代价模型可以写成:
有了代价模型,老厨师可以在心里做模拟实验;但手记是从老厨房总结的,新厨房的灶台加热曲线不同,所以下一节要讨论怎样把 $\theta$ 迁过去。
- 预测值$\hat{t}$ 是模型预测的耗时,带帽记号表示这是估计值,不是真实测量。
- 特征向量$\phi(x)$ 把原始配置 $x$ 编码成数值向量,相当于把“大火、中火、小火”变成数字。
- 模型参数$\theta$ 是权重向量,每一项表示对应特征对耗时有正向还是负向影响。
- 点积运算$\theta^{\top}\phi(x)$ 把权重和特征逐项相乘再求和,得到最终预测。
参数迁移
老厨师到了新厨房,并没有把旧手记丢掉,而是先假定新厨房大部分规则相似,只在新灶台上尝了几道菜,然后把“油温”和“加热时间”那几栏修正过来。参数迁移对待代价模型的 $\theta$ 也是如此:以源域 $\theta_s$ 为锚点微调。
具体做法是在目标域少量样本上求解一个带正则的优化问题。第一项要求迁移后的模型在目标样本上误差小,第二项要求它不要离源域参数太远。$\lambda$ 就是“对新厨房的信任度”:$\lambda$ 越大,越相信旧手记;$\lambda$ 越小,越相信新试菜。
当目标域样本只有十几条时,直接从头学 $\theta$ 会严重过拟合,就像只尝了三道菜就写满整本菜谱。挂在 $\theta_s$ 附近,等于让老厨师用旧手记稳住基本盘,再用新试菜做局部修正。
- 优化目标$\min_\theta$ 表示我们要找一组新参数,使整个目标函数最小。
- 目标域误差$\sum_{(x,t)\in D_t}(\theta^{\top}\phi(x)-t)^2$ 是模型在目标域少量样本上的平方误差总和。
- 迁移正则$\|\theta-\theta_s\|^2$ 度量新参数与源域参数的欧氏距离。
- 平衡系数$\lambda$ 控制正则强度,$\lambda=0$ 时完全相信新样本,$\lambda\to\infty$ 时退化为直接使用源域模型。
调优流程
迁移调优像一次有章法的跳槽,而不是漫无目的地试菜。一般分三步:老厨房总结、搬手记、新厨房校准。
第一步,先在源域做一次完整调优,得到源代价模型 $\theta_s$ 和若干有代表性的最优配置。第二步,建立特征映射,把 $\theta_s$ 初始化到目标代价模型。第三步,在目标域收集少量测量,用上一节的目标函数微调参数,最后用适配后的模型指导新一轮配置搜索。
注意目标域也要做少量真实搜索,不是完全零样本。所谓迁移学习,是把全量搜索变成小样本适配,而不是凭空预测。这样,老厨房的几百次试菜经验只搬一次,新厨房只要十几次试菜就能稳下来。
- 最优配置$\mathcal{A}^*$ 是最终选出的最快计算配置,也就是搜索的目标答案。
- 搜索空间$\mathcal{A}\in\Omega$ 表示所有可能的循环分块、向量化等优化选项组成的空间。
- 用迁移模型打分$\hat{t}(\mathcal{A};\theta_t)$ 是用迁移后的目标代价模型对配置 $\mathcal{A}$ 预测耗时。
收益场景
迁移学习的价值不难算:如果每换一次硬件都要全量调优,产品迭代会被按在试菜台上动弹不得。有了迁移,一次性成本变成可以多次复用的存量成本。
在频繁迭代场景下收益尤其明显:同一个模型部署到不同手机芯片,或同一块 GPU 上持续优化新算子。源域经验不断累积,目标域测量成本从几千次降到几十次。假设每次测量成本为 $c_{\text{meas}}$,迁移后总成本可以写成:
从工程指标看,迁移模型通常能在一开始就给出较准的预测,搜索收敛曲线前段明显抬升。这本手记越厚越值钱:产品线里积累的源域调优数据,会成为面向新硬件时的核心竞争力。
- 总成本$C_{\text{total}}$ 是完成一次新设备调优的全部开销。
- 源域成本$C_{\text{source}}$ 是第一次在老环境做全量调优的沉没成本,之后可复用。
- 迁移成本$C_{\text{transfer}}$ 是训练或微调迁移模型的固定开销。
- 测量成本$N_t$ 是目标域测量次数,乘以单次测量成本 $c_{\text{meas}}$ 得到可变开销。
挑战实践
如果老厨师只会做川菜,硬要跳槽到粤菜馆,旧手记可能反而帮倒忙:他按麻辣思维调火候,做出来的菜面目全非。这就是迁移学习里的负迁移。
源域和目标域差异过大时,迁移后的模型可能比从头训练还差。工程上需要通过相似性检验、正则强度 $\lambda$ 调节,以及少量目标样本验证来规避。如果几个验证点都表明旧经验的误差大于随机猜测,就不该强行迁移。更严格地说,迁移有效当且仅当:
在 TVM 工程实现中,源域和目标域需要共用同一套特征模板,参数才可迁移。调优脚本一般会先加载源域模型文件,再根据目标域的少量样本执行带约束的更新;如果特征不匹配,需要先做特征归一化或改用更鲁棒的迁移方式。所以,手记要用对地方:先尝两筷子,判断是不是同一派系;确认可迁移,才把整本手记搬过来。
---
- 目标域风险$R_t(\theta)$ 表示用参数 $\theta$ 在目标域上预测耗时的平均误差。
- 迁移模型$\theta_{\text{transfer}}$ 是经过源域初始化并在目标域微调后的参数。
- 从头模型$\theta_{\text{scratch}}$ 是只使用目标域数据、完全不借助源域经验训练出的参数。
- 有效性条件只有迁移模型的风险更小,迁移才真正带来收益;否则就是负迁移。
AI 应用场景
新 GPU 型号的算子性能优化
阶段:模型部署 / 编译器自动调优
解决的问题:传统方式下,每换一块新 GPU,算子调优都要全量搜索配置空间,动辄几千上万次测量,耗时以天计。迁移学习把旧 GPU 上训练好的代价模型参数搬过来,再在新 GPU 上采集少量样本微调,把调优时间压缩到几小时甚至几十分钟。
具体案例:一家公司的推理服务从 V100 迁移到 A100,编译器工程师保留了 V100 上的代价模型,只在新卡上测了 50 个配置,就用迁移后的模型指导搜索完成了关键算子的调优,性能与全量调优相差不到 3%。
移动端模型的快速迭代
阶段:端侧推理优化
解决的问题:移动端模型每个版本都可能有新算子、新网络结构,如果每次发布前都要重新全量调优,产品节奏会被拖垮。迁移学习让上一版模型的调优经验平滑迁移到新版本,大幅减少真机测量。
具体案例:某 App 的图像分割模型新增了一个轻量注意力模块,优化工程师从旧模型源域迁移代价模型到新模型,只做了 30 次真机测量,就找到了接近最优的配置,上线时间提前了一周。
Python 演示
class CostModel: def __init__(self, dim): self.theta = [0.0] * dim def predict(self, x): return sum(t * xi for t, xi in zip(self.theta, x)) def fit(self, X, y, epochs=300, lr=0.05, reg_theta=None, reg_lambda=0.0): if reg_theta is None: reg_theta = [0.0] * len(self.theta) for _ in range(epochs): for xi, yi in zip(X, y): err = self.predict(xi) - yi for j in range(len(self.theta)): grad = err * xi[j] if reg_lambda > 0.0: grad += reg_lambda * (self.theta[j] - reg_theta[j]) self.theta[j] -= lr * grad def feature(p): return [1.0, p, p * p] def source_time(p): return 0.8 + 0.2 * p + 0.01 * p * p def target_time(p): return 0.6 + 0.4 * p + 0.015 * p * p def main(): source_model = CostModel(3) src_p = [i / 10.0 for i in range(1, 11)] source_model.fit([feature(p) for p in src_p], [source_time(p) for p in src_p]) target_p = [0.15, 0.35, 0.55, 0.75, 0.95] target_X = [feature(p) for p in target_p] target_y = [target_time(p) + 0.01 * ((i % 3) - 1) for i, p in enumerate(target_p)] trans_model = CostModel(3) trans_model.theta = list(source_model.theta) trans_model.fit(target_X, target_y, reg_theta=source_model.theta, reg_lambda=0.3) scratch_model = CostModel(3) scratch_model.fit(target_X, target_y) print("p transfer_err scratch_err") for p in [0.3, 0.5, 0.7]: true_t = target_time(p) err_t = abs(trans_model.predict(feature(p)) - true_t) err_s = abs(scratch_model.predict(feature(p)) - true_t) print("%.2f %.4f %.4f" % (p, err_t, err_s)) if __name__ == "__main__": main()
class CostModel:定义一个简单的线性代价模型,用参数列表 theta 表示权重。self.theta = [0.0] * dim初始化模型参数,dim 个全零权重。def predict(self, x)用权重和特征向量做点积,返回预测耗时。def fit(self, X, y, epochs=300, lr=0.05, reg_theta=None, reg_lambda=0.0)用梯度下降训练模型,支持向源域参数做正则约束。grad = err * xi[j]计算普通平方误差对第 j 个参数的梯度。grad += reg_lambda * (self.theta[j] - reg_theta[j])加入迁移正则项,让参数不要离源域模型太远。source_model.fit(...)在源域大量配置上训练出源代价模型。trans_model.theta = list(source_model.theta)把源域参数作为迁移模型的初始点。trans_model.fit(target_X, target_y, reg_theta=source_model.theta, reg_lambda=0.3)用目标域少量样本微调,并用源参数做约束。scratch_model.fit(target_X, target_y)从零训练基准模型,用来对比迁移效果。
常见误区
误区既然迁移是把老厨房的手记搬过来,那到了新厨房应该什么都不用试,直接照着手记做菜就好了。
正解没有任何目标域数据时,你只是“直接使用源模型”,而不是“迁移学习”。迁移必须用少量目标样本做校准,否则无法发现新硬件与新模型的差异。就像老厨师至少也要试两道菜,才知道新灶台火力偏大还是偏小。
为何常见:“迁移”两个字容易让人理解成“整体搬走”,忽略了真正关键的“适配”环节。
误区两个硬件看起来差不多,模型结构也接近,那旧手记肯定能直接拿来用,效果一定更好。
正解相似是迁移的前提,但不是充分条件。如果源域模型已经很好,而目标域样本太少,迁移提升可能很小;如果某些微妙差异没被特征捕捉到,仍可能出现负迁移。工程上一定要用验证集对比迁移前和迁移后的目标域风险。
为何常见:人们容易把“相似”当成“等价”,却忽略了性能预测这类回归任务对微小分布偏差也很敏感。
误区新样本很宝贵,既然测了更多数据,就应该更用力地把模型往新数据上拉,所以 λ 要调大。
正解$\lambda$ 控制的是“对源域参数的保留程度”。样本越多,模型越能直接从目标数据中学到规律,反而应该适当减小 $\lambda$,让目标数据发挥更大作用。$\lambda$ 越大,模型越不敢偏离源域,可能无法拟合新硬件。
为何常见:把 λ 误当成“学习强度”,而没有理解它是源域与目标域之间的信任天平。
误区用了迁移学习,自动调优就一定能找到比全量调优更好的配置,甚至会收敛到全局最优。
正解迁移学习提高的是搜索效率,不是搜索保证。它让代价模型在早期更准,从而少做无效测量;但最终配置是否全局最优,仍取决于搜索算法、配置空间和测量噪声。它更像是给老厨师一个更好的起点,而不是保证每道菜都拿满分。
为何常见:把“收敛更快”等同于“结果一定更好”,忽略了调优本身仍然是一种有随机性的搜索过程。
面试题
Q1. 调优迁移学习解决的核心问题是什么?
- A.让模型在更多语言上运行
- B.降低新设备的调优成本← 正确答案
- C.提高神经网络的精度
- D.减少编译器的内存占用
答案:B。调优迁移学习复用源域经验,让新硬件或新模型只需少量测量即可完成调优,核心目标是降低调优成本。A、C、D 分别涉及语言支持、模型精度和内存,都不是迁移学习的主攻方向。
Q2. 在调优迁移学习中,“源域”通常指什么?
- A.待优化的新目标硬件
- B.已有调优经验的环境← 正确答案
- C.编译器的中间表示
- D.算子自动生成的代码
答案:B。源域是已经积累了大量调优数据的环境,比如旧 GPU 或上一版模型;目标域才是等待优化适配的新环境。C、D 是编译器内部概念,与域定义无关。
Q3. 代价模型在自动调优中的主要作用是什么?
- A.直接生成最快的算子
- B.预测配置性能并筛选候选← 正确答案
- C.替代 TVM 编译流程
- D.统计训练数据的分布
答案:B。代价模型给候选配置打分,预测耗时,从而只把少量高分配置送去真实测量。它不直接生成算子,也不替代编译流程,只是搜索过程中的性能预测器。
Q4. 参数迁移的常见做法是?
- A.丢弃源域模型并重新训练
- B.以源域参数为初始点微调← 正确答案
- C.对硬件参数求平均值
- D.用随机参数覆盖目标模型
答案:B。参数迁移通常把源域参数作为初始点,再用目标域样本微调。丢弃源模型等于从头开始;对硬件参数取平均或随机覆盖都不是可学习的迁移策略。
Q5. 在迁移目标函数中,λ 的作用是?
- A.控制测量样本数量
- B.控制迁移约束的强度← 正确答案
- C.控制学习率的大小
- D.控制特征向量的维度
答案:B。$\lambda$ 是正则项系数,控制模型对源域参数的保留程度。它不直接改变样本数、学习率或特征维度,只调节“旧经验”和“新数据”之间的信任比例。
Q6. 目标域样本数量通常有什么特点?
- A.比源域样本多很多
- B.与源域样本完全相同
- C.比源域样本少很多← 正确答案
- D.只需要一个标签即可
答案:C。迁移学习的典型设定是目标域样本远少于源域。如果目标域样本足够多,直接全量调优即可,迁移收益就不明显;一个样本通常不足以校准多维参数。
Q7. 以下哪一项是“负迁移”的表现?
- A.迁移后调优速度毫无变化
- B.迁移后性能反而比从头调差← 正确答案
- C.迁移后模型参数全部归零
- D.迁移后目标域无法测量
答案:B。负迁移指源域经验对目标域产生了干扰,使迁移模型在目标域上的表现比从头训练的模型更差。参数归零、无法测量属于工程故障,不属于迁移学习中的负迁移概念。
Q8. 哪些因素会造成源域和目标域的差异?
- A.硬件型号发生变化← 正确答案
- B.算子结构发生变化← 正确答案
- C.运行库版本发生变化← 正确答案
- D.编译日志格式变化
答案:ABC。硬件型号、算子结构、运行库版本都会改变配置与耗时之间的映射关系,因此构成域差异。编译日志格式变化只影响日志解析,不直接影响性能模型。
Q9. 调优迁移学习完整流程包括哪些步骤?
- A.源域全量调优获得经验← 正确答案
- B.迁移代价模型的参数← 正确答案
- C.用目标域样本微调校准← 正确答案
- D.重写 TVM 编译器源码
答案:ABC。完整流程是先在源域调优得到经验,再把代价模型参数初始化到目标域,最后用少量目标样本微调并指导搜索。重写编译器源码既不是迁移流程的一部分,也不是迁移学习的必要条件。
Q10. 在 $L(\theta)=\sum_{i}(\theta^{\top}\phi(x_i)-t_i)^2+\lambda\|\theta-\theta_s\|^2$ 中,当 $\lambda\to+\infty$ 时模型会怎样?
- A.完全忽略源域参数
- B.完全退化为源域模型← 正确答案
- C.完全拟合所有目标样本
- D.目标函数值趋向无穷大
答案:B。当 $\lambda$ 趋于无穷时,正则项占据绝对主导,只有 $\theta=\theta_s$ 时惩罚最小,因此模型完全退化为源域模型,无法适配目标域样本。这正好说明 λ 不是越大越好。