0 参考资料

书籍推荐

  1. 统计学习方法 (第2版)
  2. 动手学深度学习(PyTorch版)

课程推荐

  1. 专为程序员设计的高等数学
  2. 程序员的数学基础课
  3. 专为程序员设计的统计课
  4. 专为程序员设计的线性代数(课程代码)
  5. 《深度学习必修课》

深度学习中运用到的数学知识是很多,但没必要陷入去研究数学,重在理解,够用即可。

Markdown数学公式、符号

conda工具常用命令:

  • conda activate env_name # 切换至 env_name 环境
  • conda deactivate # 退出环境
  • conda info -e # 显示所有已经创建的环境 或者 使用 conda env list
  • conda list # 查看所有已经安装的包
  • conda install package_name # 在当前环境中安装包
  • conda remove package # 删除当前环境中的包
  • conda create -n env_name package_name # 创建名为 env_name 的新环境,并在该环境下安装名为package_name的包,可以指定新环境的版本号
  • conda remove --name env_name --all # 删除环境

Jupyter-Notebook 常用快捷键:

1 数学基础

1.1 集合、映射与函数

  • 设A、B是两个非空集合,如果存在一个法则f,使得对A中的每个元素a,按法则 f,在B中有唯一确定的元素b与之对应,那么称 f 为从 A 到B的映射,记作 f:A-> B
  • b 称为元素a在映射f下的像,记作 b = f(a)
  • a 称为元素 b 在映射 f 下的一个原像
  • A 称为 映射 f 的定义域,记作 Df
  • A 中所有元素的像所组成的集合称为映射 f 的值域,记为 Rf

1.2 线性代数

标量:一个标量就是一个数,它只有大小,没有方向
向量:向量是一组标量排列而成,只有一个轴,沿着行或者列的方向。

模长和范数
向量的模长:可以简称为向量的模,英文为norm。表示向量在空间的长度。
对二维向量 a = (a1, a2),其模长 ||a|| 等于 $$\sqrt{a^2 + a_2^2}$$
对n 维向量 a = (a1, a2, …, an),其模长 ||a|| 等于 $$\sqrt{a_1^2 + a_2^2 + … + a_n^2}$$

单位向量:

向量的内积: 也称为点乘、点积,是两个向量对应位置元素相乘后相加,结果是一个标量。

向量的外积:又称向量叉积、叉乘等。外积的运算结果是一个向量而不像内积是一个标量。
两个向量的叉积与这两个向量组成的坐标平面垂直,其值取决于a,b的方向和大小,对应计算公式如下:

矩阵: 是由多个元素组成的表格,是一种二维数据结构,每个数字在矩阵中都有一个对应的行号和列号。

矩阵转置:矩阵的转置是以主对角线为轴,进行镜像翻转。矩阵转置公式如下:
$$(A)^T_m,_n = A_n,_m$$

矩阵乘法: 有m行k列的矩阵 A 和 k行 n列的矩阵 B,矩阵A和矩阵B相乘,则 A 的列数 必须和B的行数相乘。

矩阵相乘示例:
$$\left[
\begin{matrix}
1 & 2 & 3 & 4\
1 & 1 & 1 & 1 \
5 & 6 & 7 & 8
\end{matrix}
\right]

\times

\left[
\begin{matrix}
1 & 5 \
2 & 6 \
3 & 7 \
4 & 8
\end{matrix}
\right]

=

\left[
\begin{matrix}
30 & 70 \
10 & 26 \
70 & 174
\end{matrix}
\right]

$$

矩阵内积: 结果是一个标量,等于两个矩阵AB对应元素直接相乘再相加。对应公式如下:
$$ c = \sum_{i=1}^{m}\sum_{j=1}^{n}A_{i,j}B_{i,j}$$
哈达玛积(Hadamard product): 两个矩阵AB对应元素直接相乘,结果是一个矩阵:

矩阵乘法的性质:

  • 交换律:$AB \leq BA$
  • 分配律:$A(B + C) = AB + AC$
  • 结合律:$(AB)C = A(BC)$
  • 转置性质:$(AB)^T = B^TX^T$

张量: 是多维数组的抽象概括,可以看作是向量和矩阵的推广。向量矩阵的运算方法对张量同样适用。

1.3 微积分

极限: 表示某一点处函数值趋近于某一特定值的过程,一般记为:$\lim_{x\rightarrow{a}}f(x) = L$ ,极限是一种变化状态的描述,核心思想是无限靠近而永远不能到达。

导数: 是函数的局部性质,指一个函数在某一点附近的变化率,对函数 $y=f(x)$ 来说,他的导数用符号 $f^{\prime}(x)$ 来表示,也可记为 $\frac{df(x)}{dx}$ 。

常见导数计算公式:

  • 常数函数: $f(x) = C$ $f^{\prime}(x) = 0$
  • 幂函数: $f(x) = x^n$ $f^{\prime}(x) = nx^{n-1}$
  • 指数函数:$f(x) = e^x$ $f^{\prime}(x) = e^x$
  • 对数函数:$f(x) = ln(x)$ $f^{\prime}(x) = \frac{1}{x}$

微分: 是指对函数的局部变化的一种线性描述,自变量的微分记作 $dx$ ,函数 $y = f(x)$ 的微分记作 $dy = df(x) = f^{\prime}(x)dx$
导数是微分的比值:$f^{\prime} = \frac{df(x)}{dx}$
导数表示变化率,微分表示变化量

偏导数:指的是多元函数在某一点处关于某一变量的导数。

梯度: 为一个包含所有偏导数的向量,符号是 $\nabla$
对函数 $z = f(x,y) = x^2 + y^2$ 来说,它的梯度向量是:$\nabla f(x,y) = (2x,2y)$

链式法则: 用来计算复合函数导数的。假设对实数x,有可微函数 f 和 g,其中 $z = f(y), y = g(x)$ 那么,链式法则公式如下:$$\frac{dz}{dx}=\frac{dz}{dy}.\frac{dy}{dx}$$

所谓链式法则,就是一层一层增加可以“相互抵消”的分子分母

有函数 $f(x)=x^2$ 和 $g(x)=x+1$ ,计算 $h(x)=f(g(x))=(x+1)^2$ 的导数,可得:$$h^\prime(x) = f^\prime(g(x)){\cdot}g^\prime(x) = 2(x+1){\cdot}1 = 2x + 2$$

1.4 概率统计

概率:

  • 概率可以用来表示模型的准确率(错误率)
  • 概率可以用来描述模型的不确定性
  • 概率可以作为模型损失的度量

事件:

  • 事件相当于实验的结果
  • 随机事件指一次或多次随机试验的结果
  • 事件的基本属性包括:可能性、确定性、兼容性
  • 依赖事件指的是事件的发生受其他事件影响
  • 独立事件指的是事件的发生与其他事件无关

随机变量和概率分布:

  • 随机变量是概率统计中用来表示随机事件结果的变量
  • 随机变量包括离散型随机变量和连续型随机变量
  • 概率分布用来描述随机变量的分布情况

概率密度:

联合概率和条件概率:

  • 联合概率指同时发生两个或多个事件的概率,记为 $P(A,B)$
  • 条件概率是指在某个条件下发生某个事件的概率,记为 $P(A|B)$
  • 联合概率和条件概率相互转化: $P(A,B) = P(A|B)P(B)$ $P(A|B) = \frac{P(A,B)}{P(B)}$

贝叶斯定理: 表示在已知条件概率的情况下,可以推导出联合概率。常用于根据已知信息推测未知信息的场景,公式如下:$$ P(A|B) = \frac{P(B|A)P(A)}{P(B)}$$
极大似然估计: Maximum Likelihood Estimation,MLE:利用已知的样本结果,反推最有可能导致这样结果的参数值,即找到参数的最大概率取值。

