02 - 深度学习算法(必修)
0 参考资料
书籍推荐
课程推荐
- 专为程序员设计的高等数学
- 程序员的数学基础课
- 专为程序员设计的统计课
- 专为程序员设计的线性代数(课程代码)
- 《深度学习必修课》
深度学习中运用到的数学知识是很多,但没必要陷入去研究数学,重在理解,够用即可。
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 搭建神经网络的流程:
- 加载数据
- 定义网络结构
- 损失函数
- 优化器
- 训练
- 测试
- 保存模型
2.5 模型训练常见问题
模型架构设计考虑以下几点:
- 网络结构
- 节点数量
- 网络层数
- 不同类型的层
- 层间连接关系等
万能近似定理: 一个足够多的隐藏节点的多层前馈神经网络,可以逼近任意连续的函数
宽度 指 每层神经元数量,深度 指 神经网络隐藏层的层数。
- 大量实验证明 增加深度更有助于提高泛化能力
2.5.1 过拟合欠拟合
过拟合问题:
- Overfitting:模型在训练数据上表现良好,在测试数据上不佳
- 泛化能力:训练后的模型应用到新的、未知的数据上的能力
- 产生原因:通常是由模型复杂度过高导致
欠拟合问题:
- Underfitting:学习能力不足,无法学习到数据集中的“一般规律”
- 产生原因:模型学习能力较弱,而数据复杂度较高的情况
过拟合与欠拟合在误差上的变化:
2.5.2 过拟合问题解决方法
数据集大小选择: 根据情况进行评估
- 数据集较小,很容易出现过拟合
- 数据集过大可能导致训练效率降低
- 通过数据增强:对训练数据进行变换,增加数据数量和多样性,可以有效解决过拟合问题,提高模型的泛化能力
使用验证集: 训练中评估模型性能,调整超参数
K折交叉验证:
- 将训练数据划分为 K 份
- 对于每份数据作为验证集,剩余的 K-1 份数据作为训练集,进行训练和验证
- 计算 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
相当于把一个网络拆分,由多个网络构成集成学习,减少神经元之间复杂的关系
优点:可以有效减少过拟合,简单方便,实用有效
缺点:降低训练效率,损失函数不够明确
整理后,过拟合应对策略如下:
- 问题本质分析
- 数据集大小选择
- 数据增强
- 增加验证集
- 模型选择
- K 折交叉验证
- 提前终止
- 正则化
- Dropout
没有免费午餐定理:没有一种算法或者模型能够在所有的场景中都表现良好
2.5.3 梯度消失和梯度爆炸
梯度消失: 激活函数的导数小于 1 容易发生梯度消失
梯度爆炸: 梯度在更新中累积,变成非常大,导致网络不稳定。原因:1. 深层网络 2. 初始化权重的值过大
解决方法:
- 预训练加微调
- 梯度剪切:设置一个梯度剪切阈值,超过则将其强制限制在这个范围之内
- 正则
- ReLU激活函数
- Batchnorm:将输出信号规范化到均值为0,方差为1,保证网络的稳定性
- 残差结构:跨层连接结构解决梯度消失问题
2.6 梯度下降 **
2.6.1 损失函数
- 损失函数(loss function):衡量预测值和真实值之间差异的函数,可以用下边表达式表示: