你好,我是 Tyler。
在上节课中我们学习了特征工程相关的知识,你对这部分内容掌握得如何呢?
今天我们开始学习模型工程。你是否还记得,我在开篇词中说过,AI 系统是一个极其复杂的系统,我们需要自顶向下地学习,而不要一开始就陷入技术细节,要先明确各个算法的定位和作用。
在这节课里,我也会为你介绍现在人工智能在学术上的三大学派,它们分别是符号主义学派、连接主义学派和行为主义学派,其中的代表分别是知识图谱、深度学习和强化学习。
目前,以深度学习模型为代表的连接主义派表现出色。然而,在许多情况下,AI 系统仍然需要结合其他两个学派的算法,才能发挥最大的功效。所以我们要学习各个学派的算法,博采众长,才能形成对 AI 系统模型工程的全面认识。
监督学习(Supervised Learning)
先来看监督学习,它意味着在正确答案的指导下进行学习,这和你在考试前通过习题和答案来对照学习是一样的。
为了让机器和你一样,也能学习问答之间的关系,我们需要使用函数 Y = F(X) 来表示它们之间的映射关系。
X 是问题的描述,比如“世界上最高的山是哪座山?”
Y 是问题的答案,即“珠穆朗玛峰”。
所以只要你得到 Y = F(X) 的具体表达式,就能够算出所有问题的答案。
接下来,问题就变成了——你该如何获得函数 F 的表达式。其实这个过程和你在学校时求解多元方程没有太大区别,就是根据已知条件,得到未知数的解析解。
只不过在真实世界中,你无法获取全部的已知条件,甚至不知道方程的具体形式,几乎无法获得解析解。因此,你只能使用统计的方式,来拟合 X 和 Y 之间的关系,得到函数 F 的近似解 F’。
拟合的过程分为两步。首先建立模型,选择一个适合的 F’ 的表达式(比如 F(X) = AX + B)来对你的场景建模。然后,我们需要将已知数据作为条件,来求解参数 F’ 中的未知参数(也就是 A 和 B)。
点击率模型(CTR)
为了让你更好地理解这个过程,我们沿用之前点击率预测的例子。预测用户“是否点击”是一个经典的监督学习问题。其中的 X 包括用户年龄和商品价格等各类特征,标签 Y 则表示 “是否点击”,一般用 0 来代表未点击,1 代表点击。
现在,你已经清楚数据的情况了,如果需要你设计一个模型来预测点击率,你会怎么做呢?你可以先自己暂停思考一下。
接下来我们就揭晓答案。其实很简单,刚才已经教给你了。第一件事是建立数学模型,也就是设计方程,第二件事是求解方程未知数。
但是由于你之前没有做过类似的任务,所以可能不知道该选什么样的方程。其实很简单,你甚至可以直接用刚才例子中的 Y = AX + B。X 就是你的特征,A 和 B 是你的未知参数,Y 则是是否点击的标签。
当然了,真实的工业场景中,会选择更复杂一些的函数表达式,因为这类表达式的拟合能力更强,可以更好地刻画复杂数据的分布,这里我为你选择了 Google 的 Wide&Deep 模型,这是点击率预测的经典模型。你可以看到,在论文中,它的数学表达式是后面这样。
第一眼看到这个表达式,你可能会有点懵。这里和你分享一个经验,那就是拿到一个模型之后,不要死磕公式,而是先理解它的设计思路。
论文中提到,该模型由宽度和深度两部分组成。宽度部分用于处理与“是否点击”有直接联系的特征,原理与传统的逻辑回归相同。深度部分则可以更好地利用那些看似与标签无关,但组合起来会很有用的特征,是一个多层的神经网络(MLP)。本质上,它是将宽度和深度两个模型融合成了一个模型,来发挥各自的优势。
理解了这个背景之后,就算你不懂前面的公式,也可以搭建好这个模型了。你只需要按照下面的图示来“搭乐高”就好了,这个乐高的“示意图说明书”和对应搭好的代码如下所示。
Wide & Deep 模型示意图
接下来,你只需要按照前面的图示来“搭乐高”,也就是按照前面的模型图构建你的模型,不需要理前面复杂的函数表达式。
建模示意代码如下。
import torch.nn as nn
class WideAndDeepModel(nn.Module):
def __init__(self, wide_features, deep_features):
super(WideAndDeepModel, self).__init__()
self.wide = nn.Linear(len(wide_features), 128)
self.deep = nn.Sequential(
nn.Linear(len(deep_features), 128),
nn.ReLU(),
nn.Linear(128, 128),
nn.ReLU()
)
self.output_layer = nn.Linear(128 + 128, 1)
现在你已经用搭乐高的方式,建立好了上面那个复杂的方程。下一步只需要求解方程的参数就好了。
具体求解前,你需要先理解“损失函数”是什么。简言之,损失函数 L 是模型给出的“预测”和标准“答案”之间的差距,损失越小则说明模型效果越好。所以“解方程”的过程就是要“试”出损失最小的“解”。
所以你需要用你的数据(X,Y)和你的近似解 W 带入损失函数,去试 W 是不是最优的解。
比如你可以用简单直接的损失函数(比如均方误差),求出各个样本预测误差平方的平均值即可。
L(y^,y)=n1∑(yi−y^i)2
当然,在真实工业场景中我们会使用更复杂的损失函数,比如交叉熵,它可以对预测值和真实值之间的分布做相似性的预估。
L(y^,y)=yilog(y^i)+(1−yi)log(1−y^i)
看到这里,你会说,我悟了!只要将所有可能的“解” W 都带入损失函数试一遍,然后记录下让损失函数最小的“解”不就好了?
非常好,能提出这个方法说明你已经理解了。这个方法没有错,但是“都试一遍”这件事不太可能做到,因为参数的个数是海量的,而且参数是连续的,而不是离散的,所以没法“都试一遍”。
所以你还是需要一个策略来提高“试”的效率,比如使用梯度下降法,它是一种投石问路、步步逼近的策略。
用梯度下降来求解的整个过程是这样的。
首先,我们从需要拟合的已知数据中取一小批数据(X,Y),并将它们带入损失函数。然后,随机给损失函数赋予一个解 W。接下来,计算梯度,梯度会指向这批数据上将损失函数减小的最小解的方向。之后,沿着这个方向迈出一步,也就是调整你的模型参数 W。最后,我们再取一批数据,基于更新后的解重复这个过程,直到用完所有已知数据。
最终,你将得到一个针对你的已知数据拟合后的点击率模型。这个模型可以用来预测未知数据的点击率。
你是不是觉得模型训练没什么神秘的了?你所要做的工作只是定义方程和解方程而已。你可以对照下面的示意图和代码再好好理解一下。
梯度下降示意图
model.train()
num_epochs = 10
for epoch in range(num_epochs):
for batch_data, batch_labels in train_loader:
optimizer.zero_grad()
outputs = model(batch_data)
loss = criterion(outputs, batch_labels.unsqueeze(1))
loss.backward()
optimizer.step()
对比学习(Contrastive Learning)
接下来,我们进入对比学习的部分。区别于监督学习,对比学习只需要得到样本之间的“相似度”就能完成训练,之前我们学习的 Word2Vec 就是对比学习的一个典型例子。
这里再举个推荐系统的例子,推荐系统的本质是寻找用户和物品之间的关系。所以如果你能得到用户和物品之间的“相关性”,就可以直接用它们之间的“距离”,实现第 5 节课中提到的数据召回。
具体的过程是这样,你可以用图结构来表示用户和物品的关系,构建它们之间的关系图,用户和物品是图的节点,它们之间的交互行为是图的边,边的权重则是它们交互行为的频率。
那么,如何得到它们之间的距离呢?其实你可以用 Word2Vec 来实现,因为它能找到词与词之间的距离,自然也能用来找“人”与“物”之间的关系,只不过你需要一个办法把节点之间的图结构转化成 Word2Vec 中的序列结构。
这其实也是 DeepWalk 算法的核心思想,我们来看看具体的建模过程。
首先随机选择一个初始节点,根据与它相连边的权重分配概率,进行节点之间的随机跳转,也就是所谓的随机游走。随机游走的过程中会生成许多路径,这个路径则是你想要的序列。得到序列后,自然可以使用 Word2Vec 建模,唯一不同的是对象由单词变成了用户和商品。
通过这样的处理,你就能得到用户和物品的空间投影(Embedding)并计算它们的空间距离。
你可能注意到了,刚才我们通过将复杂问题分解为多个简单问题,快速得到了解决方案。这种方法在各类算法中经常会用到,比如计算机视觉中的目标检测就用了类似的方法。
但一般而言,这往往只是一种权宜之计,最终还是会发展成端到端的模型,因为分阶段的方法通常会导致信息的丢失。所以,下节课我还会带你学习一种端到端的图神经网络算法——GraphSAGE。
这里你先重点理解对比学习的思想,因为这是大语言模型技术的核心方法。
强化学习(Reinforcement learning)
我们都知道,人工智能有三个主要派别,它们分别是行为主义派、连接主义派和符号主义派。
接下来,我来带你学习一下行为主义派,也就是控制论学派的学习框架。如下图所示,该学派采用了一种基于“感知 + 行动”的行为方法。
早期常见的思路是运用控制论中的经典算法,比如 PID 控制器,该控制器由比例、积分和微分这三个部分构成。
比例部分反映了偏差与目标之间的比例关系,能在偏差产生时立即提供反馈,实现有效的控制。
积分部分表示偏差随时间的累积情况,主要用于消除静态误差,例如在误差积累较长时间时,逐渐增加修正幅度。
微分部分则捕捉偏差信号的变化趋势,特别用于快速扩大偏差时,可以及时抑制其进一步放大的趋势。
如下图所示,只要对上述三个模块的输出加权求和,即可得到系统的综合偏差。这个综合偏差可以用来控制系统的校正力度。
这个算法很擅长解决控制动作存在延迟响应场景的问题。最初是用在通过调节空调风量来控制室温,通过控制方向盘来保持车道这样的场景。
后来该算法广泛应用在 AI 系统中的控流场景,这里我们以短视频应用为例。
短视频的 AI 系统,通常会限制每个视频在 24 小时内的流量,以避免某些视频过度占据流量,挤压中小创作者的发展空间。因此,当某个视频的曝光量达到一定值后,就会被限制流量。
不过,短视频 AI 系统还有一个目标——让各种使用习惯的人都能接触到优质内容。所以,平台还需要确保内容在一天中各时刻的流量均匀分布。这样就能避免在某个时段,比如下午使用产品的用户看不到优质内容。在这种场景下,就很适合使用 PID 控制器来控制流量。
具体来说,当收到流量请求的时候,我们要先算出实际曝光量和预期曝光量的差距值,把这个差距值和之前几个时刻的差距一起传给 PID 控制器,并将计算出输出值作为对当前视频的调控反馈。
如果输出值越高,那该视频在这次请求中,被限制的概率就越大。通过这个机制可以动态地调整当前视频的曝光量,因为这完美地利用了 PID 控制器的特点——“风浪越大,控流越强烈”。
翻译一下就是真实流量和预期流量间的误差越大,误差增长越快,误差积累时间越长,AI 系统就会越强力地限制流量。这样即使面对突然出现的流量洪峰,也能做到动态控制。
当然,PID 算法也存在一些局限性,比如调整加权参数通常需要高昂的实验成本,尤其是在在线商业系统中。因此,目前各大厂正在逐渐切换到强化学习的方案上来。
强化学习不依赖于预先标记的数据,而是通过与环境的交互来进行自主学习,根据奖励信号的反馈进行实时的策略更新,同样是行为主义派的经典方法。
这里你只需要先对强化学习的控制反馈能力和它所属的学派,建立一个直观的了解。后面课程里我再和你详细探讨这项技术,敬请期待!
小结
好了,学到这里,我帮你总结一下今天学到的内容。
你不仅掌握了 AI 内容推荐系统中各类算法的核心原理,还理解了监督学习、对比学习和强化学习这些 AI 大模型中最关键的核心技术。你可以通过课后思考题看出它们之间的联系。下面我们再回顾一下这几个概念。
1. 监督学习是在正确答案的指导下进行学习。这和你在考试前通过习题和答案来对照学习是一样的。
2. 对比学习的目标是通过样本之间的相似度,来学习它们之间的距离,进而表示它们的关系。
3. 强化学习的核心思想,是利用感知和行动的闭环进行学习。
这节课我们学习了人工智能的三个主要派别分别是什么,目前你已经掌握了两个派别的方法,下节课我会教你符号主义学派的工具。还有一些重要的观点,我将它留作课后思考,相信经过这节课的学习,你一定能想出答案。我们下节课见!
思考题
为了更好地巩固今天所学的内容,请你尝试回答后面的问题。
请你设计一个对话系统,让它在行为学派的学习框架下,自动优化自己的对话能力,给出大致流程即可。
恭喜你完成我们第 7 次打卡学习,期待你在留言区和我交流互动。也欢迎你把这节课分享给身边朋友,和 TA 一起学习进步。