关于深度学习
深度学习是当前人工智能领域的热门方向,其核心是通过多层神经网络学习数据特征。单层神经网络包含输入层、隐藏层和输出层,通过激活函数引入非线性。多层神经网络(如用于MNIST手写数字识别的网络)通过堆叠隐藏层提取更复杂的特征,使用交叉熵损失和正则化(如Dropout)提高性能。卷积神经网络(CNN)专为图像处理设计,利用卷积层检测局部特征,池化层进行下采样。研究表明,深度学习方法在图像分类等任务上显著
深度学习 (Deep Learning)
目前非常火热的领域,这个甚至能单开一本书。
单层神经网络 (Single Layer Neural Networks)
实际上是只有一个隐藏层的前馈神经网络。
神经网络接受一个包含 ppp 个变量的输入向量 X=(X1,X2,…,Xp)X = (X_1, X_2, \dots, X_p)X=(X1,X2,…,Xp),并构建一个非线性函数 f(X)f(X)f(X) 来预测响应 YYY。
上图是一个经典的单隐藏层神经网络。
- 输入层:包含 p=4p=4p=4 个节点,每个节点代表一个输入特征 X1,X2,X3,X4X_1, X_2, X_3, X_4X1,X2,X3,X4。
- 隐藏层:包含 K=5K=5K=5 个节点。每个隐藏节点计算一个激活值 AkA_kAk。
- 输出层:只有一个节点,代表最终的预测 f(X)f(X)f(X)。
隐藏层叫隐藏的原因为值是从数据中学习得到的。
该神经网络模型的形式为:
f(X)=β0+∑k=1Kβkhk(X)=β0+∑k=1Kβkg(wk0+∑j=1pwkjXj) \begin{align} f(X) &= \beta_0 + \sum_{k=1}^{K} \beta_k h_k(X) \\ &= \beta_0 + \sum_{k=1}^{K} \beta_k g\left(w_{k0} + \sum_{j=1}^{p} w_{kj}X_j\right) \end{align} f(X)=β0+k=1∑Kβkhk(X)=β0+k=1∑Kβkg(wk0+j=1∑pwkjXj)
公式分两步构建。
隐藏层中的 KKK 个激活值 Ak,k=1,…,KA_k, k=1, \dots, KAk,k=1,…,K,被计算为输入特征 X1,…,XpX_1, \dots, X_pX1,…,Xp 的函数:
Ak=hk(X)=g(wk0+∑j=1pwkjXj) A_k = h_k(X) = g\left(w_{k0} + \sum_{j=1}^{p} w_{kj}X_j\right)Ak=hk(X)=g(wk0+j=1∑pwkjXj)
其中:
- wkjw_{kj}wkj 是权重,连接输入 jjj 到隐藏单元 kkk。
- wk0w_{k0}wk0是偏置项,相当于线性模型的截距。
- g(z)g(z)g(z) 是一个预先指定的非线性激活函数。
然后,来自隐藏层的这 KKK 个激活值馈送到输出层,得到:
f(X)=β0+∑k=1KβkAk f(X) = \beta_0 + \sum_{k=1}^{K} \beta_k A_kf(X)=β0+k=1∑KβkAk
可以发现,这是一个关于 K=5K=5K=5 个激活值的线性回归模型。
激活函数
激活函数 g(⋅)g(\cdot)g(⋅) 中的非线性是至关重要的,没有它,模型 f(X)f(X)f(X) 将会退化为一个关于 X1,…,XpX_1, \dots, X_pX1,…,Xp 的简单线性模型。
f(X)=β0+∑βk(wk0+∑wkjXj)=(β0+∑βkwk0)+∑(∑βkwkj)Xj \begin{align} f(X) &= \beta_0 + \sum\beta_k(w_{k0}+\sum w_{kj}X_j)\\ &=(\beta_0 + \sum\beta_kw_{k0})+\sum(\sum \beta_kw_{kj})X_j \end{align} f(X)=β0+∑βk(wk0+∑wkjXj)=(β0+∑βkwk0)+∑(∑βkwkj)Xj
常用的激活函数有两个。
- sigmoid激活函数:g(z)=11+e−zg(z) = \frac{1}{1+e^{-z}}g(z)=1+e−z1
- 将输入压缩到(0,1)区间
- 历史上很流行,但现在较少用于隐藏层
- ReLU(修正线性单元,rectified linear unit):g(z)=max(0,z)g(z) = max(0, z)g(z)=max(0,z)
- 现代神经网络的首选
- 计算简单高效
- 缓解了梯度消失问题
上图是两个激活函数图像,线性的 ReLU 很受欢迎。
例子
书里有一个例子。
假设有 p=2p=2p=2 个输入变量 X=(X1,X2)X=(X_1, X_2)X=(X1,X2) 和 K=2K=2K=2 个隐藏单元 h1(X)h_1(X)h1(X) 和 h2(X)h_2(X)h2(X),激活函数为 g(z)=z2g(z)=z^2g(z)=z2。我们指定其他参数如下:
β0=0,β1=14,β2=−14,w10=0,w11=1,w12=1,w20=0,w21=1,w22=−1. \begin{align} \beta_0 &= 0, \quad \beta_1 = \frac{1}{4}, \quad \beta_2 = -\frac{1}{4}, \\ w_{10} &= 0, \quad w_{11}=1, \quad w_{12}=1, \\ w_{20} &= 0, \quad w_{21}=1, \quad w_{22}=-1. \end{align} β0w10w20=0,β1=41,β2=−41,=0,w11=1,w12=1,=0,w21=1,w22=−1.
接下来计算,有
h1(X)=(0+X1+X2)2,h2(X)=(0+X1−X2)2.f(X)=0+14⋅(0+X1+X2)2−14⋅(0+X1−X2)2=14((X1+X2)2−(X1−X2)2)=X1X2. \begin{align} h_1(X) &= (0 + X_1 + X_2)^2, \\ h_2(X) &= (0 + X_1 - X_2)^2. \\ f(X) &= 0 + \frac{1}{4} \cdot (0+X_1+X_2)^2 - \frac{1}{4} \cdot (0+X_1-X_2)^2 \\ &= \frac{1}{4}\left((X_1+X_2)^2 - (X_1-X_2)^2\right) \\ &= X_1X_2. \end{align} h1(X)h2(X)f(X)=(0+X1+X2)2,=(0+X1−X2)2.=0+41⋅(0+X1+X2)2−41⋅(0+X1−X2)2=41((X1+X2)2−(X1−X2)2)=X1X2.
神经网络自动学习出了交互项 X1X2X_1X_2X1X2.
模型训练
拟合一个神经网络需要估计一些未知参数,对于定量响应,通常使用平方误差损失,因此选择参数以最小化:
∑i=1n(yi−f(xi))2 \sum_{i=1}^{n} (y_i - f(x_i))^2 i=1∑n(yi−f(xi))2
多层神经网络 (Multilayer Neural Networks)
书里用 MNIST 数据集来说明。
上图就是数据集,特点如下:
- 任务:将28x28像素的灰度手写数字图像分类为0-9。
- 输入:
p = 28 × 28 = 784
个像素值(0-255的灰度值)。 - 输出:10个类别的概率分布,使用独热编码(one-hot encoding)表示。
- 例如,数字"3"表示为
[0,0,0,1,0,0,0,0,0,0]
- 例如,数字"3"表示为
- 数据规模:60,000张训练图像,10,000张测试图像。
然后是解决这个问题的多层网络架构。
这图跟上一节的单层网络有不同,他有两层隐藏层。
- 输入层:784个节点(对应784个像素)
- 第一个隐藏层 L1L_1L1:256个节点
- 第二个隐藏层 L2L_2L2:128个节点
- 输出层:10个节点(对应10个数字类别)
计算
第一层隐藏层:
Ak(1)=hk(1)(X)=g(wk0(1)+∑j=1pwkj(1)Xj) A_k^{(1)} = h_k^{(1)}(X) = g\left(w_{k0}^{(1)} + \sum_{j=1}^{p} w_{kj}^{(1)}X_j\right)Ak(1)=hk(1)(X)=g(wk0(1)+j=1∑pwkj(1)Xj)
从原始像素 XXX 中学习第一层特征表示。
第二层隐藏层:
Al(2)=hl(2)(X)=g(wl0(2)+∑k=1K1wlk(2)Ak(1)) A_l^{(2)} = h_l^{(2)}(X) = g\left(w_{l0}^{(2)} + \sum_{k=1}^{K_1} w_{lk}^{(2)}A_k^{(1)}\right) Al(2)=hl(2)(X)=g(wl0(2)+k=1∑K1wlk(2)Ak(1))
第二个隐藏层将第一个隐藏层的激活值 Ak(1)A_k^{(1)}Ak(1) 作为输入并计算新的激活值。
Al(2)A_l^{(2)}Al(2) 实际上是 XXX 的更复杂的非线性变换。
- 这一层学习的是特征的组合,比第一层更抽象。
最后是输出层,第一步是计算十个不同的线性模型
Zm=βm0+∑l=1K2βmlhl(2)(X)=βm0+∑l=1K2βmlAl(2) Z_m = \beta_{m0} + \sum_{l=1}^{K_2} \beta_{ml}h_l^{(2)}(X) = \beta_{m0} + \sum_{l=1}^{K_2} \beta_{ml}A_l^{(2)}Zm=βm0+l=1∑K2βmlhl(2)(X)=βm0+l=1∑K2βmlAl(2)
对于 m=0,1,…,9m=0, 1, \dots, 9m=0,1,…,9。矩阵 BBB 存储了所有这 129×10=1,290129 \times 10 = 1,290129×10=1,290 个权重。
这里是为每个类别 mmm 计算一个"得分"。
激活函数使用softmax函数:
fm(X)=Pr(Y=m∣X)=eZm∑l=09eZl f_m(X) = \text{Pr}(Y=m|X) = \frac{e^{Z_m}}{\sum_{l=0}^{9} e^{Z_l}}fm(X)=Pr(Y=m∣X)=∑l=09eZleZm
将10个得分转换为概率分布。
对于多分类问题,使用交叉熵损失:
−∑i=1n∑m=09yimlog(fm(xi)) -\sum_{i=1}^{n}\sum_{m=0}^{9} y_{im}\log(f_m(x_i)) −i=1∑nm=0∑9yimlog(fm(xi))
也被称为交叉熵(cross-entropy)。
之后需要正则化,具体的放在之后说。
书里有个表格说明正则的重要性。
方法 | 测试错误率 |
---|---|
神经网络 + 岭正则化 | 2.3% |
神经网络 + Dropout正则化 | 1.8% |
多项式逻辑回归 | 7.2% |
线性判别分析 | 12.7% |
卷积神经网络 (Convolutional Neural Networks)
图像分类会用到 CNN。
书里用这个例子。
网络首先识别输入图像中的低级特征,例如小的边缘、色块等。然后,这些低级特征被组合起来形成更高级的特征,例如耳朵、眼睛的局部等等。最终,这些高级特征的存在与否,共同决定了任何给定输出类别的概率。
卷积神经网络是包含两种特殊类型的隐藏层,分别称为卷积层 (convolution layers) 和池化层 (pooling layers)。
卷积层在图像中搜索小模式的实例,而池化层则对这些实例进行下采样 (downsample),以选择其中一个突出的子集。
卷积层 (Convolution Layers)
一个卷积层由大量的卷积滤波器 (convolution filters) 组成,每个滤波器都是一个模板,用于确定图像中是否存在特定的局部特征。
卷积操作为用一个小的滤波器(模板)在图像上滑动,检测是否存在特定的局部模式。
书里有一个例子,假设有一个4×34 \times 34×3 图像的例子:
原始图像=(abcdefghijkl) \text{原始图像} = \begin{pmatrix} a & b & c \\ d & e & f \\ g & h & i \\ j & k & l \end{pmatrix} 原始图像=
adgjbehkcfil
现在考虑一个 2×22 \times 22×2 的滤波器,形式如下:
卷积滤波器=(1111) \text{卷积滤波器} = \begin{pmatrix} 1 & 1 \\ 1 & 1 \end{pmatrix} 卷积滤波器=(1111)
当我们将图像与该滤波器进行卷积时,得到的结果是:
卷积后的图像=(a+b+d+eb+c+e+fd+e+g+he+f+h+ig+h+j+kh+i+k+l). \text{卷积后的图像} = \begin{pmatrix} a+b+d+e & b+c+e+f \\ d+e+g+h & e+f+h+i \\ g+h+j+k & h+i+k+l \end{pmatrix}. 卷积后的图像=
a+b+d+ed+e+g+hg+h+j+kb+c+e+fe+f+h+ih+i+k+l
.
人话来说,滤波器在图像的每个位置进行元素乘积累加,相似度高的区域会产生大的响应值。
上图是应用,老虎是192×179192 \times 179192×179 ,滤波器是15×1515 \times 1515×15。水平条纹滤波器检测图像中的水平边缘和条纹,垂直条纹滤波器检测图像中的垂直边缘和条纹。
这样原始图像视为卷积神经网络中的输入层,卷积后的图像视为第一个隐藏层中的单元。
卷积层有如下特性:
- 局部连接:每个神经元只连接输入的一小片区域(感受野)
- 权重共享:同一个滤波器在整个图像上滑动使用
- 多通道处理:彩色图像的RGB三通道分别卷积后相加
池化层 (Pooling Layers)
池化层 (pooling layer) 提供了一种将大图像压缩成更小摘要图像的方法。
最大池化 (max pooling) 操作通过取每个不重叠的 2×22 \times 22×2 像素块中的最大值来对图像进行摘要。这使得图像在每个方向上的尺寸都减小了一半,并且还提供了一定的位置不变性 (location invariance)。
下面是一个最大池化的简单例子:
(1253301221341120)→最大池化(3524). \begin{pmatrix} 1 & 2 & 5 & 3 \\ 3 & 0 & 1 & 2 \\ 2 & 1 & 3 & 4 \\ 1 & 1 & 2 & 0 \end{pmatrix} \xrightarrow{\text{最大池化}} \begin{pmatrix} 3 & 5 \\ 2 & 4 \end{pmatrix}.
1321201151323240
最大池化(3254).
池化层的目的是防止过拟合。
卷积神经网络的架构
CNN有非常多的卷积层和池化层,上图的流程:
输入图像 (32x32x3) -> 卷积 -> 32x32x8 -> 池化 -> 16x16x8 -> 卷积 -> 16x16x16 -> 池化 -> 8x8x16 -> 卷积 -> 8x8x32 -> 池化 -> 4x4x32 -> 展平 (flatten) -> 500 个单元 -> 100 个单元 (输出)
这种卷积-池化的交替是CNN的标准设计、
在构建这样一个网络时,除了每层的数量、性质和大小之外,还有许多调节参数需要选择。可以在每一层使用 Dropout 学习,也可以使用 lasso 或岭回归正则化等等。
数据增强 (Data Augmentation)
数据增强是一种通过对现有训练数据进行合理的随机变换来人工扩展数据集的技术。、
上图就是个例子。最左图是原图,右边都是变换的。
人类来看都是老虎,但 CNN不觉得这些都是老虎,学习的时候相当于一种正则化技术。
使用预训练分类器的结果
这里是迁移学习:将在大型数据集上学到的知识应用到相关但数据量较小的任务中。
书里有个例子,没什么干货,直接省略了。
提到了权重冻结(Weight Freezing):
- 冻结:保持预训练模型的卷积层权重不变
- 微调:只训练最后几层(全连接层)
- 优势:
- 利用通用特征提取能力
- 只需要少量任务特定数据
- 训练速度快,计算成本低
文档分类 (Document Classification)
这一节的例子是 IMDb 电影评论数据集。响应变量是评论的情感,分为正面或负面。
比如说下面这个:
This has to be one of the worst films of the 1990s. When my friends & I were watching this film (being the target audience it was aimed at) we just sat & watched the first half an hour with our jaws touching the floor at how bad it really was. The rest of the time, everyone else in the theater just started talking to each other, leaving or generally crying into their popcorn …
单纯的文字肯定不行,这些段落需要特征化 (featurize) 才能用。
最简单和最常见的特征化方法是词袋 (bag-of-words) 模型,词袋模型将文档表示为词汇表中单词出现与否的向量,完全忽略单词的顺序和语法。
首先会构建一个包含 MMM 个单词的词汇表,然后对每个文档创建一个长度为 MMM 的二元特征向量,如果单词出现则记为 1,否则记为 0。
本节的例子限制为在 25,000 条评论的训练语料库中出现频率最高的 10,000 个单词。
START this film was just brilliant casting location scenery story direction everyone’s really suited the part they played and you could just imagine being there robert UNK is an amazing actor and now the same being director UNK father came from the same scottish island as myself so i loved …
经过这种简化后,二元特征向量的长度为 10,000,并且主要由 0 组成,只有少量对应于文档中出现的单词的位置为 1。
词袋模型也有问题:
- 忽略词序:"not good"和"good not"被视为相同
- 忽略上下文:无法理解短语和语义关系
- 词汇鸿沟:同义词被当作不同特征处理
准备一个训练集和一个测试集,每个都包含 25,000 个样本。最终得到的训练特征矩阵 XXX 的维度是 25,000×10,00025,000 \times 10,00025,000×10,000,但其中只有 1.3% 的二元条目是非零的。
这样的矩阵为稀疏 (sparse) 矩阵,大部分的值是相同的,在计算机上很好存储。
上图是模型比较,左图是Lasso逻辑回归,可以看到随着 λ\lambdaλ 减小,训练准确率单调上升。
右图是神经网络,两个隐藏层,每层16个ReLU单元。随着训练轮次增加,训练准确率单调上升。
但两个方法都表现出明显的过拟合。
二分类神经网络等价于一个非线性逻辑回归模型:
logPr(Y=1∣X)Pr(Y=0∣X)=Z1−Z0=(β10−β00)+∑k=1K2(β1k−β0k)Ak(2) \begin{align} \log \frac{\text{Pr}(Y=1|X)}{\text{Pr}(Y=0|X)} &= Z_1 - Z_0 \\ &= (\beta_{10} - \beta_{00}) + \sum_{k=1}^{K_2} (\beta_{1k} - \beta_{0k})A_k^{(2)} \end{align} logPr(Y=0∣X)Pr(Y=1∣X)=Z1−Z0=(β10−β00)+k=1∑K2(β1k−β0k)Ak(2)
公式能说明三个性质:
- 神经网络学习的是对数几率的非线性变换
- softmax函数在二分类情况下存在冗余性
- 本质上是在学习特征的非线性组合
此外,词袋模型还有其他版本:n-gram 词袋模型 (bag-of-n-grams model),考虑连续的单词对。或者是文档视为一个序列 (sequence),考虑所有单词在其前后词的上下文中。
循环神经网络 (Recurrent Neural Networks)
很多文档本质上是序列性的,需要特殊处理。
循环神经网络 (recurrent neural network, RNN) 是专门为处理序列数据而设计的神经网络架构。
上图是 RNN 的示意图。输入是一个向量序列 {Xℓ}ℓ=1L\{X_\ell\}_{\ell=1}^L{Xℓ}ℓ=1L。网络按顺序处理输入序列 XXX。
每个 XℓX_\ellXℓ 都被输入到隐藏层,该隐藏层同时也接收来自序列中前一个元素的激活向量 Aℓ−1A_{\ell-1}Aℓ−1 作为输入,并产生当前的激活向量 AℓA_\ellAℓ。
在处理序列的每个元素时,都使用相同的权重集合 WWW, UUU 和 BBB。输出层根据当前的激活 AℓA_\ellAℓ 产生一个预测序列 OℓO_\ellOℓ,一般只关心最后一个预测 OLO_LOL。这是权重共享 (weight sharing)。
隐藏状态的更新公式如下:
Aℓk=g(wk0+∑j=1pwkjXℓj+∑s=1KuksAℓ−1,s) A_{\ell k} = g\left( w_{k0} + \sum_{j=1}^p w_{kj}X_{\ell j} + \sum_{s=1}^K u_{ks}A_{\ell-1,s} \right) Aℓk=g(wk0+j=1∑pwkjXℓj+s=1∑KuksAℓ−1,s)
其中:
- WWW:输入到隐藏层的权重
- UUU:隐藏层到隐藏层的权重
- g(⋅)g(\cdot)g(⋅):激活函数(如ReLU)
输出 OℓO_\ellOℓ 的计算方式为
Oℓ=β0+∑k=1KβkAℓk O_\ell = \beta_0 + \sum_{k=1}^K \beta_k A_{\ell k}Oℓ=β0+k=1∑KβkAℓk
对于回归问题,一个观测 (X,Y)(X,Y)(X,Y) 的损失函数是
(Y−OL)2, (Y - O_L)^2,(Y−OL)2,
只有最后一个输出OLO_LOL用于计算损失,中间输出O1,…,OL−1O_1, \dots, O_{L-1}O1,…,OL−1不被直接使用。
总体目标为最小化所有训练序列的损失和:
∑i=1n(yi−oiL)2=∑i=1n(yi−(β0+∑k=1Kβkg(wk0+∑j=1pwkjxiLj+∑s=1Kuksai,L−1,s)))2 \sum_{i=1}^n (y_i - o_{iL})^2 = \sum_{i=1}^n \left( y_i - \left( \beta_0 + \sum_{k=1}^K \beta_k g\left( w_{k0} + \sum_{j=1}^p w_{kj}x_{iLj} + \sum_{s=1}^K u_{ks}a_{i,L-1,s} \right) \right) \right)^2i=1∑n(yi−oiL)2=i=1∑n(yi−(β0+k=1∑Kβkg(wk0+j=1∑pwkjxiLj+s=1∑Kuksai,L−1,s)))2
用于文档分类的序列模型
都热编码有他自身的局限性:
- 维度爆炸:10,000维向量表示每个词
- 语义缺失:所有词向量相互正交,无法表达语义关系
- 计算低效:处理高维稀疏向量计算成本高
一个好的解决方案是引入 词嵌入(Word Embeddings)。核心思想是将每个词映射到低维稠密向量空间。
上图是对比情况,上面是独热编码,16维稀疏向量,只有1个位置为1。
下面是嵌入表示,5维稠密向量,所有位置都有实数值。
嵌入矩阵 EEE
本质上是一个查找表。
- 维度:m×Dm \times Dm×D,其中:
- mmm:嵌入维度(如32)
- DDD:词汇表大小(10,000)
- 作用:将独热编码的单词索引转换为稠密向量
- 计算:Xℓ=E⋅one-hot(wordℓ)X_\ell = E \cdot \text{one-hot}(\text{word}_\ell)Xℓ=E⋅one-hot(wordℓ)
得到嵌入矩阵
一般有两种:
- 预训练嵌入
- 在嵌入层中插入一个预先计算好的矩阵 EEE,这个过程被称为权重冻结 (weight freezing)。
- Word2Vec:通过预测上下文词学习嵌入
- GloVe:基于词共现矩阵的全局向量
- 优势:
- 利用大规模无标注文本
- 捕捉丰富的语义关系
- 减少训练时间
- 学习嵌入
- EEE 被称为一个嵌入层 (embedding layer)
- 端到端学习:在分类任务中同时学习嵌入
- 优势:
- 任务特定的语义表示
- 可能获得更好的任务性能
序列处理流程
数据预处理
首先要把复杂的语料库转变为由 nnn 个独立的长度为 LLL 的序列。
短于 LLL 的文档会在前面用零进行填充,长的截取最后 LLL 个词。
RNN 处理
训练语料库由 nnn 个独立的长度为 LLL 的序列组成。
每个序列创建一个并行的隐藏激活向量序列 Aℓ,ℓ=1,…,LA_\ell, \ell = 1, \dots, LAℓ,ℓ=1,…,L。AℓA_\ellAℓ 被输入到输出层以产生演进的预测 OℓO_\ellOℓ,使用最终值 OLO_LOL 来预测响应变量。
性能结果
如果有个 KKK 隐藏单元,那么共享的权重矩阵 WWW 有 K×(m+1)K \times (m+1)K×(m+1) 个参数,矩阵 UUU 有 K×KK \times KK×K 个参数,在这个例子中,大概有32w个参数。
最终测试的准确率为 76%,效果甚至不如词袋模型(88%)。
原因在于长距离依赖难以捕捉,有一个改进的方法为长短期记忆 (Long Short-Term Memory, LSTM),它维持两轨隐藏层激活,这样在计算激活 AℓA_\ellAℓ 时,它会同时接收来自时间上更久远和更近的隐藏单元的输入——这被称为 LSTM RNN。对于长序列,这种 LSTM 结构克服了早期信号在通过链式传播到最终激活向量 ALA_LAL 时被冲淡的问题。
但LSTM训练很慢,因为序列处理无法正则化。
时间序列预测
时间序列预测的核心挑战在于如何有效利用历史数据的模式来预测未来的值,同时处理序列的自相关性和潜在的非线性关系。
书里举了这个大家都特别喜欢的股市分析,红线左侧是训练数据,右侧是测试数据。
一个观测值由第 ttt 天的测量值 (vt,rt,zt)(v_t, r_t, z_t)(vt,rt,zt) 组成,在例子中即 log_volume
, DJ_return
和 log_volatility
的值。
可以发现,上面三个值日复一日的观测值并非相互独立。这些序列表现出自相关 (auto-correlation)。
上图是log_volume
的自相关函数。可以看到,时间上相近的值有相当强的相关性。即使滞后20天,自相关仍达0.2以上
RNN 预测器
我们希望根据过去的值 vt−1,vt−2,…v_{t-1}, v_{t-2}, \dotsvt−1,vt−2,… 来预测值 vtv_tvt,并且也利用其他序列的过去值 rt−1,rt−2,…r_{t-1}, r_{t-2}, \dotsrt−1,rt−2,… 和 zt−1,zt−2,…z_{t-1}, z_{t-2}, \dotszt−1,zt−2,…。相比与以前的数据,这个数据有如下问题:
- 只有一个数据序列,而不是 25,000 个。
- 有一整个目标序列 vtv_tvt,并且输入包含了这个序列的过去值。
解决思路是从中提取许多具有预定义长度 LLL(在此上下文中称为滞后 (lag))的短的输入序列“迷你序列” X={X1,X2,…,XL}X=\{X_1, X_2, \dots, X_L\}X={X1,X2,…,XL} 和一个对应的目标 YYY。它们的形式如下:
X1=(vt−Lrt−Lzt−L),X2=(vt−L+1rt−L+1zt−L+1),⋯ ,XL=(vt−1rt−1zt−1), and Y=vt X_1 = \begin{pmatrix} v_{t-L} \\ r_{t-L} \\ z_{t-L} \end{pmatrix}, X_2 = \begin{pmatrix} v_{t-L+1} \\ r_{t-L+1} \\ z_{t-L+1} \end{pmatrix}, \cdots, X_L = \begin{pmatrix} v_{t-1} \\ r_{t-1} \\ z_{t-1} \end{pmatrix}, \text{ and } Y=v_t X1=
vt−Lrt−Lzt−L
,X2=
vt−L+1rt−L+1zt−L+1
,⋯,XL=
vt−1rt−1zt−1
, and Y=vt
目标 YYY 是在单个时间点 ttt 的 log_volume
值 vtv_tvt,输入序列 XXX 是由从第 t−Lt-Lt−L 天、第 t−L+1t-L+1t−L+1 天,直到第 t−1t-1t−1 天的三个测量值 log_volume
、DJ_return
和 log_volatility
组成的 3 维向量序列 {Xℓ}ℓ=1L\{X_\ell\}_{\ell=1}^L{Xℓ}ℓ=1L。
上图是预测结果,黑色是真实的,橙色是预测的。R2R^2R2约 0.42,总体还不错。
自回归 (Autoregression)
只考虑响应序列 vtv_tvt 本身,并为最小二乘回归构建一个响应向量 yyy 和一个预测变量矩阵 MMM,如下所示:
y=(vL+1vL+2vL+3⋮vT)M=(1vLvL−1⋯v11vL+1vL⋯v21vL+2vL+1⋯v3⋮⋮⋮⋱⋮1vT−1vT−2⋯vT−L). y = \begin{pmatrix} v_{L+1} \\ v_{L+2} \\ v_{L+3} \\ \vdots \\ v_T \end{pmatrix} \quad M = \begin{pmatrix} 1 & v_L & v_{L-1} & \cdots & v_1 \\ 1 & v_{L+1} & v_L & \cdots & v_2 \\ 1 & v_{L+2} & v_{L+1} & \cdots & v_3 \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & v_{T-1} & v_{T-2} & \cdots & v_{T-L} \end{pmatrix}. y=
vL+1vL+2vL+3⋮vT
M=
111⋮1vLvL+1vL+2⋮vT−1vL−1vLvL+1⋮vT−2⋯⋯⋯⋱⋯v1v2v3⋮vT−L
.
对 yyy 在 MMM 上进行回归相当于拟合模型:
v^t=β^0+β^1vt−1+β^2vt−2+⋯+β^Lvt−L \hat{v}_t = \hat{\beta}_0 + \hat{\beta}_1 v_{t-1} + \hat{\beta}_2 v_{t-2} + \dots + \hat{\beta}_L v_{t-L} v^t=β^0+β^1vt−1+β^2vt−2+⋯+β^Lvt−L
这被称为 LLL 阶自回归模型,或简称为 AR(L)。在上面的例子使用之后 R2=0.41R^2=0.41R2=0.41,差不多。
如果将将滞后变量输入前馈神经网络,那么就是非线性AR模型。
RNN 总结
RNN 同样能单开一本书。核心价值在于能够捕捉序列中的时间依赖关系和上下文信息。
RNN同样有很多变体,比如
- 将序列视为"一维图像"来处理,就是一维卷积神经网络。
- 堆叠多个 RNN 层,扩展为深度RNN。
- 增加前向RNN + 后向RNN,扩展为双向RNN
在语言翻译中RNN也有应用,目标也是一个单词序列,其语言与输入序列的语言不同。主流为Seq2Seq 学习,即编码器将源语言序列编码为语义向量, 解码器基于语义向量生成目标语言序列。
当然,现在 RNN 有一个更厉害的替代架构: Transformer。
这个技术在书编写的时候还没出现,很可惜。
何时使用深度学习
书里讲了一堆,总结就几点。
“如无必要,勿增实体”。
适合使用场景
- 大规模数据
- 图像分类:数百万张标注图像
- 自然语言处理:数十亿单词的语料库
- 推荐系统:数千万用户行为数据
- 复杂模式识别
- 图像中的物体检测
- 语音识别和合成
- 自然语言理解
- 端到端学习
- 从原始数据直接学习,无需特征工程
- 自动学习特征表示
- 可解释性要求低
- 用户不关心决策过程,只关心结果正确性
- 如:垃圾邮件分类、图像滤镜等
局限性
- 黑箱问题
- 可解释性差:难以理解神经网络如何做出决策
- 调试困难:问题诊断和模型改进具有挑战性
- 业务接受度:在需要解释性的场景中接受度低
- 数据量要求
- 小数据问题:在263个样本的数据集上表现不佳
- 过拟合风险:参数数量远超样本数量
- 训练不稳定:需要仔细的正则化和调参
- 计算成本
- 训练时间:神经网络训练耗时更长
- 调参复杂度:需要尝试多种架构和超参数
- 部署成本:推理计算成本高于线性模型
拟合神经网络 (Fitting a Neural Network)
直到这一节,本书第一次涉及到了非常重要的梯度。
考虑最开始提到的模型:参数是 β=(β0,β1,…,βK)\beta = (\beta_0, \beta_1, \dots, \beta_K)β=(β0,β1,…,βK),以及每个 wk=(wk0,wk1,…,wkp)w_k = (w_{k0}, w_{k1}, \dots, w_{kp})wk=(wk0,wk1,…,wkp),k=1,…,Kk=1, \dots, Kk=1,…,K。给定观测值 (xi,yi),i=1,…,n(x_i, y_i), i=1, \dots, n(xi,yi),i=1,…,n,
通过解决一个非线性最小二乘问题来拟合该模型:
minimize{βk}k=1K,{wk}k=1K12∑i=1n(yi−f(xi))2 \underset{\{\beta_k\}_{k=1}^K, \{w_k\}_{k=1}^K}{\text{minimize}} \frac{1}{2} \sum_{i=1}^n (y_i - f(x_i))^2 {βk}k=1K,{wk}k=1Kminimize21i=1∑n(yi−f(xi))2
其中
f(xi)=β0+∑k=1Kβkg(wk0+∑j=1pwkjxij) f(x_i) = \beta_0 + \sum_{k=1}^K \beta_k g\left( w_{k0} + \sum_{j=1}^p w_{kj}x_{ij} \right) f(xi)=β0+k=1∑Kβkg(wk0+j=1∑pwkjxij)
由于参数的嵌套排列和隐藏单元的对称性,这个问题在参数上是非凸 (nonconvex) 的,因此存在多个解。
上图就是“非凸”的一个例子,单变量 θ\thetaθ 有两个解:一个是局部最小值 (local minimum),另一个是全局最小值 (global minimum)。
神经网络很容易落入局部最小值,找不到全局最小值。
为了防止这个问题,有两种通用策略:
- 缓慢学习 (Slow Learning):使用梯度下降 (gradient descent) 法,以一种较为缓慢的迭代方式进行模型拟合。当检测到过拟合时,拟合过程便停止。
- 正则化 (Regularization):对参数施加惩罚,通常是如 Lasso 或岭回归。
假设所有参数表示在一个长向量 θ\thetaθ 中。目标函数就可以重写为:
R(θ)=12∑i=1n(yi−fθ(xi))2 R(\theta) = \frac{1}{2} \sum_{i=1}^n (y_i - f_\theta(x_i))^2 R(θ)=21i=1∑n(yi−fθ(xi))2
找这个 θ\thetaθ 就可以梯度下降。
梯度下降的思路很简单,就跟上图一样,小步迭代,避免跳过好的解。
- 对 θ\thetaθ 中所有参数给出一个初始猜测值 θ0\theta_0θ0,并设 t=0t=0t=0。
- 迭代直至目标函数 (10.25) 不再减小:
(a) 找到一个向量 δt\delta_tδt 作为 θt\theta_tθt 的一个微小变化,使得 θt+1=θt+δt\theta_{t+1} = \theta_t + \delta_tθt+1=θt+δt 能够减小目标函数;即 R(θt+1)<R(θt)R(\theta_{t+1}) < R(\theta_t)R(θt+1)<R(θt)。
(b) 更新 t←t+1t \leftarrow t+1t←t+1。
反向传播 (Backpropagation)
该如何找到移动的方向以减小目标函数 R(θ)R(\theta)R(θ) 呢?方向导数。
R(θ)R(\theta)R(θ) 在某个当前值 θ=θm\theta = \theta_mθ=θm 处的梯度 (gradient),是该点的偏导数向量: ∇R(θm)=∂R(θ)∂θ∣θ=θm \nabla R(\theta_m) = \left. \frac{\partial R(\theta)}{\partial \theta} \right|_{\theta=\theta_m}∇R(θm)=∂θ∂R(θ)
θ=θm
下标 θ=θm\theta = \theta_mθ=θm 表示在计算出导数向量后,我们在当前的猜测值 θm\theta_mθm 处对其进行求值。
梯度给出了在 θ\thetaθ 空间中 R(θ)R(\theta)R(θ) 增长最快的方向。梯度下降的思想是朝相反的方向移动一小步。
θm+1←θm−γ∇R(θm). \theta_{m+1} \leftarrow \theta_m - \gamma \nabla R(\theta_m). θm+1←θm−γ∇R(θm).
如果梯度向量为零,那么我们可能已经到达了目标函数的一个最小值。
出于微分的链式法则 (chain rule),公式的计算很简单。
由于 R(θ)=∑i=1nRi(θ)=12∑i=1n(yi−fθ(xi))2R(\theta) = \sum_{i=1}^n R_i(\theta) = \frac{1}{2} \sum_{i=1}^n (y_i - f_\theta(x_i))^2R(θ)=∑i=1nRi(θ)=21∑i=1n(yi−fθ(xi))2 是一个和,它的梯度也是对 nnn 个观测值的和,所以先只考察其中一项:
Ri(θ)=12(yi−β0−∑k=1Kβkg(wk0+∑j=1pwkjxij))2. R_i(\theta) = \frac{1}{2} \left( y_i - \beta_0 - \sum_{k=1}^K \beta_k g\left( w_{k0} + \sum_{j=1}^p w_{kj}x_{ij} \right) \right)^2. Ri(θ)=21(yi−β0−k=1∑Kβkg(wk0+j=1∑pwkjxij))2.
为了简化接下来的表达式,记 zik=wk0+∑j=1pwkjxijz_{ik} = w_{k0} + \sum_{j=1}^p w_{kj}x_{ij}zik=wk0+∑j=1pwkjxij。
对输出层权重 βk\beta_kβk 求导:
∂Ri(θ)∂βk=∂Ri(θ)∂fθ(xi)⋅∂fθ(xi)∂βk=−(yi−fθ(xi))⋅g(zik) \frac{\partial R_i(\theta)}{\partial \beta_k} = \frac{\partial R_i(\theta)}{\partial f_\theta(x_i)} \cdot \frac{\partial f_\theta(x_i)}{\partial \beta_k} = -(y_i - f_\theta(x_i)) \cdot g(z_{ik}) ∂βk∂Ri(θ)=∂fθ(xi)∂Ri(θ)⋅∂βk∂fθ(xi)=−(yi−fθ(xi))⋅g(zik)
对隐藏层权重 wkjw_{kj}wkj 求导:
∂Ri(θ)∂wkj=∂Ri(θ)∂fθ(xi)⋅∂fθ(xi)∂g(zik)⋅∂g(zik)∂zik⋅∂zik∂wkj=−(yi−fθ(xi))⋅βk⋅g′(zik)⋅xij. \frac{\partial R_i(\theta)}{\partial w_{kj}} = \frac{\partial R_i(\theta)}{\partial f_\theta(x_i)} \cdot \frac{\partial f_\theta(x_i)}{\partial g(z_{ik})} \cdot \frac{\partial g(z_{ik})}{\partial z_{ik}} \cdot \frac{\partial z_{ik}}{\partial w_{kj}} = -(y_i - f_\theta(x_i)) \cdot \beta_k \cdot g'(z_{ik}) \cdot x_{ij}. ∂wkj∂Ri(θ)=∂fθ(xi)∂Ri(θ)⋅∂g(zik)∂fθ(xi)⋅∂zik∂g(zik)⋅∂wkj∂zik=−(yi−fθ(xi))⋅βk⋅g′(zik)⋅xij.
这两个表达式都包含了残差 yi−fθ(xi)y_i - f_\theta(x_i)yi−fθ(xi)。
微分的这一过程通过链式法则将一部分残差分配给每个参数——在神经网络文献中,这一过程被称为反向传播 (backpropagation)。
正则化与随机梯度下降 (Regularization and Stochastic Gradient Descent)
梯度下降很慢。当规模很大的时候,很明显不可能等着他慢点”下山“。
当 nnn 很大时,我们不必在每次计算梯度步长时都对所有 nnn 个观测值进行求和,而是可以对它们进行抽样,每次只使用一小部分或一个小批量 (minibatch)。这个过程被称为随机梯度下降 (stochastic gradient descent, SGD)。
上图是 MNIST 案例的训练状态,用了SGD, 30 个轮次就很稳定了。
SGD 自然地实施了其自身的一种近似二次正则化的形式。
正则化技术也是个方法,一般为岭正则化,即目标函数增加一个惩罚项:
R(θ;λ)=−∑i=1n∑m=09yimlog(fm(xi))+λ2∑jθj2. R(\theta; \lambda) = - \sum_{i=1}^n \sum_{m=0}^9 y_{im} \log(f_m(x_i)) + \frac{\lambda}{2} \sum_j \theta_j^2. R(θ;λ)=−i=1∑nm=0∑9yimlog(fm(xi))+2λj∑θj2.
当然,一定轮次之后停止训练的早停 (early stopping) 也是一个好办法。
Dropout 学习
Dropout 是一种正则化计数。他的思想是在训练过程中随机"关闭"一部分神经元,强制网络学习更加鲁棒和冗余的特征表示。
上图左图是传统全连接网络,右边是 Dropout 网络。
可以看见右图中部分神经元变为灰色,在这里是“休眠”
此时网络结构动态变化。
在实践中,dropout 是通过将“被丢弃”单元的激活值随机设置为零来实现的,同时保持网络架构的完整性。
网络调优 (Network Tuning)
土话就是”炼丹“。
网络调优的本质是:通过系统化的实验和验证,找到在不过度拟合的情况下能够最好地捕捉数据模式的网络配置。
选择有很多,一般是:
- 隐藏层的数量,以及每层的单元数。 现代的观点是,每个隐藏层的单元数可以很大,而过拟合可以通过各种形式的正则化来控制。
- 正则化调节参数。 这些参数包括 dropout 率 π\piπ 以及 lasso 和岭回归正则化的强度,并且通常在每一层都单独设置。
- 随机梯度下降的细节。 这些包括批量大小、轮次数量,以及如果使用的话,数据增强的细节。
插值与双重下降 (Interpolation and Double Descent)
再次回到偏差-方差权衡 (bias-variance trade-off)。这一权衡表明,就测试集误差而言,统计学习方法在模型复杂度处于中等水平时往往表现最佳。
偏差-方差权衡的一个推论是,插值 (interpolate) 训练数据——即获得零训练误差——通常不是一个好主意,因为这往往会导致非常高的测试误差。
实践表明,一个对训练数据进行插值的统计学习方法可能表现得很好——或者至少,比一个复杂度稍低但未完全插值数据的模型要好。这种现象被称为双重下降 (double descent)
上面就是双重下降的例子。
训练误差曲线:
- d≤20:逐渐下降至零,
- d≥20:保持为零
测试误差曲线:
- 经典下降:d<20,偏差减少主导
- 插值峰值:d=20,方差急剧增大
- 现代下降:d>20,最小范数解降低方差
- 最终上升:d很大时,过度平滑导致偏差
上图也是自由度,黑线是真实函数,橙色是拟合函数。
- d=8(经典区域)
- 适度拟合:捕捉主要趋势但不过度波动
- 训练误差:非零但较小
- 测试误差:相对较低
- d=20(插值阈值)
- 完美插值:训练误差为零
- 剧烈波动:在数据点间大幅震荡
- 测试误差:达到峰值
- d=42(现代区域)
- 依然插值:训练误差为零
- 但更平滑:最小范数解选择了"温和"的插值方式
- 测试误差:比d=20时显著改善
- d=80(高度过参数化)
- 类似表现:与d=42几乎相同
- 稳定性:进一步增加参数变化不大
需要注意一点,双重下降不违背偏差-方差权衡。
实际应用中通常不希望依赖于这种行为。
更多推荐
所有评论(0)