对于给定的样本集 $X = {x_1,x_2,…,x_n}$ 我们需要估计参数向量 $\theta$,此时可以计算似然函数 $L(\theta)$ ,等于联合概率密度函数 $p(X|\theta)$
公式表示如下:$$L(\theta) = p(X|\theta) = \prod_{i=1}^{n}p(x_i|\theta)$$

2 深度神经网络

2.1 神经元模型

神经网络是模拟了生物上的神经元结构,通过多层神经元,组成的训练模型,如下,一层神经网络的函数如下:
$$y = f(\sum_{i=1}^{n}w_ix_i + b)$$

以上通过多个输入加权,经过激活函数 f 后得到输出。增加多个隐藏层的神经网络如下:

  • 激活函数:为了为数据增加非线性变化(每个隐藏层后边都会经过激活函数后产生的输出作为下一个隐藏层的输入)
  • softmax:对输出数据进行归一化处理,转换成概率值
  • 交叉熵损失:计算损失

2.2 常见的激活函数

2.2.1 Sigmoid

2.2.2 Tranh 函数

  • Sigmoid 改进版
  • 输出值压缩到(-1,1)
  • 输出以 0 为中心
  • 更快的收敛速度

函数公式:$$f(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}$$
函数表示:

2.2.3 ReLU 函数

  • 多数情况下第一选择
  • 解决梯度消失问题
  • 计算上比 Sigmoid 和 tanh 函数快
  • Dying ReLU 问题

公式表示:$f(x) = max(0, x)$
函数表示:

2.3 Softmax 函数

  • 输入值映射到概率分布上
  • 主要用在多分类问题
  • 使得输出具有可解释性

2.4 前向传播和反向传播

损失函数:

  • 链式法则
    通过链式法则最小化损失函数求解。

基于 PyTorch 搭建神经网络的流程:

  1. 加载数据
  2. 定义网络结构
  3. 损失函数
  4. 优化器
  5. 训练
  6. 测试
  7. 保存模型

2.5 模型训练常见问题

模型架构设计考虑以下几点:

  1. 网络结构
  2. 节点数量
  3. 网络层数
  4. 不同类型的层
  5. 层间连接关系等

万能近似定理: 一个足够多的隐藏节点的多层前馈神经网络,可以逼近任意连续的函数
宽度 指 每层神经元数量,深度 指 神经网络隐藏层的层数。

  • 大量实验证明 增加深度更有助于提高泛化能力

2.5.1 过拟合欠拟合

过拟合问题:

  • Overfitting:模型在训练数据上表现良好,在测试数据上不佳
  • 泛化能力:训练后的模型应用到新的、未知的数据上的能力
  • 产生原因:通常是由模型复杂度过高导致

欠拟合问题:

  • Underfitting:学习能力不足,无法学习到数据集中的“一般规律”
  • 产生原因:模型学习能力较弱,而数据复杂度较高的情况

过拟合与欠拟合在误差上的变化:

2.5.2 过拟合问题解决方法

数据集大小选择: 根据情况进行评估

  • 数据集较小,很容易出现过拟合
  • 数据集过大可能导致训练效率降低
  • 通过数据增强:对训练数据进行变换,增加数据数量和多样性,可以有效解决过拟合问题,提高模型的泛化能力

使用验证集: 训练中评估模型性能,调整超参数

K折交叉验证:

  1. 将训练数据划分为 K 份
  2. 对于每份数据作为验证集,剩余的 K-1 份数据作为训练集,进行训练和验证
  3. 计算 K 次验证的平均值

提前终止:模型对训练数据集迭代收敛之前停止迭代来防止过拟合,如果在训练集上发现测试误差上升,则停止训练

