从RNN到Transformer,从CNN到图神经网络,从监督学习到深度强化学习,这十年深度学习的技术演进速度确实够快的。但大多数人学习时是一个模型一个模型地学,学完就忘,很难形成体系。这篇文章要做的,就是把这几年Python生态里我认为最核心的六块架构串起来——物理信息神经网络(PINN)的正反问题求解、Transformer在文本/视觉/时序三个域的迁移逻辑、时空图推理、深度强化学习的主要算法谱系、进化神经架构搜索,以及当下最热的自进化Agent。它们之间其实存在一条暗线:从“拟合数据”走向“拟合规律”,从“固定结构”走向“结构自适应”,从“单任务求解”走向“持续自进化”。
这篇文章适合谁?适合已经会用Python和PyTorch写基础模型、但想建立全局视野的工程师,也适合准备做技术选型、想搞清楚某个架构到底能解决什么问题的研究者。我会把每个架构的核心原理、关键代码思路、踩过的坑和适用边界都讲清楚,争取让你读完能判断“我的问题该用哪一套”。
1. PINN:把物理定律写进损失函数,反问题才是真正的门槛
1.1 正问题求解的套路:约束来自方程本身
物理信息神经网络(Physics-Informed Neural Network, PINN)这两年热度一直不减,核心思想一句话就能说清:让神经网络的输出满足偏微分方程(PDE)的约束,训练时除了数据损失,再加上方程残差损失和边界条件损失。模型不是在拟合数据点,而是在“学习”一个物理规律。
拿经典的一维热传导方程举例:
∂u/∂t = α · ∂²u/∂x²
传统解法是有限差分、有限元这类数值方法,网格剖分、稳定性分析、边界处理都得懂。PINN的做法是:定义一个神经网络 u_θ(x, t),用自动微分算出 ∂u/∂t 和 ∂²u/∂x²,然后构造损失函数:
L = L_data + λ_pde · L_pde + λ_bc · L_bc
其中 L_pde 就是把网络输出代回方程后算出的残差。训练完成后,网络就是一个可微的近似解,想查哪个点的温度场就直接前向推理,比数值方法灵活得多。
我之前在PyTorch里实现过一个简化版,核心就是两步:
import torch import torch.nn as nn class PINN(nn.Module): def __init__(self): super().__init__() self.net = nn.Sequential( nn.Linear(2, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, 1) ) def forward(self, x, t): return self.net(torch.cat([x, t], dim=1)) # 自动微分计算PDE残差 def pde_residual(model, x, t): x.requires_grad_(True) t.requires_grad_(True) u = model(x, t) u_t = torch.autograd.grad(u, t, grad_outputs=torch.ones_like(u), create_graph=True)[0] u_x = torch.autograd.grad(u, x, grad_outputs=torch.ones_like(u), create_graph=True)[0] u_xx = torch.autograd.grad(u_x, x, grad_outputs=torch.ones_like(u), create_graph=True)[0] return u_t - alpha * u_xx # alpha为热扩散系数这段代码虽然短,但把PINN的精髓都体现出来了。训练时三个损失一起回传,边界条件用初值和边值点约束,方程残差用配置点(collocation points)约束。关键点在于采样的分布:配置点不能全在初始时刻附近,得在整个时空域内均匀或自适应采样,否则模型后期会“忘掉”早期时段。
1.2 反问题才是PINN的真正价值
正问题求解器已经很多了,数值方法也成熟,PINN在这个领域顶多是“另一种选择”。但反问题不一样——已知部分观测数据 + 方程形式,要求未知参数或未知初始条件,传统方法要么难以处理,要么迭代过程极其繁琐,PINN天然适合这类任务。
最简单的做法是把未知参数直接作为可训练变量,和网络权重一起优化。比如热扩散系数未知,就设一个alpha_log = torch.nn.Parameter(torch.tensor(0.0)),每步训练沿着损失下降的方向更新它。多试几次你就知道:损失曲线下降得很顺利不代表参数估计准确,尤其是噪声数据下,结果对损失权重极其敏感。
我的经验是,反问题要分两个阶段训练:第一阶段冻结未知参数,只训练网络拟合观测数据,让输出场先“成形”;第二阶段再放开参数一起优化。这样能避免早期梯度互相干扰。另外,不同物理量的量纲差异要提前归一化,否则方程残差里各项数量级差几个量级,小量纲项会被直接淹没。
1.3 PINN的适用边界和部署陷阱
哪些问题适合用PINN?我的判断标准有三条:一是无法生成足够训练数据,但物理规律已知;二是需要快速求解同一方程族的多个实例,比如数字孪生里的参数扫描;三是反问题,也就是参数/场重建。
哪些问题不适合?强对流、激波这类解不光滑的问题,PINN训练非常痛苦,需要加注意力权重或自适应采样才勉强能用。高维PDE也够呛,配置点数量随维度指数增长,计算量直接爆炸。部署时还要注意:模型和传统求解器不是一个验证逻辑,你必须拿少量真实数值解或解析解做对照,否则网络可能已经“自洽地错”了。
2. Transformer三域迁移:从文本到图像再到时序,注意力机制到底在迁移什么
2.1 为什么Transformer能跨域?
Transformer最早在NLP领域提出,解决的是序列建模问题。它的核心组件是自注意力机制——每个token都能看到序列里所有其他token,并自适应地决定“该关注谁”。这种全局依赖建模能力,正是CNN的局部感受野和RNN的逐步传递机制所欠缺的。
后来视觉领域发现,把图片切成patch(例如16×16像素一块),每个patch当作一个token,再叠加位置编码,喂给Transformer编码器,图像分类效果居然能和CNN掰手腕,这就是ViT(Vision Transformer)。再后来,时间序列预测也开始用Transformer架构:把时间窗口内的每个采样点当作token,通过自注意力捕捉长程依赖。
为什么能这样迁移?关键在于Transformer本身对输入模态没有先验假设。CNN假设了“局部相邻像素有关联”,RNN假设了“序列是逐步展开的”,但Transformer只假设“有一组对象,对象之间有相关性”。文本词、图像patch、时间步、图节点,本质上都是一组对象。所以它是目前最接近“通用信息处理架构”的模型之一。
2.2 三域迁移时哪些东西必须改
虽然架构通用,但直接把NLP那套代码搬到其他域,大概率翻车。我按实践顺序说说几个关键改造点。
位置编码部分是第一个要改的。文本的位置编码可以是一维的绝对位置编码,也可以用RoPE这类相对位置编码。图像patch是二维排布,ViT用的是一维可学习位置编码——直接把patch的二维坐标展平成一维索引,实践证明够用但不是最优。后来有工作提出二维位置编码,效果略有提升。时序数据更特殊,时间步之间的距离有实际物理意义(比如间隔10分钟),简单的绝对位置编码捕捉不到这种变化,需要用带时间间隔信息的编码方式,或者对时间戳做归一化后拼进token向量。
Token化方式是第二个改造点。文本天然按词或子词切分;图像按固定patch切分;时间序列则看场景——单变量序列可以每个时间点一个token;多变量序列有两种选择,要么把同一时刻的多个变量拼成一个token,要么把每个变量单独当序列做通道维度的注意力。我实测下来,变量多、相关性明显时,第一方案更合理;变量少、依赖复杂时,第二方案表现更好。
归一化层的摆放也有讲究。原始的Post-LN结构(即残差之后做LayerNorm)在深层Transformer里容易出现训练不稳定,Pre-LN(即先归一化再进子层)更稳,收敛更快。视觉Transformer大多采用Pre-LN,文本到视觉迁移时如果不改这层,几十层叠下来梯度很容易出问题。
2.3 三域Transformer的实战对比
| 迁移域 | Token化方式 | 位置编码策略 | 典型架构 |
|---|---|---|---|
| NLP | BPE/WordPiece | 绝对位置编码/RoPE | BERT、GPT |
| 视觉 | Patch Embedding | 1D可学习位置编码 | ViT、Swin Transformer |
| 时序 | 时间点/时间窗口 | 时间戳归一化+间隔编码 | Informer、PatchTST |
Swin Transformer在视觉域的思路值得单独说一句。它不是全局做自注意力,而是在小窗口内做,然后通过shifted window机制让信息跨窗口流动。这一设计让计算量从O(N²)降到O(N),同时引入类似CNN的局部先验,所以在小样本视觉任务里往往比ViT效果好。
2.4 Transformer不是万能的:我在时序预测上踩过的坑
有一段时间我迷信Transformer能搞定所有时序问题,结果在多步预测任务上被一个简单的LSTM按在地上摩擦。复盘后发现原因很清晰:时间序列存在很强的自回归特性,逐点Transformer的局部归纳偏置太弱,对趋势项和季节项的捕捉效率不如专门设计的模型。
后来换成了PatchTST的思路——先把时间窗口切成若干patch,每个patch内部做线性映射,再对patch序列做注意力。这么做一方面缩短了序列长度,注意力计算量降下来了;另一方面patch内部做了局部平滑,对噪声更鲁棒,效果立竿见影。所以我的结论是:Transformer迁移到新领域时,先别急着硬套,分析清楚数据的最小编码单元是什么,“Token化”设计得对不对,远比调注意力头数重要。
3. 时空图推理:当数据带着连接关系,卷积和注意力都不够用了
3.1 从结构化数据到图结构数据
前面提到的PINN处理的是规则网格上的物理场,Transformer处理的是有序的token序列,但现实中有大量数据天然不具备规则结构——社交网络、交通路网、分子结构、知识图谱,节点之间有边,边有权重,节点本身也有特征。这时候卷积核没法用了,因为局部邻居数量不固定;标准的Transformer也没法直接用,因为它假设的是一组独立的token,没有显式建模节点间的关系。
时空图推理(Spatio-Temporal Graph Reasoning)要解决的核心问题是:节点特征随时间变化,同时节点之间通过边互相影响,如何同时建模这两种依赖。典型应用包括:交通流量预测、电网负荷预测、气象站点温度估计。
3.2 图卷积、图注意力、时空图网络的基本链路
图卷积之所以能工作,核心思路是消息传递(Message Passing):每个节点聚合邻居的特征,再经过一次非线性变换更新自己的表示。GCN就是最简单的实现,一步聚合一层邻居,堆多层就能感知多跳邻居。它本质上是拉普拉斯平滑的一种形式,所以深层GCN容易过平滑——所有节点特征趋向一致。这个问题我实际使用时非常明显,用两层GCN效果最好,四层之后精度陡降。
图注意力网络(GAT)则是在聚合时引入注意力权重:每个节点对不同的邻居学一个权重系数,权重可以理解为“邻居对我有多重要”。相比GCN,GAT的表达能力更强,尤其在异质图(不同类型节点和边)上优势明显。
但GCN和GAT只处理了空间维度,时间维度怎么办?主流方案有两种:
- 时间卷积 + 图卷积交替堆叠:每层先做时间维度的因果卷积,再做图卷积聚合空间信息。STGCN是这条路线上的代表作。
- 门控循环单元与图卷积结合:把GRU的线性变换替换成图卷积,让每个时间步都进行一次空间聚合。DCRNN用的就是这条路线。
我自己的项目里更多用第一种。门控循环单元类模型训练速度慢,对大图也吃显存,而时间卷积可以并行计算,部署时方便得多。
3.3 建图这件事,比模型选择更决定上限
做时空图推理的人经常把大部分精力花在调模型结构上,但我必须说一句:图的构造方式才是决定效果上限的核心。你拿什么定义节点之间的边?不同定义方式会带来完全不同的注意力分布和信息传播路径。
交通流量预测里,最常见的做法是根据路网物理距离建图——两个路段的空间距离小于某个阈值就连接。但实际数据里,两条相距很远的道路可能因为绕行而产生强相关,物理距离图就捕捉不到。另一种做法是用历史数据的相关系数建图,先算出所有节点流量序列的皮尔逊相关系数,超过阈值的连边。我实测过,这类数据驱动图往往比物理图带来更明显的精度提升,缺点是泛化性差,一旦路网结构或出行模式变化就需要重新建图。
还有第三种做法:把图结构当成可学习参数。用一个矩阵表示边的权重,在训练中不断更新,让模型自己发现最优连接关系。这种做法灵活,但容易过拟合,需要加稀疏性正则。我目前的经验是:物理图作为先验、数据驱动图作为补充、可学习图作为微调,三者结合最为稳妥。
3.4 时空图模型的显存与推理优化
时空图推理模型训练时最痛的还是显存问题。大图的邻接矩阵动辄百万级,即使稀疏存储,做消息传递时中间变量也极其吃显存。我的处理方式是:
- 训练时采用图采样(Graph Sampling):每次迭代只对部分节点子图做消息传递,而不是整张图全套计算。
- 能合并的算子尽量合并,图卷积的本质是稀疏矩阵乘法,用PyTorch的
torch.sparse.mm而不是稠密矩阵乘法,显存和速度都有明显改善。 - 推理时改成逐步行走模式:只计算目标节点的N跳邻居,而不是整图前向。
4. 深度强化学习的谱系:从DQN到PPO,从SAC到多智能体
4.1 强化学习解决的是什么问题
前面几类模型都是在做“给定输入,预测输出”的监督学习,深度强化学习(Deep Reinforcement Learning)解决的是另一种问题:智能体如何在一个环境里通过试错最大化长期收益。你没有一个标注好的“正确答案”数据集,只有一个奖励函数告诉你“刚才这一步好不好”。
这个范式特别适合那些不能靠静态数据学习、必须与环境实时交互才能获得反馈的场景。训练无人机悬停控制、机器人抓取、游戏AI、自动驾驶决策等任务,都需要这类框架。
4.2 算法谱系梳理:基于价值、基于策略、基于演员-评论家
强化学习算法家族庞杂,我梳理出一条清晰的谱系线:
基于价值的方法(Value-Based):以DQN为代表。核心思路是学习一个Q函数,Q(s, a)表示在状态s下执行动作a的预期累积回报,然后选Q值最大的动作执行。DQN的三大改进——经验回放、目标网络、双Q网络——每一招都在解决训练不稳定的问题。这类方法适合离散动作空间,比如Atari游戏。
基于策略的方法(Policy-Based):策略梯度类算法直接学习策略函数 π(a|s),通过梯度上升让高回报动作的概率变大。这类方法天然支持连续动作,但方差很大,训练效率低。REINFORCE、A2C/A3C属于这个分支。
演员-评论家方法(Actor-Critic):把两类方法结合——Actor负责学策略,Critic负责评估当前状态或动作的价值,用Critic的输出来降低Actor更新的方差。A2C、DDPG、TD3、PPO、SAC都属于这个大家族。
| 算法 | 动作空间 | 核心思路 | 主要适用 |
|---|---|---|---|
| DQN | 离散 | 学习Q函数 + 经验回放 | 游戏控制 |
| DDPG | 连续 | 确定性策略 + Q函数 | 机器人控制 |
| TD3 | 连续 | DDPG + 双Q + 目标策略平滑 | 高噪声环境 |
| PPO | 离散/连续 | 截断的重要性采样 | 通用首选 |
| SAC | 连续 | 最大熵强化学习 | 样本效率敏感任务 |
4.3 PPO为何成为工程首选
现在做项目,如果没有特殊理由,我默认上PPO。原因有三:一是训练稳定。PPO通过截断的重要性采样比率把策略更新的步长限制在可控范围内,不像传统策略梯度那样一步走太远直接把策略推崩。二是实现简单。开源实现多到数不清,稳定基线的代码写得很规整,改环境就行。三是调参相对不敏感。SAC这类最大熵方法理论上效果好,但温度参数、目标熵的设定非常影响结果,PPO只需要关注裁剪阈值和学习率。
PPO里最容易出问题的是优势估计。很多新手直接用TD误差当优势,训练波动很大。正确做法是用GAE(泛化优势估计)——通过 λ 参数在偏差与方差之间做平衡,λ 取0.95是比较常规的起点。
4.4 模拟环境与真实部署之间的鸿沟
深度强化学习在真实环境中训练成本极高,绝大多数项目都在模拟器里训练,再想办法迁移到真机。这个“Sim-to-Real”过程是工程落地最大的坑。
无人机控制项目里常见的问题是:模拟器里的动力学参数和真实风场条件差异过大,模型在仿真里飞得很好,真机上一跑就翻车。解决办法通常是域随机化(Domain Randomization):训练时不固定动力学参数,而是在一个范围内随机采样,让策略学会适应各种参数下的动力学特性。这样部署到真机时,真实参数落在训练域内的概率大大增加。
另外一个经验,强化学习项目的日志记录比监督学习重要得多。训练曲线不下降、突然崩溃、评估波动巨大,这些现象都要能及时看到,否则跑了一天的实验等于白费。
5. 进化神经架构搜索与自进化Agent:让模型自己设计自己的两条路径
5.1 NEAT:从拓扑进化到权重进化
神经架构搜索(Neural Architecture Search, NAS)的想法很直接:不靠人工设计网络结构,让算法自己去搜索最优结构。传统NAS依赖超参优化和强化学习,计算成本高。进化神经架构搜索(Evolutionary Neural Architecture Search)则用遗传算法的思路——把网络结构编码成基因组,通过选择、交叉、变异不断迭代。
NEAT(NeuroEvolution of Augmenting Topologies)是最有代表性的算法之一。它把神经网络编码成基因序列,初始群体都是最简单的网络,随着进化代际增加,拓扑结构逐步复杂化。它的创新点在于:用历史标记(Historical Marking)解决了交叉时基因不对齐的问题;用物种形成(Speciation)保护还处于早期、效果不佳但潜力很大的网络拓扑。
用Python做NEAT也很方便,有现成的neat-python库可以直接跑。我之前在一个简易游戏中做过实验,给智能体一个距离传感器输入,让它进化出能避开障碍物的网络——不写任何训练逻辑,光靠进化就能找到不错的控制策略。但NEAT的问题在于进化速度慢,复杂任务里一个网络几百万参数,遗传算子的搜索效率远不如梯度方法。所以它在强化学习领域适合低维控制任务,不太适合大规模视觉输入。
5.2 自进化Agent:环境、技能与评估的飞轮
“自进化Agent”(Self-Evolving Agent)是最近特别火的概念。传统的强化学习是在固定环境里更新策略,而自进化Agent更进一步——不仅策略在进化,环境生成、技能库、评估标准也在进化。
最简单的理解方式是这样的循环:Agent先在自己生成的任务变体中训练技能;把学到的技能存入技能库;评估模块判断哪些技能有效;基于当前技能短板生成更有针对性的新任务;再训练新技能。如此循环,Agent的能力边界在不断扩大。
实现自进化Agent的Python框架其实不复杂,核心要四个模块:
class SelfEvolvingAgent: def __init__(self): self.skill_library = {} self.environment_generator = TaskGenerator() self.policy = PolicyNetwork() self.evaluator = SkillEvaluator() def evolve(self, generations): for gen in range(generations): tasks = self.environment_generator.generate( candidates=self.skill_library, weaknesses=self.evaluator.weakness_report() ) for task in tasks: self.policy.train(task) skill = self.policy.extract_skill() self.skill_library.register(skill) self.evaluator.evaluate(self.skill_library, self.policy)这套流程写起来不难,难在如何评估“技能是否有效”。如果评估标准太简单,Agent会钻空子;太复杂,计算成本又收不住。我的经验是先定义好“不能退化的底线指标”,再追求“新技能是否能提升跨任务泛化表现”。没有底线指标,自进化很容易变成自我欺骗——每代都在新生成的任务上表现良好,但对原有任务却越来越差。
5.3 自进化Agent、大模型与强化学习的交汇
现在很多自进化Agent的实践都搭在大语言模型之上。大模型作为“策略网络”提供行动能力,强化学习提供“试错信号”,环境生成器自动创造新任务,形成一套持续自我改进的循环。这个方向我这半年看得最多、也最兴奋——它把深度学习从“针对特定任务学一个模型”带到了“针对一类任务持续自我改进”的阶段。
但也要泼一盆冷水:自进化Agent目前还处于非常早期的阶段,大多数成功的案例都在相对封闭的环境中,比如代码生成、机器翻译、数学推理这类有明确反馈信号的任务。在开放世界里做自进化Agent,评估和奖励设计依然是个没有标准答案的难题。
6. 六条技术路线如何组合:Python工具链与真实的工程落地
6.1 几种有效的“组合拳”思路
单独理解每个架构是第一步,更关键的是知道怎么组合使用。我在实际项目里见过几种效果不错的搭配。
PINN + 深度强化学习:PINN可以作为强化学习环境的快速替代。真实物理系统仿真太慢,可以用训练好的PINN作为环境模型,让强化学习智能体在里面做策略探索。因为PINN是神经网络,反向传播可以直接打通环境与策略之间的梯度,这在传统数值求解器里做不到。
Transformer + 时空图推理:图注意力的局限是只能关注一跳邻居,多层堆叠又容易过平滑。可以用Transformer的全局注意力替代消息传递,构建Graph Transformer——先用图结构信息增强节点特征,再用Transformer对所有节点做全局建模。在交通流量预测项目里,这个组合通常比纯GCN或纯Transformer效果更好。
进化架构搜索 + 强化学习:用进化算法搜索网络结构(比如神经元连接方式、层数、激活函数组合),用强化学习训练被搜索出来的网络。两者形成内外循环,进化负责结构搜索,强化学习负责参数训练。这个方法计算成本高,但对无梯度或稀疏奖励的场景特别有效。
6.2 Python生态与工程化注意事项
这几条技术路线在Python里的工具链已经相当成熟:
- PINN:DeepXDE封装了大量PDE案例,上手比从头写方便太多,但复杂方程还是得自己实现网络结构。
- Transformer:PyTorch的
nn.Transformer模块和HuggingFace生态已经足够强大,不建议自己从零造轮子。 - 图神经网络:PyTorch Geometric(PyG)是首选,从数据加载到采样都封装得不错,注意版本兼容性问题。
- 强化学习:Stable-Baselines3最省心,封装了PPO、SAC等多种算法,改环境就能起跑。
- 进化算法:
neat-python适合NEAT,deap适合通用遗传算法。
工程上我总结了几条容易踩的坑:
版本兼容性是最大的坑。PyTorch、PyG、CUDA版本三者只要有一个不匹配,调用图卷积就会报奇怪的底层错误。建议固定一套已知兼容的版本组合,别频繁升级。
GPU利用率不等于训练效率。图神经网络和强化学习都有大量小算子调用,GPU利用率可能看起来很高,但实际吞吐量很低。用PyTorch Profiler看一下核函数的耗时分布,往往能发现大量时间花在内存拷贝上。
实验管理要趁早规范。这六个方向都有一个共同特征:实验状态多、超参数多、结果波动大。我用的是MLflow记录每次实验的配置参数和指标曲线,配合统一的随机种子管理。别等到跑了一百个实验再来补,到那时候谁也说不清哪个实验对应哪组配置。
6.3 选型决策框架:面对一个新问题,该用哪条路线
最后给一个我自己常用的选型决策框架,希望能帮你做技术判断:
- 物理规律是否基本明确?已知方程、但数据难生成,选PINN;物理规律不明、数据充足,别碰PINN,老老实实用监督学习。
- 数据是否有规则结构?文本、图像、序列用Transformer家族;有显式节点和边、且边关系对结果影响大,选时空图推理。
- 是否存在交互式环境、能否获得奖励信号?能交互且可低成本获得反馈,深度强化学习;无法交互,只有静态数据集,别碰强化学习。
- 网络结构是否难以手工设计?当前任务换个结构效果天差地别,但你又没有先验,试试进化神经架构搜索。
- 任务是否会不断演化,新任务形态无法提前枚举?考虑自进化Agent的框架,设计好任务生成器和评估机制。
这五步过完,你的技术路线基本就有谱了。
7. 写在最后的一些实在话
这几条技术线我陆陆续续做下来,最大的感受是:深度学习这几年的发展不是在造一座座孤岛,而是在编织一张网。PINN把物理规律注入网络,Transformer让一个架构在不同模态之间迁移,时空图推理把关系归纳进模型,深度强化学习让模型在交互中成长,进化架构搜索让模型自己决定结构,自进化Agent让模型在任务演化中存活。每个方向都在打破“固定数据集、固定任务、固定结构”这三个旧假设。
如果你现在刚开始接触这些内容,我给的建议是:不要六个方向一把抓,先选一个与你当前工作最贴近的方向,至少完整复现一个项目。比如做工程仿真的,从PINN起步;做NLP的,从Transformer的源码精读开始;做控制的,从PPO跑通一个简单环境开始。跑通之后再往其他方向拓展,你会发现那些看似独立的架构,底层的基本功都是相通的——自动微分、梯度传播、损失函数设计、训练稳定性调优,永远是核心。
最后分享一个我做技术评估时的小技巧:任何新架构出来,先不看它的SOTA数字,只看它改变了训练范式的哪个环节——是改变了数据来源,还是改变了模型结构,还是改变了优化目标,还是改变了评估方式。抓住这一点,你就能快速判断它适合用在什么场景,也就能真正看懂这个领域的演进方向了。