目标检测、人脸识别、循环序列模型。

This commit is contained in:
yinkanglong_lab
2020-10-31 17:26:34 +08:00
parent 795c3f4089
commit 3c0ce3d926
4 changed files with 237 additions and 213 deletions

View File

@@ -42,108 +42,123 @@ $$
* 除了使用平方误差,也可以使用逻辑回归损失函数,类标签 $c_1,c_2,c_3$ 也可以通过 softmax 输出。相比较而言,平方误差已经能够取得比较好的效果。
## 特征点检测
## 2 特征点检测
神经网络可以像标识目标的中心点位置那样,通过输出图片上的特征点,来实现对目标特征的识别。在标签中,这些特征点以多个二维坐标的形式表示。
* 神经网络可以像标识目标的中心点位置那样,通过输出图片上的特征点,来实现对目标特征的识别。在标签中,这些特征点以多个二维坐标的形式表示。
通过检测人脸特征点可以进行情绪分类与判断,或者应用于 AR 领域等等。也可以透过检测姿态特征点来进行人体姿态检测。
* 通过检测人脸特征点可以进行情绪分类与判断,或者应用于 AR 领域等等。也可以透过检测姿态特征点来进行人体姿态检测。
## 目标检测
* 可以实现人的动作识别。标记动作上的特征点。
想要实现目标检测,可以采用**基于滑动窗口的目标检测Sliding Windows Detection**算法。该算法的步骤如下:
## 3 目标检测
1. 训练集上搜集相应的各种目标图片和非目标图片,样本图片要求尺寸较小,相应目标居于图片中心位置并基本占据整张图片。
2. 使用训练集构建 CNN 模型,使得模型有较高的识别率。
3. 选择大小适宜的窗口与合适的固定步幅,对测试图片进行从左到右、从上倒下的滑动遍历。每个窗口区域使用已经训练好的 CNN 模型进行识别判断。
4. 可以选择更大的窗口,然后重复第三步的操作。
* 想要实现目标检测,可以采用**基于滑动窗口的目标检测Sliding Windows Detection**算法。该算法的步骤如下:
![Sliding-windows-detection](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/Sliding-windows-detection.png)
1. 训练集上搜集相应的各种目标图片和非目标图片,样本图片要求尺寸较小,相应目标居于图片中心位置并基本占据整张图片。
2. 使用训练集构建 CNN 模型,使得模型有较高的识别率。
3. 选择大小适宜的窗口与合适的固定步幅,对测试图片进行从左到右、从上倒下的滑动遍历。每个窗口区域使用已经训练好的 CNN 模型进行识别判断。
4. 可以选择更大的窗口,然后重复第三步的操作。
滑动窗口目标检测的**优点**是原理简单,且不需要人为选定目标区域;**缺点**是需要人为直观设定滑动窗口的大小和步幅。滑动窗口过小或过大,步幅过大均会降低目标检测的正确率。另外,每次滑动都要进行一次 CNN 网络计算,如果滑动窗口和步幅较小,计算成本往往很大。
![Sliding-windows-detection](Sliding-windows-detection.png)
所以,滑动窗口目标检测算法虽然简单,但是性能不佳,效率较低
* 滑动窗口目标检测的**优点**是原理简单,且不需要人为选定目标区域;**缺点**是需要人为直观设定滑动窗口的大小和步幅。滑动窗口过小或过大,步幅过大均会降低目标检测的正确率。另外,每次滑动都要进行一次 CNN 网络计算,如果滑动窗口和步幅较小,计算成本往往很大
## 基于卷积的滑动窗口实现
* 所以,滑动窗口目标检测算法虽然简单,但是性能不佳,效率较低。
相比从较大图片多次截取,在卷积层上应用滑动窗口目标检测算法可以提高运行速度。所要做的仅是将全连接层换成卷积层,即使用与上一层尺寸一致的滤波器进行卷积运算。
## 4 基于卷积的滑动窗口实现
![Convolution-implementation-of-sliding-windows](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/Convolution-implementation-of-sliding-windows.png)
* 相比从较大图片多次截取,在卷积层上应用滑动窗口目标检测算法可以提高运行速度。*所要做的仅是将全连接层换成卷积层,即使用与上一层尺寸一致的滤波器进行卷积运算。*(不太理解这句话)
* 为什么使用滑动窗口来实现?因为截取小范围图片进行卷积运算,包含了图像上很多重复的区域,导致重复进行相同的卷积运算。
* 对整个图片进行卷积运算,在全连接层,实现滑动窗口。即某个窗口内部的全连接,而不是整个图片的全连接,就能一次性实现所有的窗口的运算。运算速度极快。
如图,对于 16x16x3 的图片,步长为 2CNN 网络得到的输出层为 2x2x4。其中2x2 表示共有 4 个窗口结果。对于更复杂的 28x28x3 的图片,得到的输出层为 8x8x4共 64 个窗口结果。最大池化层的宽高和步长相等。
运行速度提高的原理:在滑动窗口的过程中,需要重复进行 CNN 正向计算。因此,不需要将输入图片分割成多个子集,分别执行向前传播,而是将它们作为一张图片输入给卷积网络进行一次 CNN 正向计算。这样,公共区域的计算可以共享,以降低运算成本。
![Convolution-implementation-of-sliding-windows](Convolution-implementation-of-sliding-windows.png)
相关论文:[Sermanet et al., 2014. OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks](https://arxiv.org/pdf/1312.6229.pdf)
* 如图,对于 16x16x3 的图片,步长为 2CNN 网络得到的输出层为 2x2x4。其中2x2 表示共有 4 个窗口结果。对于更复杂的 28x28x3 的图片,得到的输出层为 8x8x4共 64 个窗口结果。最大池化层的宽高和步长相等。
## 边框预测
* 运行速度提高的原理:在滑动窗口的过程中,需要重复进行 CNN 正向计算。因此,不需要将输入图片分割成多个子集,分别执行向前传播,而是将它们作为一张图片输入给卷积网络进行一次 CNN 正向计算。这样,公共区域的计算可以共享,以降低运算成本。
在上述算法中,边框的位置可能无法完美覆盖目标,或者大小不合适,或者最准确的边框并非正方形,而是长方形。
> 相关论文:[Sermanet et al., 2014. OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks](https://arxiv.org/pdf/1312.6229.pdf)
**YOLOYou Only Look Once算法**可以用于得到更精确的边框。YOLO 算法将原始图片划分为 n×n 网格,并将[目标定位](http://kyonhuang.top/Andrew-Ng-Deep-Learning-notes/#/Convolutional_Neural_Networks/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B?id=%e7%9b%ae%e6%a0%87%e5%ae%9a%e4%bd%8d)一节中提到的图像分类和目标定位算法,逐一应用在每个网格中,每个网格都有标签如:
## 5 边框预测
* 在上述算法中,边框的位置可能无法完美覆盖目标,或者大小不合适,或者最准确的边框并非正方形,而是长方形。
* **YOLOYou Only Look Once算法**可以用于得到更精确的边框。YOLO 算法将原始图片划分为 n×n 网格,并将[目标定位](http://kyonhuang.top/Andrew-Ng-Deep-Learning-notes/#/Convolutional_Neural_Networks/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B?id=%e7%9b%ae%e6%a0%87%e5%ae%9a%e4%bd%8d)一节中提到的图像分类和目标定位算法,逐一应用在每个网格中,每个网格都有标签如:
$$\left[\begin{matrix}P_c\\\ b_x\\\ b_y\\\ b_h\\\ b_w\\\ c_1\\\ c_2\\\ c_3\end{matrix}\right]$$
若某个目标的中点落在某个网格,则该网格负责检测该对象。
* 若某个目标的中点落在某个网格,则该网格负责检测该对象。
![Bounding-Box-Predictions](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/Bounding-Box-Predictions.png)
![Bounding-Box-Predictions](Bounding-Box-Predictions.png)
如上面的示例中,如果将输入的图片划分为 3×3 的网格、需要检测的目标有 3 类,则每一网格部分图片的标签会是一个 8 维的列矩阵,最终输出的就是大小为 3×3×8 的结果。要得到这个结果,就要训练一个输入大小为 100×100×3输出大小为 3×3×8 的 CNN。在实践中可能使用更为精细的 19×19 网格,则两个目标的中点在同一个网格的概率更小。
* 如上面的示例中,如果将输入的图片划分为 3×3 的网格、需要检测的目标有 3 类,则每一网格部分图片的标签会是一个 8 维的列矩阵,最终输出的就是大小为 3×3×8 的结果。要得到这个结果,就要训练一个输入大小为 100×100×3输出大小为 3×3×8 的 CNN。在实践中可能使用更为精细的 19×19 网格,则两个目标的中点在同一个网格的概率更小。
YOLO 算法的优点:
* YOLO 算法的优点:
1. 和图像分类和目标定位算法类似,显式输出边框坐标和大小,不会受到滑窗分类器的步长大小限制。
2. 仍然只进行一次 CNN 正向计算,效率很高,甚至可以达到实时识别。
1. 和图像分类和目标定位算法类似,显式输出边框坐标和大小,不会受到滑窗分类器的步长大小限制
2. 仍然只进行一次 CNN 正向计算,效率很高,甚至可以达到实时识别。
* 如何编码边框 $b_x$、$b_y$、$b_h$、$b_w$YOLO 算法设 $b_x$、$b_y$、$b_h$、$b_w$ 的值是相对于网格长的比例。则 $b_x$、$b_y$ 在 0 到 1 之间,而 $b_h$、$b_w$ 可以大于 1。当然也有其他参数化的形式且效果可能更好。这里只是给出一个通用的表示方法
如何编码边框 $b_x$、$b_y$、$b_h$、$b_w$YOLO 算法设 $b_x$、$b_y$、$b_h$、$b_w$ 的值是相对于网格长的比例。则 $b_x$、$b_y$ 在 0 到 1 之间,而 $b_h$、$b_w$ 可以大于 1。当然也有其他参数化的形式且效果可能更好。这里只是给出一个通用的表示方法
> 相关论文:[Redmon et al., 2015. You Only Look Once: Unified, Real-Time Object Detection](https://arxiv.org/pdf/1506.02640.pdf)。Ng 认为该论文较难理解
相关论文:[Redmon et al., 2015. You Only Look Once: Unified, Real-Time Object Detection](https://arxiv.org/pdf/1506.02640.pdf)。Ng 认为该论文较难理解。
## 6 交并比
## 交互比
**交互比IoU, Intersection Over Union**函数用于评价对象检测算法它计算预测边框和实际边框交集I与并集U之比
* **交并比IoU, Intersection Over Union** 函数用于评价对象检测算法它计算预测边框和实际边框交集I与并集U之比
$$IoU = \frac{I}{U}$$
IoU 的值在 01 之间,且越接近 1 表示目标的定位越准确。IoU 大于等于 0.5 时,一般可以认为预测边框是正确的,当然也可以更加严格地要求一个更高的阈值。
* IoU 的值在 01 之间,且越接近 1 表示目标的定位越准确。IoU 大于等于 0.5 时,一般可以认为预测边框是正确的,当然也可以更加严格地要求一个更高的阈值。
## 非极大值抑制
## 7 非极大值抑制
YOLO 算法中,可能有很多网格检测到同一目标。**非极大值抑制Non-max Suppression**会通过清理检测结果,找到每个目标中点所位于的网格,确保算法对每个目标只检测一次。
* YOLO 算法中,可能有很多网格检测到同一目标。 **非极大值抑制Non-max Suppression** 会通过清理检测结果,找到每个目标中点所位于的网格,确保算法对每个目标只检测一次。
进行非极大值抑制的步骤如下:
* 进行非极大值抑制的步骤如下:
1. 将包含目标中心坐标的可信度 $P_c$ 小于阈值(例如 0.6)的网格丢弃;
2. 选取拥有最大 $P_c$ 的网格;
3. 分别计算该网格和其他所有网格的 IoU将 IoU 超过预设阈值的网格丢弃;
4. 重复第 2~3 步,直到不存在未处理的网格。
1. 将包含目标中心坐标的可信度 $P_c$ 小于阈值(例如 0.6)的网格丢弃;
2. 选取拥有最大 $P_c$ 的网格;
3. 分别计算该网格和其他所有网格的 IoU将 IoU 超过预设阈值的网格丢弃;
4. 重复第 2~3 步,直到不存在未处理的网格。
上述步骤适用于单类别目标检测。进行多个类别目标检测时,对于每个类别,应该单独做一次非极大值抑制。
* 上述步骤适用于单类别目标检测。进行多个类别目标检测时,对于每个类别,应该单独做一次非极大值抑制。
## Anchor Boxes
## 8 Anchor Boxes
到目前为止,我们讨论的情况都是一个网格只检测一个对象。如果要将算法运用在多目标检测上,需要用到 Anchor Boxes。一个网格的标签中将包含多个 Anchor Box相当于存在多个用以标识不同目标的边框。
* 到目前为止,我们讨论的情况都是一个网格只检测一个对象。如果要将算法运用在多目标检测上,需要用到 Anchor Boxes。一个网格的标签中将包含多个 Anchor Box相当于存在多个用以标识不同目标的边框。
![Overlapping-objects](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/Overlapping-objects.png)
![Overlapping-objects](Overlapping-objects.png)
在上图示例中,我们希望同时检测人和汽车。因此,每个网格的的标签中含有两个 Anchor Box。输出的标签结果大小从 3×3×8 变为 3×3×16。若两个 $P_c$ 都大于预设阈值,则说明检测到了两个目标。
* 在上图示例中,我们希望同时检测人和汽车。因此,每个网格的的标签中含有两个 Anchor Box。输出的标签结果大小从 3×3×8 变为 3×3×16。若两个 $P_c$ 都大于预设阈值,则说明检测到了两个目标。
在单目标检测中,图像中的目标被分配给了包含该目标中点的那个网格;引入 Anchor Box 进行多目标检测时,图像中的目标则被分配到了包含该目标中点的那个网格以及具有最高 IoU 值的该网格的 Anchor Box。
* 在单目标检测中,图像中的目标被分配给了包含该目标中点的那个网格;引入 Anchor Box 进行多目标检测时,图像中的目标则被分配到了包含该目标中点的那个网格以及具有最高 IoU 值的该网格的 Anchor Box。
Anchor Boxes 也有局限性,对于同一网格有三个及以上目标,或者两个目标的 Anchor Box 高度重合的情况处理不好。
* Anchor Boxes 也有局限性,对于同一网格有三个及以上目标,或者两个目标的 Anchor Box 高度重合的情况处理不好。
Anchor Box 的形状一般通过人工选取。高级一点的方法是用 k-means 将两类对象形状聚类,选择最具代表性的 Anchor Box。
* Anchor Box 的形状一般通过人工选取。高级一点的方法是用 k-means 将两类对象形状聚类,选择最具代表性的 Anchor Box。
如果对以上内容不是很理解在“3.9 YOLO 算法”一节中视频的第 5 分钟,有一个更为直观的示例。
* 如果对以上内容不是很理解在“3.9 YOLO 算法”一节中视频的第 5 分钟,有一个更为直观的示例。
## R-CNN
前面介绍的滑动窗口目标检测算法对一些明显没有目标的区域也进行了扫描,这降低了算法的运行效率。为了解决这个问题,**R-CNNRegion CNN带区域的 CNN**被提出。通过对输入图片运行**图像分割算法**,在不同的色块上找出**候选区域Region Proposal**,就只需要在这些区域上运行分类器。
## 9 YOLO算法
![R-CNN](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/R-CNN.png)
### YOLO算法的过程
R-CNN 的缺点是运行速度很慢,所以有一系列后续研究工作改进。例如 Fast R-CNN与基于卷积的滑动窗口实现相似但得到候选区域的聚类步骤依然很慢、Faster R-CNN使用卷积对图片进行分割。不过大多数时候还是比 YOLO 算法慢。
![](2020-10-31-11-53-59.png)
相关论文:
1. 如果有两个待检测的对象,那么对于每一个单元格,会有两个预测的边界框。
2. 舍弃可能性较低的预测。
3. 对于每一个待检测的对象,运行非最大值抑制(即去掉重叠的边界内,概率较小的预测)
## 10 R-CNN
* 前面介绍的滑动窗口目标检测算法对一些明显没有目标的区域也进行了扫描,这降低了算法的运行效率。为了解决这个问题,**R-CNNRegion CNN带区域的 CNN**被提出。通过对输入图片运行**图像分割算法**,在不同的色块上找出**候选区域Region Proposal**,就只需要在这些区域上运行分类器。
![R-CNN](R-CNN.png)
* R-CNN 的缺点是运行速度很慢,所以有一系列后续研究工作改进。例如 Fast R-CNN与基于卷积的滑动窗口实现相似但得到候选区域的聚类步骤依然很慢、Faster R-CNN使用卷积对图片进行分割。不过大多数时候还是比 YOLO 算法慢。
### 相关论文:
* R-CNN[Girshik et al., 2013. Rich feature hierarchies for accurate object detection and semantic segmentation](https://arxiv.org/pdf/1311.2524.pdf)
* Fast R-CNN[Girshik, 2015. Fast R-CNN](https://arxiv.org/pdf/1504.08083.pdf)

View File

@@ -1,168 +1,175 @@
<h1 align="center">特殊应用:人脸识别和神经风格转换</h1>
特殊应用:人脸识别和神经风格转换
## 人脸识别
## 1 人脸识别
**人脸验证Face Verification**和**人脸识别Face Recognition**的区别:
### 定义
* 人脸验证:一般指一个一对一问题,只需要验证输入的人脸图像是否与某个已知的身份信息对应;
* 人脸识别:一个更为复杂的一对多问题,需要验证输入的人脸图像是否与多个已知身份信息中的某一个匹配。
* **人脸验证Face Verification** 和 **人脸识别Face Recognition** 的区别:
一般来说,由于需要匹配的身份信息更多导致错误率增加,人脸识别比人脸验证更难一些。
* 人脸验证:一般指一个一对一问题,只需要验证输入的人脸图像是否与某个已知的身份信息对应;
* 人脸识别:一个更为复杂的一对多问题,需要验证输入的人脸图像是否与多个已知身份信息中的某一个匹配。
### One-Shot 学习
* 一般来说,由于需要匹配的身份信息更多导致错误率增加,人脸识别比人脸验证更难一些。
人脸识别所面临的一个挑战是要求系统只采集某人的一个面部样本,就能快速准确地识别出这个人,即只用一个训练样本来获得准确的预测结果。这被称为**One-Shot 学习**。
## 2 One-Shot 学习
有一种方法是假设数据库中存有 N 个人的身份信息,对于每张输入图像,用 Softmax 输出 N+1 种标签,分别对应每个人以及都不是。然而这种方法的实际效果很差,因为过小的训练集不足以训练出一个稳健的神经网络;并且如果有新的身份信息入库,需要重新训练神经网络,不够灵活
* 人脸识别所面临的一个挑战是要求系统只采集某人的一个面部样本,就能快速准确地识别出这个人,即只用一个训练样本来获得准确的预测结果。这被称为**One-Shot 学习**
因此,我们通过学习一个 Similarity 函数来实现 One-Shot 学习过程。Similarity 函数定义了输入的两幅图像的差异度,其公式如下:
* 有一种方法是假设数据库中存有 N 个人的身份信息,对于每张输入图像,用 Softmax 输出 N+1 种标签,分别对应每个人以及都不是。然而这种方法的实际效果很差,因为过小的训练集不足以训练出一个稳健的神经网络;并且如果有新的身份信息入库,需要重新训练神经网络,不够灵活。
* 因此,我们通过学习一个 Similarity 函数来实现 One-Shot 学习过程。Similarity 函数定义了输入的两幅图像的差异度,其公式如下:
$$Similarity = d(img1, img2)$$
可以设置一个超参数 $τ$ 作为阈值,作为判断两幅图片是否为同一个人的依据。
* 可以设置一个超参数 $τ$ 作为阈值,作为判断两幅图片是否为同一个人的依据。
### Siamese 网络
## 3 Siamese 网络
实现 Similarity 函数的一种方式是使用**Siamese 网络**,它是一种对两个不同输入运行相同的卷积网络,然后对它们的结果进行比较的神经网络。
* 实现 Similarity 函数的一种方式是使用**Siamese 网络**,它是一种对两个不同输入运行相同的卷积网络,然后对它们的结果进行比较的神经网络。
![Siamese](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/Siamese.png)
![Siamese](Siamese.png)
如上图示例,将图片 $x^{(1)}$、$x^{(2)}$ 分别输入两个相同的卷积网络中,经过全连接层后不再进行 Softmax而是得到特征向量 $f(x^{(1)})$、$f(x^{(2)})$。这时Similarity 函数就被定义为两个特征向量之差的 L2 范数:
* 如上图示例,将图片 $x^{(1)}$、$x^{(2)}$ 分别输入两个相同的卷积网络中,经过全连接层后不再进行 Softmax而是得到特征向量 $f(x^{(1)})$、$f(x^{(2)})$。这时Similarity 函数就被定义为两个特征向量之差的 L2 范数:
$$d(x^{(1)}, x^{(2)}) = ||f(x^{(1)}) - f(x^{(2)})||^2\_2$$
相关论文:[Taigman et al., 2014, DeepFace closing the gap to human level performance](http://www.cs.wayne.edu/~mdong/taigman_cvpr14.pdf)
> 相关论文:[Taigman et al., 2014, DeepFace closing the gap to human level performance](http://www.cs.wayne.edu/~mdong/taigman_cvpr14.pdf)
### Triplet 损失
## 4 人脸识别与Triplet 损失
**Triplet 损失函数**用于训练出合适的参数以获得高质量的人脸图像编码。“Triplet”一词来源于训练这个神经网络需要大量包含 Anchor靶目标、Positive正例、Negative反例的图片组其中 Anchor 和 Positive 需要是同一个人的人脸图像。
* **Triplet 损失函数** 用于训练出合适的参数以获得高质量的人脸图像编码。“Triplet”一词来源于训练这个神经网络需要大量包含 Anchor靶目标、Positive正例、Negative反例的图片组其中 Anchor 和 Positive 需要是同一个人的人脸图像。
![Training-set-using-triplet-loss](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/Training-set-using-triplet-loss.png)
![Training-set-using-triplet-loss](Training-set-using-triplet-loss.png)
对于这三张图片,应该有:
* 对于这三张图片,应该有:
$$||f(A) - f(P)||^2\_2 + \alpha \le ||f(A) - f(N)||^2\_2$$
其中,$\alpha$ 被称为**间隔margin**,用于确保 $f()$ 不会总是输出零向量(或者一个恒定的值)。
* 其中,$\alpha$ 被称为**间隔margin**,用于确保 $f()$ 不会总是输出零向量(或者一个恒定的值)。
Triplet 损失函数的定义:
* Triplet 损失函数的定义:
$$L(A, P, N) = max(||f(A) - f(P)||^2\_2 - ||f(A) - f(N)||^2\_2 + \alpha, 0)$$
其中,因为 $||f(A) - f(P)||^2\_2 - ||f(A) - f(N)||^2\_2 + \alpha$ 的值需要小于等于 0因此取它和 0 的更大值。
* 其中,因为 $||f(A) - f(P)||^2\_2 - ||f(A) - f(N)||^2\_2 + \alpha$ 的值需要小于等于 0因此取它和 0 的更大值。
对于大小为 $m$ 的训练集,代价函数为:
* 对于大小为 $m$ 的训练集,代价函数为:
$$J = \sum^m\_{i=1}L(A^{(i)}, P^{(i)}, N^{(i)})$$
通过梯度下降最小化代价函数。
* 通过梯度下降最小化代价函数。
在选择训练样本时,随机选择容易使 Anchor 和 Positive 极为接近,而 Anchor 和 Negative 相差较大,以致训练出来的模型容易抓不到关键的区别。因此,最好的做法是人为增加 Anchor 和 Positive 的区别,缩小 Anchor 和 Negative 的区别,促使模型去学习不同人脸之间的关键差异。
* 在选择训练样本时,随机选择容易使 Anchor 和 Positive 极为接近,而 Anchor 和 Negative 相差较大,以致训练出来的模型容易抓不到关键的区别。因此,最好的做法是人为增加 Anchor 和 Positive 的区别,缩小 Anchor 和 Negative 的区别,促使模型去学习不同人脸之间的关键差异。
相关论文:[Schroff et al., 2015, FaceNet: A unified embedding for face recognition and clustering](https://arxiv.org/pdf/1503.03832.pdf)
> 相关论文:[Schroff et al., 2015, FaceNet: A unified embedding for face recognition and clustering](https://arxiv.org/pdf/1503.03832.pdf)
### 二分类结构
## 5 人脸验证与二分类结构
除了 Triplet 损失函数,二分类结构也可用于学习参数以解决人脸识别问题。其做法是输入一对图片,将两个 Siamese 网络产生的特征向量输入至同一个 Sigmoid 单元,输出 1 则表示是识别为同一人,输出 0 则表示识别为不同的人。
* 除了 Triplet 损失函数,二分类结构也可用于学习参数以解决人脸识别问题。其做法是输入一对图片,将两个 Siamese 网络产生的特征向量输入至同一个 Sigmoid 单元,输出 1 则表示是识别为同一人,输出 0 则表示识别为不同的人。
Sigmoid 单元对应的表达式为:
1. Sigmoid 单元对应的表达式为:
$$\hat y = \sigma (\sum^K\_{k=1}w\_k|f(x^{(i)})\_{k} - x^{(j)})\_{k}| + b)$$
其中,$w\_k$ 和 $b$ 都是通过梯度下降算法迭代训练得到的参数。上述计算表达式也可以用另一种表达式代替:
2. 其中,$w\_k$ 和 $b$ 都是通过梯度下降算法迭代训练得到的参数。上述计算表达式也可以用另一种表达式代替:
$$\hat y = \sigma (\sum^K\_{k=1}w\_k
\frac{(f(x^{(i)})\_k - f(x^{(j)})\_k)^2}{f(x^{(i)})\_k + f(x^{(j)})\_k} + b)$$
其中,$\frac{(f(x^{(i)})\_k - f(x^{(j)})\_k)^2}{f(x^{(i)})\_k + f(x^{(j)})\_k}$ 被称为 $\chi$ 方相似度。
3. 其中,$\frac{(f(x^{(i)})\_k - f(x^{(j)})\_k)^2}{f(x^{(i)})\_k + f(x^{(j)})\_k}$ 被称为 $\chi$ 方相似度。
无论是对于使用 Triplet 损失函数的网络,还是二分类结构,为了减少计算量,可以提前计算好编码输出 $f(x)$ 并保存。这样就不必存储原始图片,并且每次进行人脸识别时只需要计算测试图片的编码输出。
* 无论是对于使用 Triplet 损失函数的网络,还是二分类结构,为了减少计算量,可以提前计算好编码输出 $f(x)$ 并保存。这样就不必存储原始图片,并且每次进行人脸识别时只需要计算测试图片的编码输出。
## 神经风格迁移
## 6 什么是神经风格迁移
**神经风格迁移Neural style transfer**将参考风格图像的风格“迁移”到另外一张内容图像中,生成具有其特色的图像。
* **神经风格迁移Neural style transfer** 将参考风格图像的风格“迁移”到另外一张内容图像中,生成具有其特色的图像。
![Neural-style-transfer](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/Neural-style-transfer.png)
![Neural-style-transfer](Neural-style-transfer.png)
### 深度卷积网络在学什么?
## 7 深度卷积网络在学什么?
想要理解如何实现神经风格转换,首先要理解在输入图像数据后,一个深度卷积网络从中都学到了些什么。我们借助可视化来做到这一点。
* 想要理解如何实现神经风格转换,首先要理解在输入图像数据后,一个深度卷积网络从中都学到了些什么。我们借助可视化来做到这一点。
![Visualizing-deep-layers](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/Visualizing-deep-layers.png)
![Visualizing-deep-layers](Visualizing-deep-layers.png)
我们通过遍历所有的训练样本,找出使该层激活函数输出最大的 9 块图像区域。可以看出,浅层的隐藏层通常检测出的是原始图像的边缘、颜色、阴影等简单信息。随着层数的增加,隐藏单元能捕捉的区域更大,学习到的特征也由从边缘到纹理再到具体物体,变得更加复杂。
* 我们通过遍历所有的训练样本,找出使该层激活函数输出最大的 9 块图像区域。可以看出,浅层的隐藏层通常检测出的是原始图像的边缘、颜色、阴影等简单信息。随着层数的增加,隐藏单元能捕捉的区域更大,学习到的特征也由从边缘到纹理再到具体物体,变得更加复杂。
相关论文:[Zeiler and Fergus., 2013, Visualizing and understanding convolutional networks](https://arxiv.org/pdf/1311.2901.pdf)
* 简单来说,神经网络的的层数越多,学习的图片块越广泛。学习到的特征范围越大。图片快指某个隐藏层涉及到的图片的像素范围;激活值是指对当前神经元产生的激活值较大的图片块,表示该神经元学习到的图片特征。
### 代价函数
神经风格迁移生成图片 G 的代价函数如下:
> 相关论文:[Zeiler and Fergus., 2013, Visualizing and understanding convolutional networks](https://arxiv.org/pdf/1311.2901.pdf)
## 8 代价函数
* 神经风格迁移生成图片 G 的代价函数如下:
$$J(G) = \alpha \cdot J\_{content}(C, G) + \beta \cdot J\_{style}(S, G)$$
其中,$\alpha$、$\beta$ 是用于控制相似度比重的超参数。
* 其中,$\alpha$、$\beta$ 是用于控制相似度比重的超参数。
神经风格迁移的算法步骤如下:
* 神经风格迁移的算法步骤如下:
1. 随机生成图片 G 的所有像素点;
2. 使用梯度下降算法使代价函数最小化,以不断修正 G 的所有像素点。
1. 随机生成图片 G 的所有像素点;
2. 使用梯度下降算法使代价函数最小化,以不断修正 G 的所有像素点。
相关论文:[Gatys al., 2015. A neural algorithm of artistic style](https://arxiv.org/pdf/1508.06576v2.pdf)
> 相关论文:[Gatys al., 2015. A neural algorithm of artistic style](https://arxiv.org/pdf/1508.06576v2.pdf)
#### 内容代价函数
## 9 内容代价函数
上述代价函数包含一个内容代价部分和风格代价部分。我们先来讨论内容代价函数 $J\_{content}(C, G)$,它表示内容图片 C 和生成图片 G 之间的相似度。
* 上述代价函数包含一个内容代价部分和风格代价部分。我们先来讨论内容代价函数 $J\_{content}(C, G)$,它表示内容图片 C 和生成图片 G 之间的相似度。
$J\_{content}(C, G)$ 的计算过程如下:
* 使用一个预训练好的 CNN例如 VGG
* 选择一个隐藏层 $l$ 来计算内容代价。$l$ 太小则内容图片和生成图片像素级别相似,$l$ 太大则可能只有具体物体级别的相似。因此,$l$ 一般选一个中间层;
* 设 $a^{(C)[l]}$、$a^{(G)[l]}$ 为 C 和 G 在 $l$ 层的激活,则有:
1. 使用一个预训练好的 CNN例如 VGG
2. 选择一个隐藏层 $l$ 来计算内容代价。$l$ 太小则内容图片和生成图片像素级别相似,$l$ 太大则可能只有具体物体级别的相似。因此,$l$ 一般选一个中间层;
3. 设 $a^{(C)[l]}$、$a^{(G)[l]}$ 为 C 和 G 在 $l$ 层的激活,则有:
$$J\_{content}(C, G) = \frac{1}{2}||(a^{(C)[l]} - a^{(G)[l]})||^2$$
$a^{(C)[l]}$ 和 $a^{(G)[l]}$ 越相似,则 $J\_{content}(C, G)$ 越小。
* $a^{(C)[l]}$ 和 $a^{(G)[l]}$ 越相似,则 $J\_{content}(C, G)$ 越小。
#### 风格代价函数
## 10 风格代价函数
![Intuition-about-style-of-an-image](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/Intuition-about-style-of-an-image.png)
![Intuition-about-style-of-an-image](Intuition-about-style-of-an-image.png)
每个通道提取图片的特征不同,比如标为红色的通道提取的是图片的垂直纹理特征,标为黄色的通道提取的是图片的橙色背景特征。那么计算这两个通道的相关性,相关性的大小,即表示原始图片既包含了垂直纹理也包含了该橙色背景的可能性大小。通过 CNN“风格”被定义为同一个隐藏层不同通道之间激活值的相关系数因其反映了原始图片特征间的相互关系。
* 每个通道提取图片的特征不同,比如标为红色的通道提取的是图片的垂直纹理特征,标为黄色的通道提取的是图片的橙色背景特征。那么计算这两个通道的相关性,相关性的大小,即表示原始图片既包含了垂直纹理也包含了该橙色背景的可能性大小。通过 CNN“风格”被定义为同一个隐藏层不同通道之间激活值的相关系数因其反映了原始图片特征间的相互关系。
对于风格图像 S选定网络中的第 $l$ 层,则相关系数以一个 gram 矩阵的形式表示:
* 对于风格图像 S选定网络中的第 $l$ 层,则相关系数以一个 gram 矩阵的形式表示:
$$G^{\[l](S)}\_{kk'} = \sum^{n^{[l]}\_H}\_{i=1} \sum^{n^{[l]}\_W}\_{j=1} a^{\[l](S)}\_{ijk} a^{\[l](S)}\_{ijk'}$$
其中,$i$ 和 $j$ 为第 $l$ 层的高度和宽度;$k$ 和 $k'$ 为选定的通道,其范围为 $1$ 到 $n\_C^{[l]}$$a^{\[l](S)}\_{ijk}$ 为激活。
* 其中,$i$ 和 $j$ 为第 $l$ 层的高度和宽度;$k$ 和 $k'$ 为选定的通道,其范围为 $1$ 到 $n\_C^{[l]}$$a^{\[l](S)}\_{ijk}$ 为激活。
同理,对于生成图像 G
* 同理,对于生成图像 G
$$G^{\[l](G)}\_{kk'} = \sum^{n^{[l]}\_H}\_{i=1} \sum^{n^{[l]}\_W}\_{j=1} a^{\[l](G)}\_{ijk} a^{\[l](G)}\_{ijk'}$$
因此,第 $l$ 层的风格代价函数为:
* 因此,第 $l$ 层的风格代价函数为:
$$J^{[l]}\_{style}(S, G) = \frac{1}{(2n^{[l]}\_Hn^{[l]}\_Wn^{[l]}\_C)^2} \sum\_k \sum\_{k'}(G^{\[l](S)}\_{kk'} - G^{\[l](G)}\_{kk'})^2$$
如果对各层都使用风格代价函数,效果会更好。因此有:
* 如果对各层都使用风格代价函数,效果会更好。因此有:
$$J\_{style}(S, G) = \sum\_l \lambda^{[l]} J^{[l]}\_{style}(S, G)$$
其中,$lambda$ 是用于设置不同层所占权重的超参数。
* 其中,$lambda$ 是用于设置不同层所占权重的超参数。
### 推广至一维和三维
## 11 一维推广至三维
之前我们处理的都是二维图片,实际上卷积也可以延伸到一维和三维数据。我们举两个示例来说明。
* 之前我们处理的都是二维图片,实际上卷积也可以延伸到一维和三维数据。我们举两个示例来说明。
![1D-3D-Convolution](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Convolutional_Neural_Networks/1D-3D-Convolution.png)
![1D-3D-Convolution](1D-3D-Convolution.png)
EKG 数据(心电图)是由时间序列对应的每个瞬间的电压组成,是一维数据。一般来说我们会用 RNN循环神经网络来处理不过如果用卷积处理则有
* EKG 数据(心电图)是由时间序列对应的每个瞬间的电压组成,是一维数据。一般来说我们会用 RNN循环神经网络来处理不过如果用卷积处理则有
* 输入时间序列维度14 x 1
* 滤波器尺寸5 x 1滤波器个数16
* 输出时间序列维度10 x 16
* 输入时间序列维度14 x 1
* 滤波器尺寸5 x 1滤波器个数16
* 输出时间序列维度10 x 16
而对于三维图片的示例,有
* 而对于三维图片的示例,有
* 输入 3D 图片维度14 x 14 x 14 x 1
* 滤波器尺寸5 x 5 x 5 x 1滤波器个数16
* 输出 3D 图片维度10 x 10 x 10 x 16
* 输入 3D 图片维度14 x 14 x 14 x 1
* 滤波器尺寸5 x 5 x 5 x 1滤波器个数16
* 输出 3D 图片维度10 x 10 x 10 x 16
> 神经风格迁移的原理没有搞懂,等到下一次学习的时候再深入了解。

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

View File

@@ -1,181 +1,183 @@
<h1 align="center">循环序列模型</h1>
# 循环序列模型
自然语言和音频都是前后相互关联的数据,对于这些序列数据需要使用**循环神经网络Recurrent Neural NetworkRNN**来进行处理。
## 1 循环神经网络
* 自然语言和音频都是前后相互关联的数据,对于这些序列数据需要使用**循环神经网络Recurrent Neural NetworkRNN**来进行处理。
使用 RNN 实现的应用包括下图中所示:
* 使用 RNN 实现的应用包括下图中所示:
![Examples-of-Sequence-Model](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Sequence_Models/Examples-of-Sequence-Model.png)
![Examples-of-Sequence-Model](Examples-of-Sequence-Model.png)
## 数学符号
## 2 数学符号
对于一个序列数据 $x$,用符号 $x^{⟨t⟩}$来表示这个数据中的第 $t$个元素,用 $y^{⟨t⟩}$来表示第 $t$个标签,用 $T\_x$ 和 $T\_y$来表示输入和输出的长度。对于一段音频,元素可能是其中的几帧;对于一句话,元素可能是一到多个单词。
* 对于一个序列数据 $x$,用符号 $x^{⟨t⟩}$来表示这个数据中的第 $t$个元素,用 $y^{⟨t⟩}$来表示第 $t$个标签,用 $T_x$ 和 $T_y$来表示输入和输出的长度。对于一段音频,元素可能是其中的几帧;对于一句话,元素可能是一到多个单词。
第 $i$ 个序列数据的第 $t$ 个元素用符号 $x^{(i)⟨t⟩}$,第 $t$ 个标签即为 $y^{(i)⟨t⟩}$。对应即有 $T^{(i)}\_x$ 和 $T^{(i)}\_y$。
* 第 $i$ 个序列数据的第 $t$ 个元素用符号 $x^{(i)⟨t⟩}$,第 $t$ 个标签即为 $y^{(i)⟨t⟩}$。对应即有 $T^{(i)}_x$ 和 $T^{(i)}_y$。
想要表示一个词语,需要先建立一个**词汇表Vocabulary**,或者叫**字典Dictionary**。将需要表示的所有词语变为一个列向量,可以根据字母顺序排列,然后根据单词在向量中的位置,用 **one-hot 向量one-hot vector**来表示该单词的标签:将每个单词编码成一个 $R^{|V| \times 1}$向量,其中 $|V|$是词汇表中单词的数量。一个单词在词汇表中的索引在该向量对应的元素为 1其余元素均为 0。
### one-hot
例如,'zebra'排在词汇表的最后一位,因此它的词向量表示为:
* 想要表示一个词语,需要先建立一个**词汇表Vocabulary**,或者叫**字典Dictionary**。将需要表示的所有词语变为一个列向量,可以根据字母顺序排列,然后根据单词在向量中的位置,用 **one-hot 向量one-hot vector** 来表示该单词的标签:将每个单词编码成一个 $R^{|V| \times 1}$向量,其中 $|V|$是词汇表中单词的数量。一个单词在词汇表中的索引在该向量对应的元素为 1其余元素均为 0。
* 例如,'zebra'排在词汇表的最后一位,因此它的词向量表示为:
$$w^{zebra} = \left [ 0, 0, 0, ..., 1\right ]^T$$
**补充:**one-hot 向量是最简单的词向量。它的**缺点**是,由于每个单词被表示为完全独立的个体,因此单词间的相似度无法体现。例如单词 hotel 和 motel 意思相近,而与 cat 不相似,但是
* **补充:** one-hot 向量是最简单的词向量。它的**缺点**是,由于每个单词被表示为完全独立的个体,因此单词间的相似度无法体现。例如单词 hotel 和 motel 意思相近,而与 cat 不相似,但是
$$(w^{hotel})^Tw^{motel} = (w^{hotel})^Tw^{cat} = 0$$
## 循环神经网络模型
## 3 循环神经网络模型
对于序列数据,使用标准神经网络存在以下问题:
* 对于序列数据,使用标准神经网络存在以下问题:
* 对于不同的示例,输入和输出可能有不同的长度,因此输入层和输出层的神经元数量无法固定。
* 从输入文本的不同位置学到的同一特征无法共享。
* 模型中的参数太多,计算量太大。
* 对于不同的示例,输入和输出可能有不同的长度,因此输入层和输出层的神经元数量无法固定。
* 从输入文本的不同位置学到的同一特征无法共享。
* 模型中的参数太多,计算量太大。
为了解决这些问题,引入**循环神经网络Recurrent Neural NetworkRNN**。一种循环神经网络的结构如下图所示:
* 为了解决这些问题,引入**循环神经网络Recurrent Neural NetworkRNN**。一种循环神经网络的结构如下图所示:
![Recurrent-Neural-Network](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Sequence_Models/Recurrent-Neural-Network.png)
![Recurrent-Neural-Network](Recurrent-Neural-Network.png)
当元素 $x^{⟨t⟩}$ 输入对应时间步Time Step的隐藏层的同时该隐藏层也会接收来自上一时间步的隐藏层的激活值 $a^{⟨t-1⟩}$,其中 $a^{⟨0⟩}$ 一般直接初始化为零向量。一个时间步输出一个对应的预测结果 $\hat y^{⟨t⟩}$。
* 当元素 $x^{⟨t⟩}$ 输入对应时间步Time Step的隐藏层的同时该隐藏层也会接收来自上一时间步的隐藏层的激活值 $a^{⟨t-1⟩}$,其中 $a^{⟨0⟩}$ 一般直接初始化为零向量。一个时间步输出一个对应的预测结果 $\hat y^{⟨t⟩}$。
循环神经网络从左向右扫描数据,同时每个时间步的参数也是共享的,输入、激活、输出的参数对应为 $W\_{ax}$、$W\_{aa}$、$W\_{ya}$。
* 循环神经网络从左向右扫描数据,同时每个时间步的参数也是共享的,输入、激活、输出的参数对应为 $W_{ax}$、$W_{aa}$、$W_{ya}$。
下图是一个 RNN 神经元的结构:
* 下图是一个 RNN 神经元的结构:
![RNN-cell](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Sequence_Models/RNN-cell.png)
![RNN-cell](RNN-cell.png)
前向传播过程的公式如下:
* 前向传播过程的公式如下:
$$a^{⟨0⟩} = \vec{0}$$
$$a^{⟨t⟩} = g\_1(W\_{aa}a^{⟨t-1⟩} + W\_{ax}x^{⟨t⟩} + b\_a)$$
$$a^{⟨t⟩} = g_1(W_{aa}a^{⟨t-1⟩} + W_{ax}x^{⟨t⟩} + b_a)$$
$$\hat y^{⟨t⟩} = g\_2(W\_{ya}a^{⟨t⟩} + b\_y)$$
$$\hat y^{⟨t⟩} = g_2(W_{ya}a^{⟨t⟩} + b_y)$$
激活函数 $g\_1$通常选择 tanh有时也用 ReLU$g\_2$可选 sigmoid 或 softmax取决于需要的输出类型。
* 激活函数 $g_1$通常选择 tanh有时也用 ReLU$g_2$可选 sigmoid 或 softmax取决于需要的输出类型。
为了进一步简化公式以方便运算,可以将 $W\_{aa}$、$W\_{ax}$ **水平并列**为一个矩阵 $W\_a$,同时 $a^{⟨t-1⟩}$和 $ x^{⟨t⟩}$ **堆叠**成一个矩阵。则有:
* 为了进一步简化公式以方便运算,可以将 $W_{aa}$、$W_{ax}$ **水平并列** 为一个矩阵 $W_a$,同时 $a^{⟨t-1⟩}$和 $ x^{⟨t⟩}$ **堆叠** 成一个矩阵。则有:
$$W\_a = [W\_{aa}, W\_{ax}]$$
$$W_a = [W_{aa}, W_{ax}]$$
$$a^{⟨t⟩} = g\_1(W\_a[a^{⟨t-1⟩}; x^{⟨t⟩}] + b\_a)$$
$$a^{⟨t⟩} = g_1(W_a[a^{⟨t-1⟩}; x^{⟨t⟩}] + b_a)$$
$$\hat y^{⟨t⟩} = g\_2(W\_{ya}a^{⟨t⟩} + b\_y)$$
$$\hat y^{⟨t⟩} = g_2(W_{ya}a^{⟨t⟩} + b_y)$$
### 反向传播
## 4 反向传播
为了计算反向传播过程,需要先定义一个损失函数。单个位置上(或者说单个时间步上)某个单词的预测值的损失函数采用**交叉熵损失函数**,如下所示:
* 为了计算反向传播过程,需要先定义一个损失函数。单个位置上(或者说单个时间步上)某个单词的预测值的损失函数采用 **交叉熵损失函数** ,如下所示:
$$L^{⟨t⟩}(\hat y^{⟨t⟩}, y^{⟨t⟩}) = -y^{⟨t⟩}log\hat y^{⟨t⟩} - (1 - y^{⟨t⟩})log(1-\hat y^{⟨t⟩})$$
将单个位置上的损失函数相加,得到整个序列的成本函数如下:
* 将单个位置上的损失函数相加,得到整个序列的成本函数如下:
$$J = L(\hat y, y) = \sum^{T\_x}\_{t=1} L^{⟨t⟩}(\hat y^{⟨t⟩}, y^{⟨t⟩})$$
$$J = L(\hat y, y) = \sum^{T_x}_{t=1} L^{⟨t⟩}(\hat y^{⟨t⟩}, y^{⟨t⟩})$$
循环神经网络的反向传播被称为**通过时间反向传播Backpropagation through time**,因为从右向左计算的过程就像是时间倒流。
* 循环神经网络的反向传播被称为**通过时间反向传播Backpropagation through time**,因为从右向左计算的过程就像是时间倒流。
更详细的计算公式如下:
* 更详细的计算公式如下:
![formula-of-RNN](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Sequence_Models/formula-of-RNN.png)
![formula-of-RNN](formula-of-RNN.png)
### 不同结构
## 5 循环神经网络的不同结构
某些情况下,输入长度和输出长度不一致。根据所需的输入及输出长度,循环神经网络可分为“一对一”、“多对一”、“多对多”等结构:
* 某些情况下,输入长度和输出长度不一致。根据所需的输入及输出长度,循环神经网络可分为“一对一”、“多对一”、“多对多”等结构:
![Examples-of-RNN-architectures](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Sequence_Models/Examples-of-RNN-architectures.png)
![Examples-of-RNN-architectures](Examples-of-RNN-architectures.png)
目前我们看到的模型的问题是,只使用了这个序列中之前的信息来做出预测,即后文没有被使用。可以通过**双向循环神经网络Bidirectional RNNBRNN**来解决这个问题。
* 目前我们看到的模型的问题是,只使用了这个序列中之前的信息来做出预测,即后文没有被使用。可以通过**双向循环神经网络Bidirectional RNNBRNN** 来解决这个问题。
## 语言模型
## 6 语言模型
**语言模型Language Model**是根据语言客观事实而进行的语言抽象数学建模,能够估计某个序列中各元素出现的可能性。例如,在一个语音识别系统中,语言模型能够计算两个读音相近的句子为正确结果的概率,以此为依据作出准确判断。
* **语言模型Language Model** 是根据语言客观事实而进行的语言抽象数学建模,能够估计某个序列中各元素出现的可能性。例如,在一个语音识别系统中,语言模型能够计算两个读音相近的句子为正确结果的概率,以此为依据作出准确判断。
建立语言模型所采用的训练集是一个大型的**语料库Corpus**,指数量众多的句子组成的文本。建立过程的第一步是**标记化Tokenize**,即建立字典;然后将语料库中的每个词表示为对应的 one-hot 向量。另外,需要增加一个额外的标记 EOSEnd of Sentence来表示一个句子的结尾。标点符号可以忽略也可以加入字典后用 one-hot 向量表示。
* 建立语言模型所采用的训练集是一个大型的**语料库Corpus**,指数量众多的句子组成的文本。建立过程的第一步是**标记化Tokenize**,即建立**字典**;然后将语料库中的每个词表示为对应的 one-hot 向量。另外,需要增加一个额外的标记 EOSEnd of Sentence来表示一个句子的结尾。标点符号可以忽略也可以加入字典后用 one-hot 向量表示。
对于语料库中部分特殊的、不包含在字典中的词汇,例如人名、地名,可以不必针对这些具体的词,而是在词典中加入一个 UNKUnique Token标记来表示。
* 对于语料库中部分特殊的、不包含在字典中的词汇,例如人名、地名,可以不必针对这些具体的词,而是在词典中加入一个 UNKUnique Token标记来表示。
将标志化后的训练集用于训练 RNN过程如下图所示
* 将标志化后的训练集用于训练 RNN过程如下图所示
![language-model-RNN-example](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Sequence_Models/language-model-RNN-example.png)
![language-model-RNN-example](language-model-RNN-example.png)
在第一个时间步中,输入的 $a^{⟨0⟩}$和 $x^{⟨1⟩}$都是零向量,$\hat y^{⟨1⟩}$是通过 softmax 预测出的字典中每个词作为第一个词出现的概率;在第二个时间步中,输入的 $x^{⟨2⟩}$是训练样本的标签中的第一个单词 $y^{⟨1⟩}$即“cats”和上一层的激活项$a^{⟨1⟩}$,输出的 $y^{⟨2⟩}$表示的是通过 softmax 预测出的、单词“cats”后面出现字典中的其他每个词的条件概率。以此类推最后就可以得到整个句子出现的概率。
* 在第一个时间步中,输入的 $a^{⟨0⟩}$和 $x^{⟨1⟩}$都是零向量,$\hat y^{⟨1⟩}$是通过 softmax 预测出的字典中每个词作为第一个词出现的概率;在第二个时间步中,输入的 $x^{⟨2⟩}$是训练样本的标签中的第一个单词 $y^{⟨1⟩}$即“cats”和上一层的激活项$a^{⟨1⟩}$,输出的 $y^{⟨2⟩}$表示的是通过 softmax 预测出的、单词“cats”后面出现字典中的其他每个词的条件概率。以此类推最后就可以得到整个句子出现的概率。
定义损失函数为:
* 定义损失函数为:
$$L(\hat y^{⟨t⟩}, y^{⟨t⟩}) = -\sum\_t y\_i^{⟨t⟩} log \hat y^{⟨t⟩}$$
$$L(\hat y^{⟨t⟩}, y^{⟨t⟩}) = -\sum_t y_i^{⟨t⟩} log \hat y^{⟨t⟩}$$
则成本函数为:
* 则成本函数为:
$$J = \sum\_t L^{⟨t⟩}(\hat y^{⟨t⟩}, y^{⟨t⟩})$$
$$J = \sum_t L^{⟨t⟩}(\hat y^{⟨t⟩}, y^{⟨t⟩})$$
## 采样
## 7 采样
在训练好一个语言模型后,可以通过**采样Sample**新的序列来了解这个模型中都学习到了一些什么。
* 在训练好一个语言模型后,可以通过**采样Sample**新的序列来了解这个模型中都学习到了一些什么。
![Sampling](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Sequence_Models/Sampling.png)
![Sampling](Sampling.png)
在第一个时间步输入 $a^{⟨0⟩}$和 $x^{⟨1⟩}$为零向量,输出预测出的字典中每个词作为第一个词出现的概率,根据 softmax 的分布进行随机采样(`np.random.choice`),将采样得到的 $\hat y^{⟨1⟩}$作为第二个时间步的输入 $x^{⟨2⟩}$。以此类推,直到采样到 EOS最后模型会自动生成一些句子从这些句子中可以发现模型通过语料库学习到的知识。
* 在第一个时间步输入 $a^{⟨0⟩}$和 $x^{⟨1⟩}$为零向量,输出预测出的字典中每个词作为第一个词出现的概率,根据 softmax 的分布进行随机采样(`np.random.choice`),将采样得到的 $\hat y^{⟨1⟩}$作为第二个时间步的输入 $x^{⟨2⟩}$。以此类推,直到采样到 EOS最后模型会自动生成一些句子从这些句子中可以发现模型通过语料库学习到的知识。
这里建立的是基于词汇构建的语言模型。根据需要也可以构建基于字符的语言模型其优点是不必担心出现未知标识UNK其缺点是得到的序列过多过长并且训练成本高昂。因此基于词汇构建的语言模型更为常用。
* 这里建立的是基于词汇构建的语言模型。根据需要也可以构建基于字符的语言模型其优点是不必担心出现未知标识UNK其缺点是得到的序列过多过长并且训练成本高昂。因此基于词汇构建的语言模型更为常用。
## RNN 的梯度消失
## 8 RNN 的梯度消失
$$The\ cat, which\ already\ ate\ a\ bunch\ of\ food,\ was\ full.$$
$$The\ cats, which\ already\ ate\ a\ bunch\ of\ food,\ were\ full.$$
对于以上两个句子,后面的动词单复数形式由前面的名词的单复数形式决定。但是**基本的 RNN 不擅长捕获这种长期依赖关系**。究其原因,由于梯度消失,在反向传播时,后面层的输出误差很难影响到较靠前层的计算,网络很难调整靠前的计算。
* 对于以上两个句子,后面的动词单复数形式由前面的名词的单复数形式决定。但是**基本的 RNN 不擅长捕获这种长期依赖关系**。究其原因,由于梯度消失,在反向传播时,后面层的输出误差很难影响到较靠前层的计算,网络很难调整靠前的计算。
在反向传播时,随着层数的增多,梯度不仅可能指数型下降,也有可能指数型上升,即梯度爆炸。不过梯度爆炸比较容易发现,因为参数会急剧膨胀到数值溢出(可能显示为 NaN。这时可以采用**梯度修剪Gradient Clipping**来解决:观察梯度向量,如果它大于某个阈值,则缩放梯度向量以保证其不会太大。相比之下,梯度消失问题更难解决。**GRU 和 LSTM 都可以作为缓解梯度消失问题的方案**
* 在反向传播时,随着层数的增多,梯度不仅可能指数型下降,也有可能指数型上升,即梯度爆炸。不过梯度爆炸比较容易发现,因为参数会急剧膨胀到数值溢出(可能显示为 NaN。这时可以采用 **梯度修剪Gradient Clipping** 来解决:观察梯度向量,如果它大于某个阈值,则缩放梯度向量以保证其不会太大。相比之下,梯度消失问题更难解决。 **GRU 和 LSTM** 都可以作为缓解梯度消失问题的方案
## GRU门控循环单元
## 9 GRU门控循环单元
**GRUGated Recurrent Units, 门控循环单元)**改善了 RNN 的隐藏层,使其可以更好地捕捉深层连接,并改善了梯度消失问题。
* **GRUGated Recurrent Units, 门控循环单元)** 改善了 RNN 的隐藏层,使其可以更好地捕捉深层连接,并改善了梯度消失问题。
$$The\ cat, which\ already\ ate\ a\ bunch\ of\ food,\ was\ full.$$
当我们从左到右读上面这个句子时GRU 单元有一个新的变量称为 $c$,代表**记忆细胞Memory Cell**,其作用是提供记忆的能力,记住例如前文主语是单数还是复数等信息。在时间 t记忆细胞的值 $c^{⟨t⟩}$等于输出的激活值 $a^{⟨t⟩}$$\tilde c^{⟨t⟩}$ 代表下一个 $c$ 的候选值。$Γ\_u$ 代表**更新门Update Gate**,用于决定什么时候更新记忆细胞的值。以上结构的具体公式为:
* 当我们从左到右读上面这个句子时GRU 单元有一个新的变量称为 $c$,代表**记忆细胞Memory Cell**,其作用是提供记忆的能力,记住例如前文主语是单数还是复数等信息。在时间 t记忆细胞的值 $c^{⟨t⟩}$等于输出的激活值 $a^{⟨t⟩}$$\tilde c^{⟨t⟩}$ 代表下一个 $c$ 的候选值。$Γ_u$ 代表**更新门Update Gate**,用于决定什么时候更新记忆细胞的值。以上结构的具体公式为:
$$\tilde c^{⟨t⟩} = tanh(W\_c[c^{⟨t-1⟩}, x^{⟨t⟩}] + b\_c)$$
$$\tilde c^{⟨t⟩} = tanh(W_c[c^{⟨t-1⟩}, x^{⟨t⟩}] + b_c)$$
$$Γ\_u = \sigma(W\_u[c^{⟨t-1⟩}, x^{⟨t⟩}] + b\_u)$$
$$Γ_u = \sigma(W_u[c^{⟨t-1⟩}, x^{⟨t⟩}] + b_u)$$
$$c^{⟨t⟩} = Γ\_u \times \tilde c^{⟨t⟩} + (1 - Γ\_u) \times c^{⟨t-1⟩}$$
$$c^{⟨t⟩} = Γ_u \times \tilde c^{⟨t⟩} + (1 - Γ_u) \times c^{⟨t-1⟩}$$
$$a^{⟨t⟩} = c^{⟨t⟩}$$
当使用 sigmoid 作为激活函数 $\sigma$ 来得到 $Γ\_u$时,$Γ\_u$ 的值在 0 到 1 的范围内,且大多数时间非常接近于 0 或 1。当 $Γ\_u = 1$时,$c^{⟨t⟩}$被更新为 $\tilde c^{⟨t⟩}$,否则保持为 $c^{⟨t-1⟩}$。因为 $Γ\_u$ 可以很接近 0因此 $c^{⟨t⟩}$几乎就等于 $c^{⟨t-1⟩}$。在经过很长的序列后,$c$ 的值依然被维持,从而实现“记忆”的功能。
* 当使用 sigmoid 作为激活函数 $\sigma$ 来得到 $Γ_u$时,$Γ_u$ 的值在 0 到 1 的范围内,且大多数时间非常接近于 0 或 1。当 $Γ_u = 1$时,$c^{⟨t⟩}$被更新为 $\tilde c^{⟨t⟩}$,否则保持为 $c^{⟨t-1⟩}$。因为 $Γ_u$ 可以很接近 0因此 $c^{⟨t⟩}$几乎就等于 $c^{⟨t-1⟩}$。在经过很长的序列后,$c$ 的值依然被维持,从而实现“记忆”的功能。
以上实际上是简化过的 GRU 单元,但是蕴涵了 GRU 最重要的思想。完整的 GRU 单元添加了一个新的**相关门Relevance Gate** $Γ\_r$,表示 $\tilde c^{⟨t⟩}$和 $c^{⟨t⟩}$的相关性。因此,表达式改为如下所示:
* 以上实际上是简化过的 GRU 单元,但是蕴涵了 GRU 最重要的思想。完整的 GRU 单元添加了一个新的**相关门Relevance Gate** $Γ_r$,表示 $\tilde c^{⟨t⟩}$和 $c^{⟨t⟩}$的相关性。因此,表达式改为如下所示:
$$\tilde c^{⟨t⟩} = tanh(W\_c[Γ\_r \* c^{⟨t-1⟩}, x^{⟨t⟩}] + b\_c)$$
$$\tilde c^{⟨t⟩} = tanh(W_c[Γ_r \* c^{⟨t-1⟩}, x^{⟨t⟩}] + b_c)$$
$$Γ\_u = \sigma(W\_u[c^{⟨t-1⟩}, x^{⟨t⟩}] + b\_u)$$
$$Γ_u = \sigma(W_u[c^{⟨t-1⟩}, x^{⟨t⟩}] + b_u)$$
$$Γ\_r = \sigma(W\_r[c^{⟨t-1⟩}, x^{⟨t⟩}] + b\_r)$$
$$Γ_r = \sigma(W_r[c^{⟨t-1⟩}, x^{⟨t⟩}] + b_r)$$
$$c^{⟨t⟩} = Γ\_u \times \tilde c^{⟨t⟩} + (1 - Γ\_u) \times c^{⟨t-1⟩}$$
$$c^{⟨t⟩} = Γ_u \times \tilde c^{⟨t⟩} + (1 - Γ_u) \times c^{⟨t-1⟩}$$
$$a^{⟨t⟩} = c^{⟨t⟩}$$
相关论文:
> 相关论文:
> 1. [Cho et al., 2014. On the properties of neural machine translation: Encoder-decoder approaches](https://arxiv.org/pdf/1409.1259.pdf)
> 2. [Chung et al., 2014. Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling](https://arxiv.org/pdf/1412.3555.pdf)
1. [Cho et al., 2014. On the properties of neural machine translation: Encoder-decoder approaches](https://arxiv.org/pdf/1409.1259.pdf)
2. [Chung et al., 2014. Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling](https://arxiv.org/pdf/1412.3555.pdf)
## 10 LSTM长短期记忆
## LSTM长短期记忆)
**LSTMLong Short Term Memory长短期记忆**网络比 GRU 更加灵活和强大,它额外引入了**遗忘门Forget Gate** $Γ_f$和**输出门Output Gate** $Γ_o$。其结构图和公式如下:
**LSTMLong Short Term Memory长短期记忆**网络比 GRU 更加灵活和强大,它额外引入了**遗忘门Forget Gate** $Γ\_f$和**输出门Output Gate** $Γ\_o$。其结构图和公式如下:
<!--$$\tilde c^{⟨t⟩} = tanh(W_c[a^{⟨t-1⟩}, x^{⟨t⟩}] + b_c)$$
<!--$$\tilde c^{⟨t⟩} = tanh(W\_c[a^{⟨t-1⟩}, x^{⟨t⟩}] + b\_c)$$
$$Γ_u = \sigma(W_u[a^{⟨t-1⟩}, x^{⟨t⟩}] + b_u)$$
$$Γ\_u = \sigma(W\_u[a^{⟨t-1⟩}, x^{⟨t⟩}] + b\_u)$$
$$Γ_f = \sigma(W_f[a^{⟨t-1⟩}, x^{⟨t⟩}] + b_f)$$
$$Γ\_f = \sigma(W\_f[a^{⟨t-1⟩}, x^{⟨t⟩}] + b\_f)$$
$$Γ_o = \sigma(W_o[a^{⟨t-1⟩}, x^{⟨t⟩}] + b_o)$$
$$Γ\_o = \sigma(W\_o[a^{⟨t-1⟩}, x^{⟨t⟩}] + b\_o)$$
$$c^{⟨t⟩} = Γ^{⟨t⟩}_u \times \tilde c^{⟨t⟩} + Γ^{⟨t⟩}_f \times c^{⟨t-1⟩}$$
$$c^{⟨t⟩} = Γ^{⟨t⟩}\_u \times \tilde c^{⟨t⟩} + Γ^{⟨t⟩}\_f \times c^{⟨t-1⟩}$$
$$a^{⟨t⟩} = Γ\_o^{⟨t⟩} \times tanh(c^{⟨t⟩})$$-->
$$a^{⟨t⟩} = Γ_o^{⟨t⟩} \times tanh(c^{⟨t⟩})$$-->
![LSTM](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Sequence_Models/LSTM.png)
@@ -195,7 +197,7 @@ $c^{0}$ 常被初始化为零向量。
因此,有
$$y^{⟨t⟩} = g(W\_y[\overrightarrow a^{⟨t⟩}, \overleftarrow a^{⟨t⟩}] + b\_y)$$
$$y^{⟨t⟩} = g(W_y[\overrightarrow a^{⟨t⟩}, \overleftarrow a^{⟨t⟩}] + b_y)$$
这个改进的方法不仅能用于基本的 RNN也可以用于 GRU 或 LSTM。**缺点**是需要完整的序列数据,才能预测任意位置的结果。例如构建语音识别系统,需要等待用户说完并获取整个语音表达,才能处理这段语音并进一步做语音识别。因此,实际应用会有更加复杂的模块。
@@ -205,6 +207,6 @@ $$y^{⟨t⟩} = g(W\_y[\overrightarrow a^{⟨t⟩}, \overleftarrow a^{⟨t⟩}]
![DRNN](https://raw.githubusercontent.com/bighuang624/Andrew-Ng-Deep-Learning-notes/master/docs/Sequence_Models/DRNN.png)
以 $a^{[2]⟨3⟩}$为例,有 $a^{[2]⟨3⟩} = g(W\_a^{[2]}[a^{[2]⟨2⟩}, a^{[1]⟨3⟩}] + b\_a^{[2]})$。
以 $a^{[2]⟨3⟩}$为例,有 $a^{[2]⟨3⟩} = g(W_a^{[2]}[a^{[2]⟨2⟩}, a^{[1]⟨3⟩}] + b_a^{[2]})$。