正则化: 能够显著减少方差,而不过度增加偏差的策略都可以认为是正则化技术,故推广的正则化技术还有:扩增样本集、提前终止、Dropout、权重衰减、L1正则化、L2正则化、集成学习、多任务学习、对抗训练、参数共享等。

L2正则化: 通过给模型的损失函数添加一个模型参数的平方和的惩罚项来实现正则化。$$Loss = Loss_{original} + \lambda\sum_{i=1}^{n}w_i^2$$
L1正则化:通过在损失函数中加入对模型参数权值矩阵各元素绝对值之和的惩罚项,来限制模型参数的值。$$Loss = Loss_{original} + \lambda\sum_{i=1}^{n}(|w_i|)$$
L1与L2对比:

  • L1正则化更倾向于产生稀疏解,适于特征选择
  • L2正则化更倾向于小的非零权值,更适用于优化问题

Dropout: 在训练过程中随机“删除”(即将其权重设为零)一些神经元,注意:只在训练期间,不用在测试期间
主要步骤:
1. 指定一个保留比例 p
2. 每层每个神经元,以 p 的概率保留,以 1-p 的概率将权重设为零
3. 训练中使用保留的神经元进行前向、反向传播
4. 测试过程,将所有权重乘以 p

相当于把一个网络拆分,由多个网络构成集成学习,减少神经元之间复杂的关系

优点:可以有效减少过拟合,简单方便,实用有效
缺点:降低训练效率,损失函数不够明确

整理后,过拟合应对策略如下:

  1. 问题本质分析
  2. 数据集大小选择
  3. 数据增强
  4. 增加验证集
  5. 模型选择
  6. K 折交叉验证
  7. 提前终止
  8. 正则化
  9. Dropout

没有免费午餐定理:没有一种算法或者模型能够在所有的场景中都表现良好

2.5.3 梯度消失和梯度爆炸

梯度消失: 激活函数的导数小于 1 容易发生梯度消失
梯度爆炸: 梯度在更新中累积,变成非常大,导致网络不稳定。原因:1. 深层网络 2. 初始化权重的值过大
解决方法:
- 预训练加微调
- 梯度剪切:设置一个梯度剪切阈值,超过则将其强制限制在这个范围之内
- 正则
- ReLU激活函数
- Batchnorm:将输出信号规范化到均值为0,方差为1,保证网络的稳定性
- 残差结构:跨层连接结构解决梯度消失问题

2.6 梯度下降 **

2.6.1 损失函数

  • 损失函数(loss function):衡量预测值和真实值之间差异的函数,可以用下边表达式表示:

2.6.2

11 注意力神经网络

11.1 什么是注意力机制

  • 注意力机制类型
    隐式 VS 显式

软注意力:函数在其域内平滑变化,因此是可微的
硬注意力:用随机抽样模型代替了确定性方法,不可微的
image.png

11.2 自注意力机制

参考资料:https://jalammar.github.io/illustrated-transformer/

在传统的循环神经网络(RNN)中,信息是按顺序处理的,这限制了模型捕捉长距离依赖的能力。而自注意力机制允许模型在处理每个词时,参考序列中所有其他词的信息,从而更全面地理解上下文。

自注意力的计算步骤:

  1. 输入表示:将输入序列中的每个词转换为向量表示,通常通过词嵌入(Embedding)实现。
  2. 生成查询(Query)、键(Key)和值(Value)向量:对于每个词的向量表示,分别乘以三个不同的权重矩阵,得到对应的 Query、Key 和 Value 向量。
  3. 计算注意力权重:对于每个词的 Query,计算其与所有词的 Key 的点积,得到一个得分,表示该词对其他词的关注程度。
  4. 缩放与归一化:将上述得分除以一个缩放因子(通常是 Key 向量维度的平方根),然后通过 Softmax 函数归一化,得到注意力权重。
  5. 加权求和:使用注意力权重对所有词的 Value 向量进行加权求和,得到当前词的新的表示。

image.png

