Skip to content

人工智能基础 A#

Abstract

想认认真真学人工智能千万不能选这门课. 想要水学分的也千万别选这门课. 哦, 是必修啊, 那没事儿了.

这篇文档除了书本上的相关知识, 还有大量的补充和实践代码, 感兴趣的同学可以仔细阅读. 比较详细的代码我索引到了专门的人工智能章节. 对于期末考试, 个人认为主要看看历年卷记忆相关公式即可. 如果你想考比较高的分数, 你需要掌握这里面大部分框架的原理, 实现等等.

1. 人工智能起源#


Quote

人工智能的诞生早于现代程序设计语言. 当时召开达特茅斯会议时大家发现, 传统的数值计算类语言(比如 FORTRAN 语言)难以满足表示和操纵符号结构的需求, 据此诞生了诸如 LISP 等符号处理类语言. 这实际上也成为后来函数式编程和元编程的设计范式.

1.1 人工智能的诞生#

1956 年, 达特茅斯会议的召开标志着人工智能元年的到来.

Tip

图灵测试: 如果人无法在对话中区别与自己对话的是人还是机器, 那么这台机器就可以称为"智能".

1.2 人工智能的三大学派#

  • 符号主义

人的本质是台机器, 强调逻辑与规则推理, 信息使用显示符号结构表示(比如 LISP 语言), 常作为逻辑推理系统.

  • 行为主义

心理过程无法被观察, 不关注逻辑的"黑箱"过程, 通过强化机制(强化学习)学习.

  • 联结主义

认知过程本质上是神经元之间的联结模式, 模拟人的神经网络结构构造人工神经网络.

1.3 幸存者偏差#

AI 的局限绝大多数起源于幸存者偏差现象. 我们在训练的过程中无意识或者有意识地忽略了很多信息, 导致特例成为了普遍现象.

Note

最典型的例子莫过于二战时期的飞机弹痕. 我们常常只关注成功的例子, 因为失败的例子我们难以直接观察到.

2. 机器学习#


2.1 机器学习的定义#

已知一个数据集 \(S\), 对任意输入的 \(x\in S\) 都存在对应的标签 \(y\), 通过计算机系统寻找一个数学模型 \(f\), 使得对于任意 \(x\), 计算得到的\(y'=f(x)\) 都尽可能的逼近于对应的 \(y\).

  • 一对 \((x,y)\) 称为一个样本, 总个数叫做样本大小.
  • \(y\) 的取值范围称为样本空间.
  • 集合 \(S\) 是样本空间中的一个随机抽样.
  • 机器学习是人工智能的子集.

Note

非机器学习类人工智能, 是传统的人工智能, 本质上都是有着严格规则一种算法. 例如各类游戏 AI (Alpha-Beta 剪枝, 寻路算法).

机器学习与非机器学习 AI 的区别

特征 机器学习 非机器学习
先验数据 必须 非必须
数学模型 推理模型+训练算法 推理模型
模型参数 机器自动习得 人工设计
准确率 理论上达不到 100% 很容易达到 100%
推理 计算机 计算机

Note

这里强调的"推理模型+训练算法"实际上是强调了机器学习类可以自行更新和加强参数, 通过推理模型根据输入的 \(x\) 输出 \(y'\), 而训练算法则根据 \(y\)\(y'\) 的关系不断更新推理模型的参数. 非机器学习类在人工写好模型后就不会再发生改变.

  • 练习: 列出的几种算法中哪一种属于机器学习?

(1), 剪枝算法; (2), 深度优先算法; (3), 蒙特卡洛树搜索; (4), 启发式搜索; (5), 蚁群算法; (6), 宽度优先算法; (7), 最大-最小算法; (8), 线性回归

参考答案

(8). 线性回归的推理模型是 \(y=bx+a\), 使用最小二乘法等最小化误差的方式作为训练算法. 对于其他几项, 和机器学习类 AI 比较接近的都是启发式算法. 要么就是传统的图算法.

首先对于剪枝算法, 深度优先搜索算法, 宽度优先搜索算法, 最大最小搜索, 这几个都是图或者树的算法, 我们不需要进行训练, 一旦写死了代码其运行方式就不会改变.

其次对于蚁群算法, 蒙特卡洛树算法和最大最小搜索算法, 虽然有了随机化模拟, 但是不会更新模型的内部参数, 因此也不属于机器学习的范畴.

  • 机器学习的五个要素: 数据, 模型, 训练, 预测, 评估
  • 机器学习的三个核心要素: 数据, 模型, 算法. 机器学习过程: 训练, 预测, 评估
  • 深度学习的三个要素: 数据, 算法, 算力

实际上就是我们获得机器学习类模型的几个动作.

首先应当获取可靠的数据集, 接下来确定我们使用的模型, 而后使用数据集训练模型调整参数, 将训练后的模型用于新数据的预测, 最后根据预测的准确性和其他性能评估模型.

2.2 过拟合#

Question

训练集的结果是不是越准确越好?

Question

为什么我们必须要分出训练集和测试集?

答: 不是越准确越好. 我们以最简单的线性回归模型举例, 假设存在一组数据与对应的映射

\[ X:\{1,2,3,4,5,6,7,8,9\}\longrightarrow Y:\{2,4,6,8,7,12,14,16,18\} \]

我们很容易观察到, \(Y\)\(X\) 的映射关系应当是 \(Y=2X\), 但是当我们训练过度之后, 在 \(X=5\) 的时候模型很可能输出一个接近于 \(7\) 的数值. 我们称这种在训练集上表现很好, 预测时表现很差的现象称之为过拟合.

解决过拟合问题的最佳方式就是对收集到的数据进行预处理, 类似于我们处理实验数据的方式, 将明显和总体趋势相悖的数据除掉, 确保训练数据的质量. 同时监督学习应当分离测试集和训练集.

Quote

没有免费午餐定理(NFL): 没有任何机器学习模型在所有问题上都是最优的. 换言之, 一个模型在某些任务上很厉害, 在另外的一些任务上一定会表现很差. 我们只能尽可能选择合适的数据集和模型进行处理.

例如, 如果按照上面我们解决过拟合问题的思路, 除掉 \(X=5\) 对应的一组数据, 或许可以提高模型整体的泛化能力, 但是在这组带有 \((x=5, y=7)\) 的测试集数据上的效果就没有过拟合的好.

2.3 机器学习的分类#

学习类别 是否存在标签 是否存在反馈 学习方式 实例
监督学习 是(直接给出正确答案) 拟合输入输出关系 回归与分类
无监督学习 机器自行寻找数据集潜在关系 聚类, 异常检测, 降维
半监督学习 是(少部分) 混合模式 -
强化学习 是(不知道答案, 但是存在奖励机制) 不断试错, 不断强化思想钢印, 某种答案最优 决策类

(ps: 半监督学习了解即可)

2.4 线性回归与最小二乘法#

线性回归模型是最简单的监督学习模型. 其核心是使误差最小化. 其具体计算原理是将误差的平方和 \(\sum_{i=1}^{n}e_i^2=\sum_{i=1}^{n}(y_i-(ax_i+b))^2\) 最小化. 如何最小化呢? 答案就是求偏导确定零点, 解这个方程

\[ \left\{\begin{matrix} \frac{\partial f}{\partial a} = 0 \\ \frac{\partial f}{\partial b} = 0 \end{matrix}\right. \]

化简即可得到

\[ a=\frac{n\sum_{i=1}^{n}x_iy_i-\sum_{i=1}^{n}x_i\sum_{i=1}^{n}y_i}{n\sum_{i=1}^{n}x_i^2-(\sum_{i=1}^{n}x_i)^2} \]

3. 无监督学习: 回归与分类模型#


3.1 常用损失函数#

3.1.1 回归损失函数#

均方误差(mean squared error). 实际上就是方差.

\[ MSE=\frac{1}{N}\sum_{i=1}^N(Y_i-Y'_i)^2 \]

平均绝对误差(mean absolute error).

\[ MAE=\frac{1}{N}\sum_{i=1}^{N}\left|Y_i-Y'_i\right| \]

平均绝对百分比误差(mean absolute percentage error).

\[ MAPE=\frac{1}{N}\sum_{i=1}^{N}\left|\frac{Y_i-Y'_i}{Y_i}\right|\times 100 \]

均方对数误差(mean squared log error).

\[ MSLE=\frac{1}{N}\sum_{i=1}^{N}(\log \frac{Y'_i+1}{Y_i+1})^2 \]

3.1.2 分类损失函数#

Note

个人认为没必要记. 太难记住了.

3.1.3 一般终止条件#

  • 损失函数值足够小
  • 损失函数值的变化足够小
  • 训练次数足够多
  • 梯度(就是模型参数变化)趋于 0
  • 预测集准确率下降

3.2 聚类#

属于无监督学习, 根据数据点之间特征的相似度或距离(欧氏距离)将相似的数据点聚集在一起形成簇.

Note

欧氏距离, 线性代数中的概念. 在学习线性代数时我们知道, 欧式空间是线性空间中的一种, n 维空间中的欧氏距离公式是

\[ d(X,Y)=\sqrt{\sum_{i=1}^{n}(x_i-y_i)^2} \]

下面我们以典型的 K-means Algorithm (K均值算法) 为例说明聚类的过程.

首先明确最终目的, 将数据集 \(S\) 按照特征分类为 \(n\) 组. 我们设 \(\forall x\in S\) 都对应了 \(n\) 个特征, \(S\) 的大小(不同 \(x\) 的个数)为 \(N\). 我们将每个 \(x\)\(n\) 个特征映射到一个 \(n\) 维空间中, 于是我们得到了一个存在 \(N\) 个点的空间.

现在我们假设要将之分为 \(m\) 组, 那么我们首先随机初始化 \(m\) 个聚类质心, 然后不断循环下面两步:

  • 计算每个数据到质心的距离, 按照如欧拉距离归类到距离最近的质心, 对应相同质心的点集我们称为簇.
  • 调整质心位置, 具体做法是将当前簇内每个点距离之和的(某种)平均值最近的一处作为质心的位置.

直到:

  • 达到迭代次数.
  • 前后两次迭代中, 聚类的质心位置基本不变, 趋于稳定.

参考演示网站: http://alekseynp.com/viz/k-means.html

Note

KNN (最近邻法), 是一种监督学习, 其功能一般是在使用 k-means 聚类之后获取新的输入, 找出与它距离最近的几个样本, 根据最近邻样本的类别的多数判别新输入的类型.

3.3 降维: 主成分分析(PCA)#

目标: 在降维得到的新坐标系中实现数据波动(例如方差)的最大化.

视觉上就是建立一个新的坐标系, 将多个维度的数据投影到这个新的坐标系, 实现数据的降维. 新的坐标系轴方向就是主成分.

在代数上, 就是将多个数据分组组合成一个新的特征, 提取最大波动的几个特征作为主特征.

4. 深度学习(Deep Learning)导论#


Abstract

一个简单的神经元只能完成一个简单的反射. 甚至, 它只能表示 0 和 1. 但是, 当足够多的神经元联结在一起时, 奇妙的事便会发生.

本章节中的"深度"是在强调神经网络组织的"深度", 或者说层的数量. 这就是"多层人工神经网络".

4.1 多层人工神经网络与深度学习#

Note

深度学习既不指监督学习或无监督学习, 也不指强化学习. 其本身是前面几种学习类型, 也就是机器学习的实现方式.

深度学习(Deep Learning, 简称 DL)是机器学习的一个子集, 它使用多层人工神经网络(特别强调隐藏层的深度)来精准完成图像检测等任务. 通过多层表示+高阶特征提取完成如图像识别, 语音识别等各种任务, 具有较强的特征鲁棒性(抗干扰能力).

深度学习的几个特征:

  • 多层网络结构

分为输入层, 隐藏层, 输出层. 各层之间通过权重进行连接, 构成复杂的网络结构. 一般而言, 输入层用于"侦测和传递数据", 输出层用于将抽象信息具体化便于我们理解, 隐藏层负责提取特征进行分析.

  • 自动特征提取

自动从原始数据中提取特征, 无需人为提取特征.

Note

传统的机器学习需要进行人工特征提取. 比如一张图, 首先要人为提取出图片的整体纹理, 颜色直方图, 边缘提取等等, 既耗时又耗力, 而且难以泛化.

深度学习通过多个隐藏层从低级特征到特征组合进行学习, 全流程自动化, 不需要人工干预.

  • 非线性激活函数

深度学习模型通常使用非线性激活函数(比如 ReLU, sigmoid 等等)结合多层设计可以轻松处理复杂的非线性关系.

Note

如果使用线性激活函数, 那么对于每个映射 \(y=f(x)\), 都可以写作 \(y=k_ix+b_i\). 假设是一个三层神经网络, 则激活函数等价于 \(y=k_3(k_2(k_1x+b_1)+b_2)+b_3\), 打开合并后变成 \(y=Kx+B\). 也就是说, 如果使用线性激活函数, 再多的层最后都等价于一个层.

  • 大规模数据处理能力

综合前面几个优点, 尤其是自动特征提取, 使用多层人工神经网络的深度学习可以实现这一点.

4.2 感知机#

4.2.1 感知机模型#

这是经典的人工神经网络模型. 简单来讲, 感知机模拟了一个神经元的行为. 例如, \(f\) 是一个非线性函数(就是激活函数), 而 \(X\) 是一个向量矩阵. 这一模型提供一个线性函数, 将 \(X\) 映射为 \(\Sigma\), 其规则表述为 \(\Sigma=WX^T+B\). 之后 \(Y\) 作为非线性函数检测 \(\Sigma\) 是否可以激活.

\[ Y=f(\Sigma),\ \]

在考试中, 会要求我们根据图写出 \(Y\) 或者 \(f\) (激活函数)的公式. 对于上述的映射, 我们可以形式化地表述公式为

\[ Y=f(WX^T+B) \]

当然, 不适用矩阵也可以表达

\[ Y=f(\sum_{i=1}^{n}(w_ix_i+b)) \]

Note

没有激活函数的感知机本质上是一个线性二分类机器, 无法处理 XOR 类型的问题. 因为 XOR 的结果无法用一条直线分隔开, 所以无解.

4.2.2 多层感知机(MLP)#

多层感知机(Multi-Layer Perceptron, 简称 MLP)的目的是解决非线性问题. 一个多层感知机至少包括三层: 输入层, 隐藏层, 输出层. 这是一个典型的前馈神经网络.

我们称只含有一个隐藏层的神经网络叫做浅层学习网络, 而将大于一个隐藏层的成为深度学习网络.

4.2.3 常见激活函数#

  • ReLU 函数(线性整流函数), 目前(在隐藏层中)最常用
\[ f(x)=\max(0,x) \]
  • Sigmoid 函数, 其只能表述正数(ReLU 可以表述 0), 所以现在已经不常用.
\[ f(x)=\frac{1}{1+e^{-x}} \]
  • Softmax 函数, 最常用于分类问题和图像识别等, 其作用是将任意\(n\) 维实数向量归一化为同阶向量(Softmax 归一化后不但分量全部在 \([0,1]\), 而且分量的和也为 \(1\)).
\[ f(x_i)=\frac{e^{x_i}}{\sum_{i=1}^{n}e^{x_i}} \]

Note

对于向量 \(X\) 常用的几种归一化方法(所谓的归一化, 就是让向量的各个分量的取值在 \([0,1]\) 之间)

最小-最大归一化

\[ x'=\frac{x-x_{min}}{x_{max}-x_{min}} \]

L2 归一化

\[ x'=\frac{x}{X^2} \]

Question

对于输入 \(X=[2,0.7,-1.5,-0.9]\), 计算其 Softmax 输出.

Success

解:

\[ \begin{aligned} &sum=\sum_{i=1}^{n=4}e^{x_i}=e^2+e^{0.7}+e^{-1.5}+e^{-0.9}=10.03\\ &S_1=\frac{e^{x_1}}{sum}=0.74\\ &S_2=\frac{e^{x_2}}{sum}=0.20\\ &S_3=\frac{e^{x_3}}{sum}=0.02\\ &S_4=\frac{e^{x_4}}{sum}=0.04\\ \end{aligned} \]

换言之, 其 Softmax 输出为 \([0.74,0.20,0.02,0.04]\).

4.3 反向传播算法: BP#

反向传播是人工神经网络用于计算误差的一种手段. 简单来说, 当输出值不在损失允许范围内或根本不符合预期时, 将输出误差以某种形式通过隐藏层向输入层逐层反向传递, 反传递过程中将误差分摊到各个神经网络层, 获取各层单元的误差信号, 算法通过这些误差信号调整连接权值, 从而减小误差, 达到设计预期.

Note

反向传播算法常用于前馈神经网络(FNN)中. 这种神经网络最大的特点就是只会不断向下一层传递, 不像循环神经网络(RNN)那样可能会回到前面的隐藏层循环传递.

BP 算法的优势 - 自适应与自主学习, 可以自动化地更新隐藏层规则 - 较强的非线性映射能力 - 严谨的推导过程(链式法则) - 较强的泛化能力(通过已有知识解决新问题)

BP 算法的劣势 - 容易陷入局部极小值(极小值不一定是最小值) - 收敛速度缓慢(大量参数导数计算和权重与偏置值的更新) - 隐藏层缺少理论指导, 需要不断设计隐藏层和隐藏节点数试凑达到最佳效果 - 学习新样本可能遗忘旧样本(每次更新都是按照新数据进行的, 这种情况很容易发生) - 计算复杂度高

4.4 梯度下降: GD#

在我们通过反向传播算法得到梯度之后, 按照公式 \(w_i\longrightarrow w_i-\eta \times \frac{\partial L}{\partial w_i}\) 不断更新本层的权重和偏置. 其中 \(\eta\) 是学习率(步长).

Note

可能上面的描述会让你感到困惑. 我们其实应当知道, 函数式编程的过程本质就是函数处理常用几种方法的调用. 也就是说, 我们只需要有基本的微积分知识就可以用数学描述上述过程

首先, 反向传播算法本质上是对误差函数在各层偏导数的计算. 或者说, 假设某一层的激活函数为 \(Y_i=f(W_iY_{i-1}^T+B_i)\), 那么反向传播就是损失函数对 \(W_i\)\(B_i\) 求偏导的过程. 通过这一过程, 我们得到了梯度, 也就是偏导数.

为了逐步追踪每个参数对于最终损失的间接影响, 我们需要使用链式法则将误差逐层从后向前传递. 比如, 对于一个两层神经网络

\[ \begin{aligned} &a_1=f_1(W_1x+b_1)\\ &a_2=f_2(W_2a_1+b_2)\\ &Loss=\varsigma (a_2,y) \end{aligned} \]

其中的 \(W_1\) 并不会直接影响 \(Loss\) 函数. 为了计算到其间接影响, 利用多元函数微分法

\[ \frac{\partial \varsigma}{\partial W_1}=\frac{\partial \varsigma}{\partial a_2}\cdot\frac{\partial a_2}{\partial f_2}\cdot\frac{\partial f_2}{\partial a_1}\cdot\frac{\partial a_1}{\partial f_1}\cdot\frac{\partial f_1}{\partial W_1} \]

之后的梯度下降实际上是利用反向传播计算得到的结果对所有层同时进行权重 \(W\) 和偏置 \(B\) 进行调整的过程.

Question

设函数 \(Loss=x^2\), 起点为 \((8, 64)\), 学习率为 \(0.1\), 使用表格描述其梯度下降的过程.

Success

(好像 admonition 里面打不了表格...)首先求导得到梯度: \(y=2x\), 而后逐步计算: \(y_1=2\times 8=16\), 因此更新 \(x_1=x-\eta\cdot y_1=8-0.1\times 16=6.4\). 类似地, 我们进一步计算 \(x_2=6.4-0.1\times (6.4\times 2)= 5,12\), ... 使用图表示为一个梯度下降的过程.

4.5 梯度下降算法的改进: 优化器#

4.5.1 随机梯度下降法(SGD)#

传统的梯度下降每次调整都要用训练集中的所有样本, 而随机梯度下降法每次只从训练集中随机选取一个样本, 利用小规模样本训练调整神经网络.

其优势有:

  • 高效
  • 可并行计算
  • 可适应新数据变化(预训练思想萌芽)
  • 有机会全局最优

其劣势有:

  • 不稳定
  • 没有解决学习率选择问题(需要人工决定学习率)
  • 随机最优解
  • 模型不可控

改进:

  • 适当增加样例(小批量)
  • 动量梯度下降法

相关代码

1
2
3
4
5
# optimizer: 优化器, .parameters() 用于读取训练参数, lr 表示 learning rate
optimizer = optim.SGD(model.parameters(), lr=0.01)

# momentum: 动量, 保留上一次梯度 90% 的值, 类似于惯性
optimizer = optim.SGD(model.parameters(), momentum=0.9)

4.5.2 自适应梯度算法(AdaGrad)#

自适应梯度算法(AutoGrad)通过自动调整学习率实现在不同梯度尺度中稳健的表现. 其学习率的分母部分会增加历史梯度的累积值, 这意味着其学习率会随着训练次数的增加逐渐趋于 0.

其优势有:

  • 自动化调整学习率
  • 权重的"步调一致", 实现对典型特征(高频特征, 高学习率)的提取, 适当减少对稀疏特征(低频特征, 低学习率)的提取, 避免过拟合

其劣势有:

  • 梯度消失(学习率趋于零)
  • 训练速度缓慢(原因与上面一样, 学习率会逐渐减小)

Note

稀疏数据是指维度很高但是绝大多数方向上的值是 0 的数据.

因为 AdaGrad 的设计原理问题, 实际上的原始算法只适用于稀疏数据. 像图像等含有大量低维数据, 需要长时间进行神经网络训练的不适合 AdaGrad.

改进: - RMSProp(自适应平方根梯度法): 调整分母的值 - Adam(自适应矩估计法, 目前最常见): 本质上是 RMSProp + Momentum

Note

Adam 结合了两种优化思路, 其核心是为每个参数维护两个动量, 一个是一阶动量估计(梯度指数的加权平均), 另一个是二阶动量估计(梯度平方的指数加权平均). 如果想要详细了解, 可以看看这篇论文https://arxiv.org/pdf/1412.6980.

相关代码

# weight_decay: 正则化项(L2 惩罚), 防止过拟合; eps 用于替代分母等于 0 的项
optimizer = optim.Adagrad(model.parameters(),
                          lr=0.01,
                          weight_decay=1e-4,
                          eps=1e-10)

# betas: 动量因子, beta1控制一阶滑动平均, beta2控制二阶平方平均
optimizer = optim.Adam(model.parameters(),
                       lr=0.01,
                       betas=(0.9, 0.999),
                       eps=1e-8,
                       weight_decay=0)

5. 幕间: 关系总结#


人工智能分为两大类, 一类是机器学习, 另一类是非机器学习. 前者除了模型本身, 还有训练算法, 可以不断增强自己的参数. 后者基本属于传统算法范畴, 在本门课程基本不做讨论.

对于机器学习, 我们可以从模型设计和训练算法两方面来分类.

对于训练算法, 我们分为监督学习, 无监督学习和强化学习, 回归是典型的监督学习, 聚类和降维则是典型的无监督学习.

对于模型设计, 我们主要讨论的是深度学习. 深度学习利用深层神经网络, 实现层级的特征抽象提取和表示学习. 现在最有名的基于 Transformer 架构的各类大模型, 就是典型的深度学习模型.

如果你是一位资深的 AI 用户, 你会发现几乎所有的 AI 都可以做到和你对话. 这一点归功于预训练模型. 预训练模型在深度学习模型的基础上, 使用大数据得到基本通用知识, 再迁移到各种具体任务中使用专业数据集进一步训练.

而当预训练模型被调教好后, 我们就得到了生成式大模型. 生成式大模型就是根据上下文自动生成相对高质量内容的大规模人工神经网络. 这其中我们最为熟悉, 最常用的便是生成式大语言模型.

6. 深度学习实例#


6.1 CNN 卷积神经网络#

卷积神经网络(CNN)是一类具有局部感受野, 权值共享机制和多层结构的前馈神经网络, 主要用于处理具有网格的数据(例如图像, 语音, 视频等), 尤其擅长从原始输入中自动提取空间和时序特征.

Note

感受野, 指神经网络某个神经元在输入图像时可以"看到"的区域大小. 例如我们人类只能准确看到在我们实现中央的区域, 我们可以粗略的将我们的感受野归结为中间区域.

卷积神经网络相较于普通的人工神经网络而言, 多了卷积层和池化层结构. 我们在卷积神经网络中一般简称传统人工神经网络组成部分(包括输入层, 隐藏层, 输出层)为全连接层.

6.1.1 卷积运算#

设计一系列大小合适的卷积核(感受野), 对数字图像的各个通道分量进行卷积. 或者说, 一个卷积核按照步长对于图像全部像素进行加权求和, 卷积核中存储有权重值. 常用的卷积核大小有 \(3\times3,5\times5,7\times7\).

Note

人工智能领域的卷积运算一般是按照卷积核确定的权重进行加权求和. 其加权计算过程如图所示

用于卷积运算的神经网络层成为卷积层.

卷积运算中有三个重要参数, 分别是卷积核的形状, 卷积的步长, 卷积核的个数(每一层卷积层可能不同).

6.1.2 池化#

池化也称为下采样. 其作用是进一步缩小特征图的尺寸, 减小计算量. 池化的原理是可以利用某一图像区域子块的统计信息包含该子块的全局信息. CNN 通常使用 \(2\times 2\) 区域进行池化.

一般池化分为四种, 分别是最大池化, 随机池化, 平均池化, L2 范数池化. 前面三种顾名思义, 第四种以 CNN 为例, 设 \(S(0,0)=19, S(0,1)=15, S(1,0)=26, S(1,1)=23\), 那么其 L2范数就是 \(\sqrt{19^2+15^2+26^2+23^2}\).

6.1.3 本质#

  • 独热码

CNN 通过独热码(One-Hot Code)来表示物质的性质. 在分类中, 我们不能简单的使用 1, 2, 3, 4 ... 这种有序数字来表达. 否则假设猪编码为 1, 羊编码为 2, 鸡编码为 3, 那么就会出现"鸡-羊=1"这种毫无意义的数值关系.

独热码将猪, 羊, 鸡按照下面这种方式进行编码:

类别
0 0 1 0 0 0
0 1 0 0 0 0
0 0 0 0 1 0

在最终输出的时候将独热码的值进行 Softmax 计算, 得到是某一种物种的概率.

  • 层次特征学习

深度神经网络(指隐藏层大于 1)可以通过层次性处理的方式逐步提取出抽象特征, 并且随着层次的深入, 低级特征逐渐向高级特征进化.

6.1.4 计算#

一般而言, 会要求你已知输入的情况下给出输出. 使用一维的情况进行记忆:

假设输入的长度为(数目) \(I\times1\), 卷积核大小(kernel_size)为 \(K\times1\), 填充大小(padding)为 \(P\) (在被卷积的输入两边都添加 \(P\)\(0\) 控制卷积的), 步长为 \(S\). 那么, 我们按照以下操作进行计算:

首先在原有的输入两边加上 \(P\)\(0\), 输入的长度变为 \(I+2\times P\), 而后我们使用卷积核(\(K\times 1\))按照步长(\(S\))在输入上移动. 我们知道, 假设 \(S=1\) 的时候我们最终可以得到 \(I+2\times P - K + 1\) 个完整的卷积输出, 而在 \(S=2\) 的时候可以得到 \(\frac{I+2\times P-K}{S}+1\) 个完整输出. 利用数学归纳法可以确定最终公式为

\[ Output=floor(\frac{Input+Padding\times 2-KernelSize}{Stride})+1 \]

最终输出还应该加上卷积核, 也就是通道的数目. 例如, 这一层卷积核有 10 个, 那么通道就有 10 个.

Question

对 kernels = \(96\), kernel_size = \(11\times11\), padding = \([1,2]\), stride = \(4\), input = \([224,224,3]\) 的图像进行卷积计算, 计算出输出形状.1

Success

\([55,55,96]\), 按公式计算即可. 注意这里一般将张量描述为形状, 其要素为\([高度(H),宽度(W),通道数(C)]\).

6.2 幕间: 三种神经网络#

神经网络分为三类, 有前馈神经网络, 反馈神经网络, 以及图网络.

  • 前馈神经网络

前面我们学的两个, 分别是 MLP 多层感知机, CNN 卷积神经网络.

  • 反馈神经网络

常见的如 RNN 循环神经网络, LSTM 长短程记忆网络, Hopfield 网络, 玻尔兹曼机

  • 图网络

知识图谱, 社交网络, 城市交通等特征为关系的结构.

6.3 RNN 循环神经网络#

循环神经网络(RNN), 其特点是可以处理顺序性信息, 或者说具有时序性的信息. 具体而言, RNN 在每个时间步除了像一般的神经网络那样处理输入输出, 还会更新其内部的隐藏状态提供给下一个时间步. 这意味着每个时间步的输出不但依赖本次输入, 还依赖于上一次结束时的记录的状态, 并且会继续记录下去.

Question

已知拓扑结构为同步多对多的 RNN, 输入层, 隐含层和输出层的神经元都只有一个, 激活函数均为 ReLU. 已知 \(W=[0.5,0.1,0.2]\), \(H=[1]\), \(V=[3]\), \(S_0=0\), \(\alpha = 0\), \(\beta=0\), 对输入序列 \(X=[[1,1,1],[2,2,2],[3,3,3]]\), 计算其对应的输出序列. 其中 \(Y_t=h(V\cdot S_t+\alpha)\), \(S_t=f(W\cdot X_t+H\cdot S_{t-1}+\beta)\).

Success

虽然看起来很麻烦, 但其实计算相当简单

\[ \begin{aligned} &S_1=f([0.5,0.1,0.2]\cdot [1,1,1]+1\cdot 0+0)=f(0.8),\ 0.8>0,\ S_1=0.8\\ &Y_1=h(3\cdot 0.8+0)=h(2.4),\ 2.4>0,\ Y_1=2.4\\ &S_2=f([0.5,0.1,0.2]\cdot [2,2,2]+1\cdot 0.8)=f(2.4)=2.4\\ &Y_2=h(3\cdot 2.4+0)=h(7.2)=7.2\\ &...(the\ same\ way) \end{aligned} \]

6.4 LSTM 长短程记忆网络#

传统的 RNN 无法很好的处理长期记忆的问题, 而 LSTM 引入了记忆状态, 利用门控循环单元(GRU)控制信息的读写, 可以很好的决定是否长时间保存记忆.

当然, LSTM 并不是完美无缺的, 它因为引入了额外的部件, 其计算变得极其复杂, 需要花费大量时间, 无法进行实时响应, 并且只能顺序处理信息.

7. 自然语言处理(NLP)#


7.1 历史#

NLP 是人工智能领域的掌上明珠, 同时也是许多人投身于人工智能的最终目标. 其历史不可谓不坎坷, 历经了如下的演变

  • 基于规则算法(语法解析器, 类似于程序语言的编译器)
  • 统计语言模型(例如 CBOW(Continuous Bag-of-Words), Skip-Gram等等, 根据语义相似度推断)
  • 序列生成模型(例如 RNN, Transformer. 前者缺少长距离记忆能力, 计算无法并行; 而后者不但支持长距离全局记忆能力, 而且可以并行计算)
  • 预训练-微调模型(一般首先进行无监督(或者自监督)预训练, 而后确定任务对预训练大模型进行微调(一般是监督学习))

Note

CBOW 和 Skip-Gram 是两个截然处理顺序相反的模型. 前者是在已知 \(a_{i-2}, a_{i-1}, a_{i+1}, a_{i+2}\) 的前提下预测 \(a_i\), 后者是在已知 \(a_i\) 的前提下预测其他几个.

7.2 分词#

将一句连续的自然语言转换为一系列的 token (令牌) . Token 可以是一个字节, 一个字, 也可以是一个词. 将一句话分割为 Token 这种最小单元, 保证自然语言处理模型可以处理.

例如, 我们将"黄山落叶松叶落山黄"进行按字分词: 黄-山-叶-落-松-叶-落-山-黄, 词汇表(不同 token)有 5 个 token, 句子共有 9 个 token. 按词分: 黄山-落叶松-叶-落-山-黄, 词汇表有 6 个 token, 句子有 6 个 token.

Note

词向量词嵌入都是一个东西, 区别在于词向量强调的是数字编码技术, 词嵌入强调的是 NLP 网络之间的数据存在形式. 注意, 我们对词向量基本只关注其相对方向, 因此其分量没有真正的限制范围

现代句子在分词后的表示一般采用一维的稠密矩阵而非二维稀疏矩阵(独热码), 因为以为稠密矩阵的存储效率高很多.

7.3 文本相似度计算#

成功地完成了词向量的表示之后, 我们就可以很轻松地计算文本相似度. 一般计算方式有以下几种

  • 余弦相似度
\[ Cosine\ Similarity= \cos\theta=\frac{A\cdot B}{\left|A\right|\left|B\right|} \]
  • 曼哈顿距离
\[ d=\sqrt{\sum_{i=1}^{n}\left|X_i-Y_i\right|} \]
  • 欧氏距离
\[ d=\sqrt{\sum_{i=1}^{n}(X_i-Y_i)^2} \]
  • Jaccard 相似度

第一定义

\[ E(A,B)=\frac{A\cdot B}{A^2+B^2-A\cdot B} \]

Note

第一定义其实是很有意思的. 其分母与狭义定义比较, 其实是并集的计算公式: 二者之和减去相同的部分, 也就是 \(\left|A\cup B\right|=\left|A\right|+\left|B\right|-\left|A\cap B\right|\)

狭义定义

\[ E=\frac{\left|A\cap B\right|}{\left|A\cup B\right|} \]

Question

根据图中提供的信息计算华为和苹果的余弦相似度与广义 Jaccard 相似度.

Success

我们首先提取华为和苹果的词向量. 华为: \(A=[0.02, 0.93, 0.95, 0.01]\), 苹果: \(B=[0.96,0.77,0.85,0.15]\). 因此根据余弦相似度的计算公式, 我们得到

\[ COS(A,B)=\frac{A\cdot B}{\left|A\right|\left|B\right|}=0.7727 \]

对于广义 Jaccard 相似度

\[ J(A,B)=\frac{A\cdot B}{A^2+B^2-A\cdot B}=0.6219 \]

Question

考虑以下两个文本的 Jaccard 相似度. 文本 1: "我爱天安门", 文本 2: "天安门雄伟壮阔让人不得不爱".(不考虑词频)

Success

文本 1 集合为 \(A=\) {我,爱,天,安,门}, 文本 2 集合为 \(B=\) {天,安,门,雄,伟,壮,阔,让,人,不,得,爱}. 因此我们找到交集: {爱, 天, 安, 门}, 找到并集数目: 根据公式 \(A\cup B=A+B-A\cap B\) 知并集的数目为(注意写集合时排除重复元素"不")13. 最终计算结果为 \(\frac{4}{13}\).

Note

词袋模型, 是一种自然语言处理和信息检索中的常用文本表示方法. 它将文本表示为一个词的集合, 忽略顺序和语法结构, 只关注词语的出现频率或其他统计量.

7.4 现代自然语言处理框架: Transformer#

Tip

此部分内容我应该会在暑假继续更新. 多留点空以便更新. 因为这部分前沿内容比较复杂, 很难学懂和实践, 所以考的基本上都是名词理解.

7.4.1 简述#

推荐某乎上的这篇文章: Transformer模型详解(图解最完整版) - 初识CV的文章 - 知乎, 这里因为时间原因不会讲的很细.

Transformer 架构由编码器和解码器两部分组成. 其工作流程大致如下:

  • 输入一个句子, 获取句子中的每个单词的表示向量 \(X\), \(X\) 由单词的词嵌入(Words Embedding)和单词位置的 Embedding 相加得到.
  • 将得到的单词表示为向量矩阵, 将矩阵传入到编码器中, 经过处理后得到所有单词的编码信息矩阵 \(C\)
  • 将矩阵 \(C\) 传入到解码器中, 解码器会通过前面 \(i\) 个词翻译第 \(i+1\) 个词, 同时会掩蔽 \(i+1\) 后面的所有词.

Note

在 Transformer 架构下的编码器 BERT 不会掩蔽掉后面的值, 但是 解码器 GPT 会掩蔽掉.

7.4.2 自注意力机制#

一句话可以概括为: 看某个词的时候也在看其他所有词. 该地方输出的是结合了所有信息, 只不过赋予不同权重的向量.

7.4.3 三种模型#

模型 采用编码器 采用解码器
BERT TRUE FALSE
GPT FALSE TRUE
T5 TRUE TRUE

8. AIGC 与 LLM#


8.1 绪论#

AIGC(AI Generated Content), 这些年发展速度之快已经远超大家的想象. 甚至有的人已经怀疑现在基于 LLM 的 AI 在某种程度上已经可以称为真正的"智能"了.

  • 区别: 传统搜索引擎与 AIGC

AIGC 会生成全新的内容, 而传统搜索引擎做不到.

  • AIGC 的局限性

原创性几乎为 0, 可解释性奇差无比(概率模型, 没有明确的因果链), 语义理解长度有限, 长文本内容和大幅度时间跨度难以解析.

8.2 名词解释#

  • LLM: 大语言模型(Large Language Model), 其特征表现为训练数据大, 参数规模大, 耗资巨大.
  • 涌现能力: 当一种系统在复杂度增加到某一临界点时, 会出现其子系统或小规模版本中未曾存在的行为或特性.
  • GAI: 生成式人工智能(Generated AI), 指生成全新内容的 AI. 需要注意的是, GAI 采用自回归生成技术, 有随机性(同一提示文本不同回答); 同时 GAI 不是搜索引擎(虽然很多人这么用就是了).
  • AGI: 通用人工智能(Artificial General Intelligence), 指能够完成人类能够完成的任何智力任务. 其最大的特点是训练"领域无关", "任务无关".
  • GPT: 基于 Transformer 的预训练生成式模型(Generative Pre-Trained Transformer)
  • Chat GPT: 采用 GPT 架构的聊天机器人产品.
  • CLIP: 即视觉语言预训练模型(Constructive Language-Image Pre-training), 由 Open AI 提出的一个跨模态模型, 可以将图像和文本嵌入到同一个向量空间(隐空间)中进行比较和对齐. 其训练方式是用大量的"图对文"数据将图映射成文的向量.
  • 扩散模型: 即先加噪声模糊化, 然后让机器学习如何修复图像可以尽可能地使图像接近原本的样子. 分为前向过程("打马赛克", 扩散过程)和反向过程("去马赛克"). U-net 是其中最常用的一个模型.
  • 多模态大语言模型(MLLM): 可以给以任意形式的输入, 可以给出任意形式的输出. 这就是最完美的多模态大语言模型.

8.3 大语言模型的特征#

  • 参数规模巨大
  • 涌现能力: 随着模型规模提升模型性能显著上升
  • 数据驱动
  • 端到端学习: 不需要人工特征工程或者规则设计, 让 AI 自行完成学习
  • 上下文感知
  • 通用性

9. python 基础与机器学习常用 python 库#


  • scikit-learn: 深度学习库, 主要分为四种算法: 分类, 回归, 聚类, 降维
from sklearn.datasets import load_iris

iris = load_iris()
print("鸢尾花数据返回值: \n", iris.keys())

X = iris.data
y = iris.target

# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# PCA(主成分降维)
pca = PCA()
X_pca = pca.fit_transform
  • python 关键字"真"
True
  • Tensorflow
# 导入必要的库
import tensorflow as tf
from tensorflow.keras import layers, models

# 初始化一个顺序模型(前馈神经网络)
model = models.Sequential()  # 初始化模型

# ---- 卷积神经网络部分 ----
# 增加卷积运算层1,卷积核数量=32,卷积核大小3x3,激活函数relu
# input_shape=(32, 32, 3) 表示输入为32x32像素的彩色图片(3通道)
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
# 增加池化层1,池化窗口2x2,减少特征图尺寸
model.add(layers.MaxPooling2D((2, 2)))

# 增加卷积运算层2,卷积核数量=64,卷积核大小3x3,激活函数relu
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# 增加池化层2
model.add(layers.MaxPooling2D((2, 2)))

# 增加卷积运算层3,卷积核数量=64,卷积核大小3x3,激活函数relu
model.add(layers.Conv2D(64, (3, 3), activation='relu'))

# ---- 全连接层(MLP)部分 ----
# 把多维特征图展平为一维向量,便于输入全连接层
model.add(layers.Flatten())
# 增加全连接层(Dense),64个神经元,激活函数relu
model.add(layers.Dense(64, activation='relu'))
# 增加输出层,10个神经元(如10分类),激活函数softmax用于多分类输出
model.add(layers.Dense(10, activation='softmax'))

# ---- 模型汇总与编译 ----
# 输出模型结构信息
model.summary()

# 编译模型,指定损失函数、优化器和评估指标
model.compile(optimizer='adam',                # 优化器
              loss='sparse_categorical_crossentropy', # 损失函数(适合多分类标签为整数的情况)(稀疏分类交叉熵)
              metrics=['accuracy'])            # 评估指标

# 你的模型已经准备好,可以用 model.fit() 进行训练
# 例如:
# model.fit(x_train, y_train, epochs=10, batch_size=32, validation_data=(x_val, y_val))
# 导入必要的库
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

def model1():
    model = Sequential()  # 初始化一个顺序模型

    # 第一层 LSTM,128 单元,激活函数 relu,输入形状 (n_input, 1)
    # dropout 和 recurrent_dropout 都为 0.5,用于防止过拟合(表示每个时间步输入的特征都有 0.5 的概率被屏蔽)
    # return_sequences=True 表示输出整个序列,为后续 LSTM 层做输入
    model.add(LSTM(
        128, 
        activation='relu', 
        dropout=0.5, 
        recurrent_dropout=0.5,
        input_shape=(n_input, 1),
        return_sequences=True
    ))

    # 第二层 LSTM,64 单元,同样设置 dropout,输出序列
    model.add(LSTM(
        64, 
        dropout=0.5, 
        recurrent_dropout=0.5, 
        activation='relu', 
        return_sequences=True
    ))

    # 第三层 LSTM,只用 1 个单元(通常用于输出最后一个序列特征)
    # return_sequences=False 表示只输出最后一个时间步的结果
    model.add(LSTM(
        1, 
        dropout=0.5, 
        recurrent_dropout=0.5, 
        activation='relu', 
        return_sequences=False
    ))

    # 添加一个全连接层(Dense),用于输出预测结果
    model.add(Dense(1))

    # 编译模型,优化器为 adam,损失函数为均方误差 mse,评估指标为 accuracy
    model.compile(optimizer='adam', loss='mse', metrics=['accuracy'])

    return model

def model2():
    model = Sequential()  # 初始化模型

    # 只有一层 LSTM,50 单元,激活函数 relu,输入形状 (n_input, 1)
    model.add(LSTM(
        50, 
        activation='relu', 
        input_shape=(n_input, 1)
    ))

    # 添加全连接层,输出预测值
    model.add(Dense(1))

    # 编译模型
    model.compile(optimizer='adam', loss='mse', metrics=['accuracy'])

    return model

10. 补充相关知识#


GNN: 生成式对抗网络. 其思想是让图灵测试自动化, 让机器人判断对方是不是机器人. 其训练方式是同时投入真数据和伪装数据给判断方, 让判断方判别真假, 并逐步增强其辨别真假的能力; 同时让生成方不断生成更逼真的伪装数据. 结束条件为达到纳什均衡(0.5).


  1. AlexNet (2012), The input to the network is a 224×224 RGB image. https://papers.nips.cc/paper_files/paper/2012/file/c399862d3b9d6b76c8436e924a68c45b-Paper.pdf 

Comments