这一过程可以用以下公式表示:
image.png

其中,Q、K、V 分别是查询、键和值的矩阵,d_k 是键向量的维度。
image.png

多头注意力机制(Multi-Head Attention):
为了让模型从不同的子空间捕捉信息,Transformer 使用了多头注意力机制。具体来说,它将 Query、Key 和 Value 向量分别通过多个不同的线性变换,得到多个头的表示。每个头独立地执行上述的注意力计算,最后将所有头的输出拼接起来,再通过一个线性变换,得到最终的输出。这种机制使模型能够同时关注到不同类型的关系和特征。

11.3 Q、K、V来源

在自注意力机制中,Q、K、V 向量都是通过对输入序列的表示进行线性变换得到的。具体过程如下:

  1. 输入表示:首先,将输入序列中的每个元素(如词或子词)转换为向量表示,通常通过词嵌入(Embedding)层实现,得到输入矩阵 X。
  2. 线性变换:然后,使用三个不同的权重矩阵 W^Q、W^K 和 W^V 对输入矩阵 X 进行线性变换,生成对应的 Q、K、V 向量:
    • Q = XW^Q
    • K = XW^K
    • V = XW^V

这些权重矩阵是模型在训练过程中学习得到的参数。通过这种方式,模型可以为每个输入元素生成不同的 Q、K、V 向量,从而捕捉序列中各元素之间的关系。

11.4 位置编码

由于 Transformer 模型完全基于自注意力机制(Self-Attention),它在处理输入序列时是并行的,缺乏对元素顺序的敏感性。为了解决这一问题,Transformer 引入了位置编码,以提供序列中元素的位置信息。

绝对位置编码:
由于 Transformer 模型完全基于自注意力机制(Self-Attention),它在处理输入序列时是并行的,缺乏对元素顺序的敏感性。为了解决这一问题,Transformer 引入了位置编码,以提供序列中元素的位置信息。
这种方法使得模型能够学习到序列中元素的绝对位置信息,并具有一定的泛化能力。

相对位置编码:
除了绝对位置编码,研究人员还提出了相对位置编码的方法,以捕捉元素之间的相对位置信息。例如,RoFormer 模型引入了旋转位置编码(Rotary Position Embedding, RoPE),通过旋转矩阵将位置信息融入到注意力机制中,从而增强模型对相对位置信息的建模能力。

11.5 编码器-解码器结构

一个由两个堆叠的编码器和解码器组成的 Transformer:
image.png

各个组件协同工作的步骤如下:

  1. 编码器首先处理输入序列。然后,顶部编码器的输出被转换为一组注意向量 K 和 V。每个解码器将在其“编码器-解码器注意”层中使用它们,这有助于解码器将注意力集中在输入序列中的适当位置
    image.png

  2. 以下步骤重复该过程,直到出现特殊到达符号表示 Transformer 解码器已完成输出。每一步的输出都会在下一个时间步中馈送到底部解码器,解码器会像编码器一样将其解码结果冒泡。就像我们对编码器输入所做的那样,我们在这些解码器输入中嵌入并添加位置编码,以指示每个单词的位置。
    image.png

  3. 解码器中的自注意力层的操作方式与编码器中的自注意力层略有不同:在解码器中,自注意力层仅允许关注输出序列中较早的位置。这是通过-inf在自注意力计算中的softmax步骤之前屏蔽未来位置(将其设置为)来实现的。

11.6 线性层和 Softmax 层

解码器堆栈输出一个浮点向量。我们如何将其转换成一个单词呢?这是最后的线性层的任务,该层之后是 Softmax 层。
线性层是一个简单的完全连接的神经网络,它将解码器堆栈产生的向量投影到一个更大的向量中,称为 logits 向量。
然后,softmax 层将这些分数转换为概率(所有分数均为正,加起来等于 1.0)。选择概率最高的单元格,并生成与其关联的单词作为此时间步的输出。
image.png