未验证 提交 9345ba49 编写于 作者: X Xiangyu.Li 提交者: GitHub

Merge branch 'master' into master

此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -140,18 +140,20 @@ learn.fit(1e-2, 1)
## 微调和差分学习率 [[43:49](https://youtu.be/JNxcznsrRb8%3Ft%3D43m49s)]
* 到目前为止,我们没有重新训练任何预先训练的特征 - 特别是卷积内核中的任何权重。 我们所做的就是在顶部添加了一些新图层,并学习如何混合和匹配预先训练的功能。
* 卫星图像,CT扫描等图像具有完全不同的特征(与ImageNet图像相比),因此你需要重新训练多个图层。
* 对于狗和猫,图像类似于模型预训练的图像,但我们仍然可能发现稍微调整一些前面的层对结果是有帮助的。
* 以下开始实际更改卷积过滤器的方法:
* 到目前为止,我们没有重新训练任何预先训练的特征 - 特别是卷积内核中的任何权重。 我们所做的就是在顶部添加了一些新层,并学习如何混合和匹配预先训练的功能。
* 卫星图像,CT扫描等图像具有完全不同的特征(与ImageNet图像相比),因此你需要重新训练多个层。
* 对于狗和猫,图像类似于模型预训练的图像,但我们仍然可能发现稍微调整一些后面的层是有帮助的。
* 以下是告诉学习器我们想要开始实际更改卷积过滤器的方法:
```py
learn.unfreeze()
```
* “冻结”层是未被训练/更新的层。 `unfreeze`解冻所有层。
* “冻结”层是未被训练/更新的层。 `unfreeze`解冻所有层。
* 像第一层(检测对角线边缘或渐变)或第二层(识别角或曲线)的早期层可能不需要改变太多,如果有的话。
* 后面的层更有可能需要更多的学习。 因此,我们创建了一系列学习率(差异学习率):
* 后面的层更有可能需要更多的学习。 因此,我们创建了一系列学习率(差异学习率):
```py
lr=np.array([1e-4,1e-3,1e-2])
......@@ -159,14 +161,17 @@ learn.fit(1e-2, 1)
* `1e-4` :前几层(基本几何特征)
* `1e-3` :用于中间层(复杂的卷积特征)
* `1e-2` :对于最后几层
* `1e-2` :对于我们在顶部添加的层
* 为什么3? 实际上它们是3个ResNet块,但就目前而言,它被认为是一组层。
**问题** :如果我的图像比训练模型的图像大,怎么办? [[50:30](https://youtu.be/JNxcznsrRb8%3Ft%3D50m30s)]
简短的回答是,通过我们使用的库和优秀的架构,我们可以使用任何我们喜欢的尺寸。
**问题** :我们可以解冻特定的图层吗? [[51:03](https://youtu.be/JNxcznsrRb8%3Ft%3D51m3s)]
我们还没有这样做,但如果你想,你可以做`lean.unfreeze_to(n)` (它将从`n``lean.unfreeze_to(n)`解冻层)。 Jeremy几乎从未发现它有用,他认为这是因为我们使用的是差异学习率,优化器可以根据需要学习。 他发现它有用的一个地方是,如果他使用的是一个非常大的内存密集型模型,并且他的GPU耗尽,你解冻的层次越少,内存和时间就越少。
**问题** :我们可以解冻特定的层吗? [[51:03](https://youtu.be/JNxcznsrRb8%3Ft%3D51m3s)] 我们还没有这样做,但如果你想,你可以做`lean.unfreeze_to(n)` (它将从`n``lean.unfreeze_to(n)`解冻层)。 Jeremy几乎从未发现它有用,他认为这是因为我们使用的是差异学习率,优化器可以根据需要学习。 他发现它有用的一个地方是,如果他使用的是一个非常大的内存密集型模型,并且他的GPU耗尽,你解冻的层次越少,内存和时间就越少。
使用差异学习率,我们正确率高达99.5%! [[52:28](https://youtu.be/JNxcznsrRb8%3Ft%3D52m28s)]
......@@ -281,8 +286,8 @@ plot_confusion_matrix(cm, data.classes)
2. 使用`lr_find()`找到损失仍在明显改善最高学习率
3. 从预先计算的激活训练最后一层1-2个epoch
4. 使用数据增强(即`precompute=False` )训练最后一层,持续2-3个时期,其中`cycle_len=1`
5. 解冻所有
6. 将早期层设置为比下一个更高层低3x-10x的学习率。 经验法则:ImageNet像图像10倍,卫星或医学成像3倍
5. 解冻所有层
6. 将早期层设置为比下一个更高层低3x-10x的学习率。 经验法则:ImageNet像图像10倍,卫星或医学成像3倍
7. 再次使用`lr_find()` (注意:如果你调用`lr_find`设置差异学习率,它打印出来的是最后一层的学习率。)
8. 使用`cycle_mult=2`训练完整网络,直到过拟合
......@@ -544,9 +549,11 @@ label_df.pivot_table(index='breed', aggfunc=len).sort_values('id', ascending=Fal
**获得良好结果的最小步骤:**
1. 使用`lr_find()`找到最高学习率,其中损失仍在明显改善
2. 使用数据增强(即`precompute=False` )训练最后一层,持续2-3个epoch,其中`cycle_len=1`
3. 解冻所有图层
4. 将早期图层设置为比下一个更高层低3x-10x的学习率
2. 使用数据增强(即`precompute=False` )训练最后一层,持续2-3个时期,其中`cycle_len=1`
3. 解冻所有层
4. 将早期层设置为比下一个更高层低3x-10x的学习率
5. 使用`cycle_mult=2`训练完整网络,直到过拟合
**问题** :减小批量大小只会影响训练速度吗? [[1:43:34](https://youtu.be/JNxcznsrRb8%3Ft%3D1h43m34s)]
......
......@@ -126,9 +126,9 @@ Quick Dogs v Cats
* Jeremy使用ResNet50作为Quick Dogs和Cats的原因是因为Keras没有ResNet34。 我们想比较苹果和苹果。
* 你不能要求它构建适合特定数据集的模型,因此你必须手动完成。
* 首先创建基础模型,然后构建要在其上添加的层。
* 首先创建基础模型,然后构建要在其上添加的层。
**3.冻结层并编译**
**3.冻结层并编译**
```
model = Model(inputs=base_model.input, outputs=predictions)
......@@ -142,7 +142,7 @@ Quick Dogs v Cats
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
```
* 循环遍历层并通过调用`layer.trainable=False`手动冻结它们
* 循环遍历层并通过调用`layer.trainable=False`手动冻结它们
* 你需要编译模型
* 传递优化程序,损失和指标的类型
......@@ -155,7 +155,7 @@ Quick Dogs v Cats
* Keras希望知道每个时期有多少批次。
* `workers` :要使用多少处理器
**5.微调:解冻一些层,编译,然后再适合**
**5.微调:解冻一些层,编译,然后再适合**
```
split_at = 140
......@@ -283,7 +283,7 @@ Quick Dogs v Cats
* **滤镜/内核:**用于卷积的3张3张3D张量
* **张量:**多维数组或矩阵隐藏层既不是输入也不是输出的层
* **最大合并:** A(2,2)最大合并将使高度和宽度的分辨率减半 - 将其视为摘要
* **完全连接的层:**为每个单独的激活赋予权重并计算总和乘积。 权重矩阵与整个输入一样大。
* **全连接层:**为每个单独的激活赋予权重并计算总和乘积。 权重矩阵与整个输入一样大。
* 注意:在最大池层之后,你可以执行许多操作。 其中一个是在整个大小上做另一个最大池。 在旧架构或结构化数据中,我们完全连接层。 大量使用完全连接层的架构容易过拟合而且速度较慢。 ResNet和ResNext不使用非常大的完全连接层。
**问题** :如果输入有3个通道会发生什么? [[1:05:30](https://youtu.be/9C06ZPF8Uuc%3Ft%3D1h5m30s)] 它看起来类似于具有2个通道的Conv1层 - 因此,滤波器每个滤波器有2个通道。 预先训练的ImageNet模型使用3个通道。 当你有少于3个频道时,你可以使用的一些技巧是复制其中一个频道使其成为3,或者如果你有2,则获得平均值并将其视为第三个频道。 如果你有4个通道,你可以用卷全部零点为卷积内核添加额外的级别。
......@@ -294,12 +294,12 @@ Quick Dogs v Cats
让我们看一个例子,我们试图预测图片是猫,狗,飞机,鱼,还是建筑物。 我们的目标是:
1.完全连接的层获取输出(没有ReLU,因此可能有负片)
1.全连接层获取输出(没有ReLU,因此可能有负片)
2. 计算5个数字,每个数字在0和1之间,它们加起来为1。
为此,我们需要一种不同类型的激活功能(一种应用于激活的功能)。
为什么我们需要非线性? 如果堆叠多个线性图层,它仍然只是一个线性图层。 通过添加非线性层,我们可以适应任意复杂的形状。 我们使用的非线性激活函数是ReLU。
为什么我们需要非线性? 如果堆叠多个线性层,它仍然只是一个线性层。 通过添加非线性层,我们可以适应任意复杂的形状。 我们使用的非线性激活函数是ReLU。
#### Softmax [[01:14:08](https://youtu.be/9C06ZPF8Uuc%3Ft%3D1h14m8s)]
......@@ -429,7 +429,7 @@ Softmax不喜欢预测多个事物。 它想要选择一件事。
_[ 0\. 0.12534 0.10926 0.90892]_ _[ 1\. 0.12035 0.10086 0.91635]_ _[ 2\. 0.11001 0.09792 0.91894]_ _[ 3\. 0.1144 0.09972 0.91748]_ _[ 4\. 0.11055 0.09617 0.92016]_ _[ 5\. 0.10348 0.0935 0.92267]_ _[ 6\. 0.10502 0.09345 0.92281]_
```
* `[lr/9, lr/3, lr]` - 这是因为图像与ImageNet图像不同,而早期的层可能并不像它们需要的那样接近。
* `[lr/9, lr/3, lr]` - 这是因为图像与ImageNet图像不同,而早期的层可能并不像它们需要的那样接近。
```
learn.sched.plot_loss()
......@@ -509,11 +509,11 @@ Softmax不喜欢预测多个事物。 它想要选择一件事。
![](../img/1_2Ocl12SOFKZ75iV4bqg-OQ.png)
你可以跳过最后一层的训练,直接进入不同的学习率,但你可能不想这样做。 卷积层都包含预先训练的权重,因此它们不是随机的 - 对于接近ImageNet的东西,它们确实很好; 对于那些与ImageNet不相近的东西,它们总比没有好。 然而,我们所有完全连接的层都是完全随机的。 因此,你总是希望通过先训练它们来使完全连接的权重优于随机。 否则,如果你直接解冻,那么当你后来的那些仍然是随机的时候,你实际上是要摆弄那些早期的图层权重 - 这可能不是你想要的。
你可以跳过最后一层的训练,直接进入不同的学习率,但你可能不想这样做。 卷积层都包含预先训练的权重,因此它们不是随机的 - 对于接近ImageNet的东西,它们确实很好; 对于那些与ImageNet不相近的东西,它们总比没有好。 然而,我们所有全连接层都是完全随机的。 因此,你总是希望通过先训练它们来使完全连接的权重优于随机。 否则,如果你直接解冻,那么当你后来的那些仍然是随机的时候,你实际上是要摆弄那些早期的层权重 - 这可能不是你想要的。
问题:当你使用差异学习率时,这三种学习率是否在各层之间均匀分布? [[01:55:35](https://youtu.be/9C06ZPF8Uuc%3Ft%3D1h55m35s)] 我们将在后面的课程中详细讨论这个问题,但是fast.ai库中有一个“图层组”的概念。 在类似ResNet50的东西中,有数百个层,你可能不想写出数百个学习率,因此库决定如何拆分它们,最后一个总是指我们随机初始化的完全连接的层并补充说。
问题:当你使用差异学习率时,这三种学习率是否在各层之间均匀分布? [[01:55:35](https://youtu.be/9C06ZPF8Uuc%3Ft%3D1h55m35s)] 我们将在后面的课程中详细讨论这个问题,但是fast.ai库中有一个“层组”的概念。 在类似ResNet50的东西中,有数百个层,你可能不想写出数百个学习率,因此库决定如何拆分它们,最后一个总是指我们随机初始化的全连接层并补充说。
#### 可视化层 [[01:56:42](https://youtu.be/9C06ZPF8Uuc%3Ft%3D1h56m42s)]
#### 可视化层 [[01:56:42](https://youtu.be/9C06ZPF8Uuc%3Ft%3D1h56m42s)]
```
learn.summary()
......@@ -598,7 +598,7 @@ Softmax不喜欢预测多个事物。 它想要选择一件事。
#### 下周
* 将列拆分为两种类型:分类和连续。 分类列将表示为一个热编码,并且连续列按原样馈送到完全连接的层。
* 将列拆分为两种类型:分类和连续。 分类列将表示为一个热编码,并且连续列按原样馈送到全连接层。
* 分类:商店#1和商店#2在数量上并不相互关联。 类似地,星期一(第0天)和星期二(第1天)的星期几。
* 连续:距离最接近的竞争对手的公里距离是我们用数字处理的数字。
* `ColumnarModelData`
此差异已折叠。
......@@ -2,9 +2,9 @@
### [第5课](http://forums.fast.ai/t/wiki-lesson-5/9403)
### 一,
### 一,
没有足够的关于结构化深度学习的出版物,但它肯定发生在行业中:
没有足够的关于结构化深度学习的出版物,但它肯定出现在行业中:
[**结构化深度学习**](https://towardsdatascience.com/structured-deep-learning-b8ca4138b848 "https://towardsdatascience.com/structured-deep-learning-b8ca4138b848")[
](https://towardsdatascience.com/structured-deep-learning-b8ca4138b848 "https://towardsdatascience.com/structured-deep-learning-b8ca4138b848")[_作者:Kerem Turgutlu_朝向datascience.com](https://towardsdatascience.com/structured-deep-learning-b8ca4138b848 "https://towardsdatascience.com/structured-deep-learning-b8ca4138b848")[](https://towardsdatascience.com/structured-deep-learning-b8ca4138b848)
......@@ -14,18 +14,18 @@
[**小图像数据集的乐趣(第2部分)**](https://towardsdatascience.com/fun-with-small-image-data-sets-part-2-54d683ca8c96 "https://towardsdatascience.com/fun-with-small-image-data-sets-part-2-54d683ca8c96")[
](https://towardsdatascience.com/fun-with-small-image-data-sets-part-2-54d683ca8c96 "https://towardsdatascience.com/fun-with-small-image-data-sets-part-2-54d683ca8c96")[_作者:Nikhil B_ towardsdatascience.com](https://towardsdatascience.com/fun-with-small-image-data-sets-part-2-54d683ca8c96 "https://towardsdatascience.com/fun-with-small-image-data-sets-part-2-54d683ca8c96")[](https://towardsdatascience.com/fun-with-small-image-data-sets-part-2-54d683ca8c96)
关于如何训练神经网络的介绍(一篇伟大的技术写作):
如何训练神经网络的介绍(一篇伟大的技术写作):
[**我们如何“训练”神经网络?**](https://towardsdatascience.com/how-do-we-train-neural-networks-edd985562b73 "https://towardsdatascience.com/how-do-we-train-neural-networks-edd985562b73")[
](https://towardsdatascience.com/how-do-we-train-neural-networks-edd985562b73 "https://towardsdatascience.com/how-do-we-train-neural-networks-edd985562b73")[_由Vitaly Bushaev_朝向dasatcience.com](https://towardsdatascience.com/how-do-we-train-neural-networks-edd985562b73 "https://towardsdatascience.com/how-do-we-train-neural-networks-edd985562b73")[](https://towardsdatascience.com/how-do-we-train-neural-networks-edd985562b73)
学生们在[Kaggle幼苗分类比赛中](https://www.kaggle.com/c/plant-seedlings-classification/leaderboard)与Jeremy [竞争](https://www.kaggle.com/c/plant-seedlings-classification/leaderboard)
### II。 协过滤 - 使用MovieLens数据集
### II。 协过滤 - 使用MovieLens数据集
讨论的笔记本可以在[这里](https://github.com/fastai/fastai/blob/master/courses/dl1/lesson5-movielens.ipynb)找到[(lesson5-movielens.ipynb)](https://github.com/fastai/fastai/blob/master/courses/dl1/lesson5-movielens.ipynb)
我们来看看数据。 我们将使用`userId`分类), `movieId` (分类)和`rating` (依赖)进行建模。
我们来看看数据。 我们将使用`userId`类别), `movieId` (类别)和`rating`(因变量)进行建模。
```
ratings = pd.read_csv(path+'ratings.csv') ratings.head()
......@@ -35,7 +35,7 @@
#### **为Excel创建子集**
我们创建了最受欢迎的电影和大多数电影上瘾用户的交叉表,我们将其复制到Excel中进行可视化。
我们创建了最受欢迎的电影和大多数电影狂热粉的交叉表,我们将其复制到Excel中进行可视化。
```
g=ratings.groupby('userId')['rating'].count() topUsers=g.sort_values(ascending=False)[:15]
......@@ -55,23 +55,23 @@
![](../img/1_QO-Doqw_0YGOU-vmI-R5CA.png)
[](https://github.com/fastai/fastai/blob/master/courses/dl1/excel/collab_filter.xlsx)是包含上述信息的excel文件。 首先,我们将使用**矩阵分解/分解**而不是构建神经网络。
[](https://github.com/fastai/fastai/blob/master/courses/dl1/excel/collab_filter.xlsx)是包含上述信息的excel文件。 首先,我们将使用**矩阵分解**而不是构建神经网络。
![](../img/1_ps-Mq2y88JBT3JsKBh-sKQ.png)
* 蓝色细胞 - 实际评级
* 紫色细胞 - 我们的预测
*细胞 - 我们的损失函数即均方根误差(RMSE)
* 蓝色单元格 - 实际评级
* 紫色单元格 - 我们的预测
*色单元格 - 我们的损失函数即均方根误差(RMSE)
* 绿色单元格 - 电影嵌入(随机初始化)
* 橙色单元格 - 用户嵌入(随机初始化)
每个预测是电影嵌入矢量和用户嵌入矢量的点积。 在线性代数项中,它等于矩阵乘积,因为一个是行,一个是列。 如果没有实际评级,我们将预测设置为零(将其视为测试数据 - 而不是训练数据)。
每个预测是电影嵌入向量和用户嵌入向量的点积。 在线性代数术语中,它等于矩阵乘积,因为一个是行,一个是列。 如果没有实际评级,我们将预测设置为零(将其视为测试数据 - 而不是训练数据)。
![](../img/1_2SeWMcKe9VCLkVQVuCvU8g.png)
然后我们使用Gradient Descent来减少损失。 Microsoft Excel在加载项中有一个“求解器”,可以通过更改所选单元格来最小化变量( `GRG Nonlinear`是你要使用的方法)。
然后我们使用梯度下降来减少损失。 Microsoft Excel在加载项中有一个“求解器”,可以通过更改所选单元格来最小化变量( `GRG Nonlinear`是你要使用的方法)。
这可称为“浅学习”(与深度学习相反),因为没有非线性层或第二线性层。 那么我们直觉上做了什么呢? 每部电影的五个数字称为“嵌入”(潜在因素) - 第一个数字可能代表科幻和幻想的数量,第二个数字可能是电影使用了多少特效,第三个可能是如何类似地,每个用户还有5个数字,例如,表示用户喜欢幻想幻想,特效和电影中的对话驱动多少。 我们的预测是这些载体的交叉产物。 由于我们没有针对每个用户进行所有电影评论,因此我们试图找出哪些电影与这部电影相似,以及其他用户如何评价与此用户类似的其他电影为此电影评分(因此称为“协作”)。
这可称为“浅学习”(与深度学习相反),因为没有非线性层或第二线性层。 那么我们直觉上做了什么呢? 每部电影的五个数字称为“嵌入”(潜在因式) - 第一个数字可能代表科幻和幻想的数量,第二个数字可能是电影使用了多少特效,第三个可能是如何类似地,每个用户还有5个数字,例如,表示用户喜欢幻想,特效和电影中的对话的多少。 我们的预测是这些载体的叉乘。 由于我们没有每个用户的所有电影评论,因此我们试图找出哪些电影与这部电影相似,以及其他用户评价其他电影,如何与这个用户评价这个电影类似(因此称为“协同”)。
我们如何处理新用户或新电影 - 我们是否需要重新训练模型? 我们现在没有时间来讨论这个问题,但基本上你需要有一个新的用户模型或最初会使用的新电影模型,随着时间的推移你需要重新训练模型。
......@@ -89,7 +89,7 @@
cf = CollabFilterDataset.from_csv(path, 'ratings.csv', 'userId', 'movieId', 'rating')
```
然后我们得到一个适合模型数据的学习者,并适合模型:
然后我们得到一个适合模型数据的学习器,并拟合模型:
```
learn = cf.get_learner(n_factors, val_idxs, 64, opt_fn=optim.Adam)
......@@ -105,13 +105,13 @@
由于输出是Mean Squared Error,你可以通过以下方式获取RMSE:
由于输出是均方误差,你可以通过以下方式获取 RMSE:
```
math.sqrt(0.765)
```
产量约为0.88,优于0.91的基准。
输出约为0.88,优于0.91的基准。
你可以通过常规方式获得预测:
......@@ -119,7 +119,7 @@
preds = learn.predict()
```
你也可以使用seaborn `sns` (建立在matplotlib之上):
你也可以使用seaborn `sns`(建立在`matplotlib`之上):
```
y = learn.data.val_y sns.jointplot(preds, y, kind='hex', stat_func=None)
......@@ -127,19 +127,19 @@
![](../img/1_cXAU8huHFkxKbJjZUwwxIA.png)
#### **使用Python的Dot产品**
#### **使用Python的点乘**
![](../img/1_kSUYsjtdLbyn2SqW9cKiHA.jpeg)
![](../img/1_H_VqypjqEku0QjLZ51rvKA.jpeg)
`T`火炬中的张量
`T` PyTorch 中的张量
```
a = T([[1., 2], [3, 4]]) b = T([[2., 2], [10, 10]])
```
当我们在numpy或PyTorch中的张量之间有一个数学运算符时,它将在元素方面假设它们都具有相同的维数。 下面是你如何计算两个向量的点积(例如(1,2)·(2,2)= 6 - 矩阵a和b的第一行):
当我们在numpy或PyTorch中的张量之间有一个数学运算符时,它将逐元素运算,假设它们都具有相同的维数。 下面是你如何计算两个向量的点积(例如`(1,2)·(2,2)= 6` - 矩阵`a``b`的第一行):
```
(a*b).sum(1)
......@@ -149,15 +149,15 @@
6 70 [torch.FloatTensor of size 2]
```
#### **构建我们的第一个自定义层(即PyTorch模块)[** [**33:55**](https://youtu.be/J99NV9Cr75I%3Ft%3D33m55s) **]**
#### **构建我们的第一个自定义层(即 PyTorch 模块)[** [**33:55**](https://youtu.be/J99NV9Cr75I%3Ft%3D33m55s) **]**
我们通过创建一个扩展`nn.Module`并覆盖`forward`函数的Python类来实现这一点
我们通过创建一个扩展`nn.Module`并覆盖`forward`函数的 Python 类来实现它
```
class DotProduct (nn.Module): def forward(self, u, m): return (u*m).sum(1)
```
现在我们可以调用它并得到预期的结果(注意我们不需要`model.forward(a, b)`来调用`forward`函数 - 它是PyTorch魔法。) [[40:14](https://youtu.be/J99NV9Cr75I%3Ft%3D40m14s)] :
现在我们可以调用它并得到预期的结果(注意我们不需要`model.forward(a, b)`来调用`forward`函数 - 它是PyTorch魔法。) [[40:14](https://youtu.be/J99NV9Cr75I%3Ft%3D40m14s)] :
```
model = DotProduct() **model(a,b)**
......@@ -284,7 +284,7 @@ _提示:_ `{o:i for i,o in enumerate(u_uniq)}`是一个方便的代码行保
既然我们有神经网络,我们可以尝试很多东西:
* 添加辍学
* 添加 Dropout
* 使用不同的嵌入大小进行用户嵌入和电影嵌入
* 不仅是用户和电影嵌入,而且还附加来自原始数据的电影类型嵌入和/或时间戳。
* 增加/减少隐藏层数和激活次数
......@@ -346,7 +346,7 @@ _提示:_ `{o:i for i,o in enumerate(u_uniq)}`是一个方便的代码行保
#### Adam [[1:59:04](https://youtu.be/J99NV9Cr75I%3Ft%3D1h59m4s)]
Adam 的速度要快得多,但问题在于最终的预测并不像SGD那样有动力。 似乎这是由于 Adam 和重衰减的联合使用。 解决此问题的新版本称为**AdamW**
Adam 的速度要快得多,但问题在于最终的预测并不像SGD那样有动力。 似乎这是由于 Adam 和重衰减的联合使用。 解决此问题的新版本称为**AdamW**
![](../img/1_0yZ9Hbn2BPSNY9L-5jL0Tg.png)
......@@ -377,6 +377,6 @@ _提示:_ `{o:i for i,o in enumerate(u_uniq)}`是一个方便的代码行保
#### AdamW [[2:11:18](https://youtu.be/J99NV9Cr75I%3Ft%3D2h11m18s)]
当参数多于数据点时,正则化变得很重要。 我们以前见过辍学,体重衰退是另一种正规化。 权重衰减(L2正则化)通过将平方权重(权重衰减乘数乘以)加到损失中来惩罚大权重。 现在损失函数想要保持较小的权重,因为增加权重会增加损失; 因此,只有当损失提高超过罚款时才这样做。
当参数多于数据点时,正则化变得很重要。 我们以前见过 Dropout ,权重衰退是另一种正规化。 权重衰减(L2正则化)通过将平方权重(权重衰减乘数乘以)加到损失中来惩罚大权重。 现在损失函数想要保持较小的权重,因为增加权重会增加损失; 因此,只有当损失提高超过罚款时才这样做。
问题在于,由于我们将平方权重添加到损失函数,这会影响梯度的移动平均值和Adam的平方梯度的移动平均值。 这导致当梯度变化很大时减少权重衰减量,并且当变化很小时增加权重衰减量。 换句话说,“惩罚大权重,除非渐变变化很大”,这不是我们想要的。 AdamW从损失函数中删除了权重衰减,并在更新权重时直接添加它。
......@@ -9,7 +9,7 @@
我们上周深入研究了协同过滤,最后我们在fast.ai库中重新创建了`EmbeddingDotBias`类( `column_data.py` )。 让我们看一下嵌入式的样子 [[笔记本](https://github.com/fastai/fastai/blob/master/courses/dl1/lesson5-movielens.ipynb)] 。
在学习`learn`内部,你可以通过调用`learn.model`来获取PyTorch模型。 `@property`看起来像常规函数,但在调用它时不需要括号。
在学习`learn`内部,你可以通过调用`learn.model`来获取PyTorch模型。 `@property`看起来像常规函数,但在调用它时不需要括号。
```
@property def model(self): return self.models.model
......@@ -29,9 +29,9 @@ PyTorch模型很好地打印出层,包括层名,这就是我们在代码中
![](../img/1_4MrbqWktWz3oroYWn5Xh6w.png)
`m.ib`是指项目偏差的嵌入层 - 在我们的例子中是电影偏见。 PyTorch模型和层的好处是我们可以将它们称为函数。 因此,如果你想获得预测,则调用`m(...)`并传入变量。
`m.ib`是指项目偏差的嵌入层 - 在我们的例子中是电影偏见。 PyTorch模型和层的好处是我们可以将它们称为函数。 因此,如果你想获得预测,则调用`m(...)`并传入变量。
层需要变量而不是张量,因为它需要跟踪导数 - 这就是`V(...)`将张量转换为变量的原因。 PyTorch 0.4将摆脱变量,我们将能够直接使用张量。
层需要变量而不是张量,因为它需要跟踪导数 - 这就是`V(...)`将张量转换为变量的原因。 PyTorch 0.4将摆脱变量,我们将能够直接使用张量。
```
movie_bias = to_np(m.ib(V(topMovieIdx)))
......@@ -216,8 +216,8 @@ Skip-Gram特定于NLP。 将未标记的问题转变为标记问题的好方法
同样,我们现在了解`forward`功能正在发生什么。
* 使用第_i_个分类变量调用嵌入层并将它们连接在一起
* 通过辍学把它
* 浏览每个线性层,调用它,应用relu和dropout
* 通过 Dropout 把它
* 浏览每个线性层,调用它,应用relu和dropout
* 然后最终线性层的大小为1
* 如果`y_range` ,则应用sigmoid并将输出拟合到一个范围内(我们上周学到的)
......@@ -314,13 +314,13 @@ Skip-Gram特定于NLP。 将未标记的问题转变为标记问题的好方法
#### 具有单个隐藏层的基本NN
所有形状都是激活(激活是由relu,矩阵产品等计算的数字)。 箭头是层操作(可能不止一个)。 查看机器学习课程9-11,从头开始创建。
所有形状都是激活(激活是由relu,矩阵产品等计算的数字)。 箭头是层操作(可能不止一个)。 查看机器学习课程9-11,从头开始创建。
![](../img/1_vPfe01ALNgbxw8DP_4RFVw.png)
#### 图像CNN具有单密集隐藏层
我们将介绍如何在下周更多地压平图层,但主要方法称为“自适应最大池” - 我们在高度和宽度上进行平均并将其转换为矢量。
我们将介绍如何在下周更多地压平层,但主要方法称为“自适应最大池” - 我们在高度和宽度上进行平均并将其转换为向量。
![](../img/1_VEEVatttQmlWeI98vTO0iA.png)
......
......@@ -139,7 +139,7 @@
* 我们没有单独的测试集,所以我们只使用验证集进行测试
* TorchText每次将bptt的长度随机化一点。 它并不总能给我们准确的8个字符; 5%的时间,它会将它减少一半并加上一个小的标准偏差,使其略大于或小于8.我们无法对数据进行混洗,因为它需要连续,所以这是一种引入一些随机性的方法。
* 问题 [[31:46](https://youtu.be/H3g26EVADgY%3Ft%3D31m46s)] :每个小批量的尺寸是否保持不变? 是的,我们需要使用`h`权重矩阵进行矩阵乘法,因此小批量大小必须保持不变。 但序列长度可以改变没有问题。
* `len(md.trn_dl)` :数据加载器的长度(即多少`md.nt`批量), `md.nt`令牌数量(即词汇表中有多少独特的东西)
* `len(md.trn_dl)` :数据加载器的长度(即多少`md.nt`批量), `md.nt`标记数量(即词汇表中有多少独特的东西)
* 一旦运行`LanguageModelData.from_text_files``TEXT`将包含一个名为`vocab`的额外属性。 `TEXT.vocab.itos`词汇表中的唯一项目列表, `TEXT.vocab.stoi`是从每个项目到数字的反向映射。
```
......@@ -225,9 +225,9 @@ LSTM还有一个状态称为“单元状态”(不仅仅是隐藏状态),
**class** **CharSeqStatefulLSTM** (nn.Module): **def** __init__(self, vocab_size, n_fac, bs, nl): super().__init__() self.vocab_size,self.nl = vocab_size,nl self.e = nn.Embedding(vocab_size, n_fac) self.rnn = nn.LSTM(n_fac, n_hidden, nl, **dropout** =0.5) self.l_out = nn.Linear(n_hidden, vocab_size) self.init_hidden(bs) **def** forward(self, cs): bs = cs[0].size(0) **if** self.h[0].size(1) != bs: self.init_hidden(bs) outp,h = self.rnn(self.e(cs), self.h) self.h = repackage_var(h) **return** F.log_softmax(self.l_out(outp), dim=-1).view(-1, self.vocab_size) **def** init_hidden(self, bs): **self.h = (V(torch.zeros(self.nl, bs, n_hidden)),** **V(torch.zeros(self.nl, bs, n_hidden)))**
```
代码与GRU代码相同。 添加的一件事是`dropout` ,它在每个时间步骤后都会辍学并将隐藏层加倍 - 希望它能够学到更多并且能够保持弹性。
代码与GRU代码相同。 添加的一件事是`dropout` ,它在每个时间步骤后都会 Dropout 并将隐藏层加倍 - 希望它能够学到更多并且能够保持弹性。
#### 没有学习课程的回调(特别是SGDR) [[55:23](https://youtu.be/H3g26EVADgY%3Ft%3D55m23s)]
#### 没有学习课程的回调(特别是SGDR) [[55:23](https://youtu.be/H3g26EVADgY%3Ft%3D55m23s)]
```
m = CharSeqStatefulLSTM(md.nt, n_fac, 512, 2).cuda() lo = LayerOptimizer(optim.Adam, m, 1e-2, 1e-5)
......@@ -381,7 +381,7 @@ CIFAR 10是学术界一个古老且众所周知的数据集 - 在ImageNet之前
#### CNN [[01:12:30](https://youtu.be/H3g26EVADgY%3Ft%3D1h12m30s)]
* 让我们用卷积模型替换完全连接的模型。 完全连接的层只是做一个点积。 这就是权重矩阵很大的原因(3072输入* 40 = 122880)。 我们没有非常有效地使用这些参数,因为输入中的每个像素都具有不同的权重。 我们想要做的是一组3乘3像素,它们具有特定的模式(即卷积)。
* 让我们用卷积模型替换完全连接的模型。 全连接层只是做一个点积。 这就是权重矩阵很大的原因(3072输入* 40 = 122880)。 我们没有非常有效地使用这些参数,因为输入中的每个像素都具有不同的权重。 我们想要做的是一组3乘3像素,它们具有特定的模式(即卷积)。
* 我们将使用具有三乘三内核的过滤器。 如果有多个过滤器,则输出将具有其他维度。
```
......@@ -447,7 +447,7 @@ CIFAR 10是学术界一个古老且众所周知的数据集 - 在ImageNet之前
#### 重构 [[01:21:57](https://youtu.be/H3g26EVADgY%3Ft%3D1h21m57s)]
通过创建`ConvLayer` (我们的第一个自定义层!)简化`forward`功能。 在PyTorch中,层定义和神经网络定义是相同的。 任何时候你有一个图层,你可以将它用作神经网络,当你有神经网络时,你可以将它用作图层。
通过创建`ConvLayer` (我们的第一个自定义层!)简化`forward`功能。 在PyTorch中,层定义和神经网络定义是相同的。 任何时候你有一个层,你可以将它用作神经网络,当你有神经网络时,你可以将它用作层。
```
**class** **ConvLayer** (nn.Module): **def** __init__(self, ni, nf): super().__init__() self.conv = nn.Conv2d(ni, nf, kernel_size=3, stride=2, padding=1) **def** forward(self, x): **return** F.relu(self.conv(x))
......@@ -463,7 +463,7 @@ CIFAR 10是学术界一个古老且众所周知的数据集 - 在ImageNet之前
#### BatchNorm [[1:25:10](https://youtu.be/H3g26EVADgY%3Ft%3D1h25m10s)]
* 最后一个模型,当我们尝试添加更多层时,我们在训练时遇到了麻烦。 我们训练有困难的原因是,如果我们使用较大的学习率,那么它将用于NaN,如果我们使用较小的学习率,则需要永远并且没有机会正确探索 - 因此它没有弹性。
* 最后一个模型,当我们尝试添加更多层时,我们在训练时遇到了麻烦。 我们训练有困难的原因是,如果我们使用较大的学习率,那么它将用于NaN,如果我们使用较小的学习率,则需要永远并且没有机会正确探索 - 因此它没有弹性。
* 为了使其具有弹性,我们将使用称为批量规范化的东西。 BatchNorm大约两年前推出,它具有很大的变革性,因为它突然使得培养更深层的网络变得非常容易。
* 我们可以简单地使用`nn.BatchNorm`但要了解它,我们将从头开始编写它。
* It is unlikely that the weight matrices on average are not going to cause your activations to keep getting smaller and smaller or keep getting bigger and bigger. It is important to keep them at reasonable scale. So we start things off with zero-mean standard deviation one by normalizing the input. What we really want to do is to do this for all layers, not just the inputs.
......@@ -473,21 +473,21 @@ CIFAR 10是学术界一个古老且众所周知的数据集 - 在ImageNet之前
```
* 计算每个通道或每个过滤器的平均值以及每个通道或每个过滤器的标准偏差。 然后减去均值并除以标准差。
* 我们不再需要对输入进行标准化,因为它会对每个通道进行标准化,或者对于以后的层,它按照过滤器进行标准化。
* 我们不再需要对输入进行标准化,因为它会对每个通道进行标准化,或者对于以后的层,它按照过滤器进行标准化。
* 原来这还不够,因为SGD是血腥的 [[01:29:20](https://youtu.be/H3g26EVADgY%3Ft%3D1h29m20s)] 。 如果SGD决定它希望矩阵整体更大/更小,那么做`(x=self.means) / self.stds`是不够的,因为SGD将撤消它并尝试在下一个小批量中再次执行。 因此,我们将为每个通道添加两个参数: `a` - 加法器(初始值零)和`m` - 乘数(初始值1)。
* `Parameter`告诉PyTorch允许将它们作为权重学习。
* 为什么这样做? 如果要扩展层,则不必扩展矩阵中的每个值。 它可以扩展这个单独的三个数字`self.m` ,如果它想要将它全部向上或向下移动一点,它不必移动整个权重矩阵,它们可以将这三个数字`self.a``self.a` 直觉:我们正在对数据进行标准化,然后我们说你可以转移它并使用比实际移位和缩放整个卷积滤波器组所需的参数少得多的参数来缩放它。 在实践中,它允许我们提高我们的学习率,增加训练的弹性,并且它允许我们添加更多层并且仍然有效地训练。
* 批量规范所做的另一件事是它规则化,换句话说,你可以经常减少或消除辍学或体重衰减。 原因是每个小批量将与先前的小批量具有不同的平均值和不同的标准偏差。 因此,它们不断变化,并以微妙的方式改变滤波器的含义,作为噪声(即正则化)。
* 为什么这样做? 如果要扩展层,则不必扩展矩阵中的每个值。 它可以扩展这个单独的三个数字`self.m` ,如果它想要将它全部向上或向下移动一点,它不必移动整个权重矩阵,它们可以将这三个数字`self.a``self.a` 直觉:我们正在对数据进行标准化,然后我们说你可以转移它并使用比实际移位和缩放整个卷积滤波器组所需的参数少得多的参数来缩放它。 在实践中,它允许我们提高我们的学习率,增加训练的弹性,并且它允许我们添加更多层并且仍然有效地训练。
* 批量规范所做的另一件事是它规则化,换句话说,你可以经常减少或消除 Dropout 或权重衰减。 原因是每个小批量将与先前的小批量具有不同的平均值和不同的标准偏差。 因此,它们不断变化,并以微妙的方式改变滤波器的含义,作为噪声(即正则化)。
* 在实际版本中,它不使用此批次的均值和标准差,而是采用指数加权移动平均标准差和均值。
* `**if** self.training` - 这很重要,因为当你通过验证集时,你不想改变模型的含义。 有些类型的层实际上对网络模式敏感,无论是处于训练模式还是评估/测试模式。 当我们为MovieLens实现迷你网时出现了一个错误,即在验证过程中应用了dropout - 这是固定的。 在PyTorch中,有两个这样的层:dropout和batch norm。 `nn.Dropout`已经进行了检查。
* [[01:37:01](https://youtu.be/H3g26EVADgY%3Ft%3D1h37m1s)] [fast.ai](https://youtu.be/H3g26EVADgY%3Ft%3D1h37m1s)的关键区别在于,无论其他库做什么,只要你基本上说我正在训练,这些手段和标准偏差都会在其他库的训练模式中更新,无论该层是否是否可以训练。 有了预先训练好的网络,这是一个糟糕的主意。 如果你有一个预先训练好的网络,用于批量标准中的那些均值和标准偏差的特定值,如果你更改它们,它将改变那些预先训练的图层的含义。 在fast.ai中,始终默认情况下,如果你的图层被冻结,它将不会触及那些均值和标准偏差。 一旦你取消冻结它,除非你设置`learn.bn_freeze=True` ,否则它将开始更新它们。 在实践中,对于预训练的模型,这似乎通常效果更好,特别是如果你使用的数据与预训练模型的训练非常相似。
* [[01:37:01](https://youtu.be/H3g26EVADgY%3Ft%3D1h37m1s)] [fast.ai](https://youtu.be/H3g26EVADgY%3Ft%3D1h37m1s)的关键区别在于,无论其他库做什么,只要你基本上说我正在训练,这些手段和标准偏差都会在其他库的训练模式中更新,无论该层是否是否可以训练。 有了预先训练好的网络,这是一个糟糕的主意。 如果你有一个预先训练好的网络,用于批量标准中的那些均值和标准偏差的特定值,如果你更改它们,它将改变那些预先训练的层的含义。 在fast.ai中,始终默认情况下,如果你的层被冻结,它将不会触及那些均值和标准偏差。 一旦你取消冻结它,除非你设置`learn.bn_freeze=True` ,否则它将开始更新它们。 在实践中,对于预训练的模型,这似乎通常效果更好,特别是如果你使用的数据与预训练模型的训练非常相似。
* 你在哪里放置批量标准层? 我们稍后会谈谈更多,但就目前来说,经过`relu`
#### 消融研究 [[01:39:41](https://youtu.be/H3g26EVADgY%3Ft%3D1h39m41s)]
在这种情况下,你可以尝试打开和关闭模型的不同部分,以查看哪些部位产生了哪些影响,而原始批次规范文件中未执行的操作之一是任何有效的消融。 因此缺少的一件事就是这个问题刚才被问到 - 在哪里提出批量规范。 这种疏忽造成了很多问题,因为事实证明原始论文并没有真正把它放在最佳位置。 从那时起,其他人现在已经想到了这一点,当Jeremy向人们展示实际上在现场更好的代码时,人们说他的批量规范是在错误的位置。
* 如果可以,请尝试并始终在每个层上使用批量规范
* 如果可以,请尝试并始终在每个层上使用批量规范
* 不要停止对数据进行规范化,以便使用你的数据的人知道你如何规范化数据。 其他库可能无法正确处理预训练模型的批量规范,因此当人们开始重新训练时,可能会导致问题。
```
......@@ -495,7 +495,7 @@ CIFAR 10是学术界一个古老且众所周知的数据集 - 在ImageNet之前
```
* 其余代码类似 - 使用`BnLayer`而不是`ConvLayer`
* 在开始时添加了单个卷积层,试图更接近现代方法。 它具有更大的内核大小和1的步幅。基本思想是我们希望第一层具有更丰富的输入。 它使用5×5区域进行卷积,这允许它尝试在5×5区域内找到更有趣的更丰富的特征,然后出更大的输出(在这种情况下,它是10乘5乘5个滤波器)。 通常它是5乘5或7乘7,或甚至11乘11卷积,并且有相当多的滤波器出来(例如32个滤波器)。
* 在开始时添加了单个卷积层,试图更接近现代方法。 它具有更大的内核大小和1的步幅。基本思想是我们希望第一层具有更丰富的输入。 它使用5×5区域进行卷积,这允许它尝试在5×5区域内找到更有趣的更丰富的特征,然后出更大的输出(在这种情况下,它是10乘5乘5个滤波器)。 通常它是5乘5或7乘7,或甚至11乘11卷积,并且有相当多的滤波器出来(例如32个滤波器)。
* 由于`padding = kernel_size — 1 / 2`并且`stride=1` ,输入大小与输出大小相同 - 只是更多的过滤器。
* 这是尝试创造更丰富起点的好方法。
......@@ -548,7 +548,7 @@ CIFAR 10是学术界一个古老且众所周知的数据集 - 在ImageNet之前
```
* `ResnetLayer`继承自`BnLayer`并覆盖`forward`
* 然后添加一堆层并使它更深3倍,因为`x + super().forward(x)` ,它仍然训练得很漂亮。
* 然后添加一堆层并使它更深3倍,因为`x + super().forward(x)` ,它仍然训练得很漂亮。
```
learn = ConvLearner.from_model_data(Resnet([10, 20, 40, 80, 160], 10), data)
......@@ -604,7 +604,7 @@ _y = x + f(x)_
_f(x)= y - x_
差值_y - x_是**残差** 。 残差是我们到目前为止计算的误差。 这就是说,试图找到一组卷积权重,试图填补我们所关闭的数量。 换句话说,我们有一个输入,我们有一个功能,试图预测错误(即我们有多少关闭)。 然后我们添加一个对输入错误的预测,然后添加另一个我们错误的预测,并在层之后重复该层 - 缩放到正确的答案。 这是基于一种称为**助推**的理论。
差值_y - x_是**残差** 。 残差是我们到目前为止计算的误差。 这就是说,试图找到一组卷积权重,试图填补我们所关闭的数量。 换句话说,我们有一个输入,我们有一个功能,试图预测错误(即我们有多少关闭)。 然后我们添加一个对输入错误的预测,然后添加另一个我们错误的预测,并在层之后重复该层 - 缩放到正确的答案。 这是基于一种称为**助推**的理论。
* 完整的ResNet在将其添加回原始输入之前会进行两次卷积(我们在这里只做了一次)。
* 在每个块`x = l3(l2(l(x)))` ,其中一个层不是`ResnetLayer`而是`stride=2`的标准卷积 - 这称为“瓶颈层”。 ResNet不是卷积层,而是一种不同形式的瓶颈块,我们将在第2部分中介绍。
......@@ -703,7 +703,7 @@ _f(x)= y - x_
```
* `ConvLearner.from_model`是我们之前学到的 - 允许我们使用自定义模型创建一个Learner对象。
* 然后冻结除我们刚添加的图层之外的图层。
* 然后冻结除我们刚添加的层之外的层。
#### 类激活图(CAM) [[02:08:55](https://youtu.be/H3g26EVADgY%3Ft%3D2h8m55s)]
......@@ -715,7 +715,7 @@ _f(x)= y - x_
![](../img/1_DPIlEiNjJOeAbiIQUubNLg.png)
大数字对应猫。 那么这个矩阵是什么? 该矩阵简单地等于特征矩阵特征`py`量的值:
大数字对应猫。 那么这个矩阵是什么? 该矩阵简单地等于特征矩阵特征`py`量的值:
```
f2=np.dot(np.rollaxis( **feat** ,0,3), **py** ) f2-=f2.min() f2/=f2.max() f2
......@@ -745,7 +745,7 @@ _f(x)= y - x_
由于时间不多,我们很快就跳过了这个问题,但我们将在第2部分中详细了解这些方法。
“钩子”是让我们让模型返回矩阵的机制。 `register_forward_hook`要求PyTorch每次计算一个图层时都会运行给定的函数 - 有点像每次计算图层时发生的回调。 在下面的例子中,它保存了我们感兴趣的特定图层的值:
“钩子”是让我们让模型返回矩阵的机制。 `register_forward_hook`要求PyTorch每次计算一个层时都会运行给定的函数 - 有点像每次计算层时发生的回调。 在下面的例子中,它保存了我们感兴趣的特定层的值:
```
**class** **SaveFeatures** (): features= **None** **def** __init__(self, m): self.hook = m.register_forward_hook(self.hook_fn) **def** hook_fn(self, module, input, output): self.features = to_np(output) **def** remove(self): self.hook.remove()
......
......@@ -49,8 +49,8 @@ Jeremy喜欢建立模型的方式:
* 添加更多数据
* 添加更多数据增强
* 做更多批处理规范层,密集网络或可以处理更少数据的各种事情。
* 添加正规化,如权重衰减和辍学
* 做更多批处理规范层,密集网络或可以处理更少数据的各种事情。
* 添加正规化,如权重衰减和 Dropout
* 终于(这通常是人们先做的事情,但这应该是你最后做的事情)降低架构的复杂性。 具有较少的层数或较少的激活。
**5.嵌入[** [**07:46**](https://youtu.be/Z0ssNAbe81M%3Ft%3D7m46s) **]**
......
......@@ -197,7 +197,7 @@ _分类器_是具有因变量的任何分类或二项式。 与_回归_相反,
该体系结构将与我们用于分类器和边界框回归的体系结构相同,但我们将仅将它们组合在一起。 换句话说,如果我们有`c`类,那么我们在最后一层中需要的激活次数是4加`c` 。 4用于边界框坐标和`c`概率(每个类一个)。
这次我们将使用额外的线性层,加上一些辍学,以帮助我们训练更灵活的模型。 一般来说,我们希望我们的自定义头能够自己解决问题,如果它所连接的预训练骨干是合适的。 所以在这种情况下,我们试图做很多 - 分类器和边界框回归,所以只是单个线性层似乎不够。 如果你想知道为什么在第一个`ReLU`之后没有`BatchNorm1d` ,ResNet主干已经将`BatchNorm1d`作为其最后一层。
这次我们将使用额外的线性层,加上一些 Dropout ,以帮助我们训练更灵活的模型。 一般来说,我们希望我们的自定义头能够自己解决问题,如果它所连接的预训练骨干是合适的。 所以在这种情况下,我们试图做很多 - 分类器和边界框回归,所以只是单个线性层似乎不够。 如果你想知道为什么在第一个`ReLU`之后没有`BatchNorm1d` ,ResNet主干已经将`BatchNorm1d`作为其最后一层。
```
head_reg4 = nn.Sequential( Flatten(), nn.ReLU(), nn.Dropout(0.5), nn.Linear(25088,256), nn.ReLU(), nn.BatchNorm1d(256), nn.Dropout(0.5), nn.Linear(256, **4+len(cats)** ), ) models = ConvnetBuilder(f_model, 0, 0, 0, custom_head=head_reg4) learn = ConvLearner(md, models) learn.opt_fn = optim.Adam
......@@ -231,7 +231,7 @@ _分类器_是具有因变量的任何分类或二项式。 与_回归_相反,
**问题:**作为一般规则,在ReLU [[18:02](https://youtu.be/0frKXR-2PBY%3Ft%3D18m2s)] 之前或之后放置BatchNorm会更好吗? Jeremy建议将它放在ReLU之后,因为BathNorm意味着走向零均值的单标准偏差。 因此,如果你把ReLU放在它之后,你将它截断为零,这样就无法创建负数。 但是如果你把ReLU然后放入BatchNorm,它确实具有这种能力并且给出稍微好一些的结果。 话虽如此,无论如何都不是太大的交易。 你在课程的这一部分看到,大多数时候,Jeremy做了ReLU然后是BatchNorm,但是当他想要与论文保持一致时,有时则相反。
**问题** :BatchNorm之后使用dropout的直觉是什么? BatchNorm是否已经做好了正规化 [[19:12](https://youtu.be/0frKXR-2PBY%3Ft%3D19m12s)] 的工作? BatchNorm可以正常化,但如果你回想第1部分,我们讨论了一些事情,我们这样做是为了避免过拟合,添加BatchNorm就像数据增强一样。 但你完全有可能仍然过拟合。 关于辍学的一个好处是,它有一个参数来说明辍学的数量。 参数是特别重要的参数,决定了规则的多少,因为它可以让你构建一个漂亮的大参数化模型,然后决定规范它的程度。 Jeremy倾向于总是从`p=0`开始辍学,然后当他添加正则化时,他可以改变辍学参数而不用担心他是否保存了他想要能够加载它的模型,但如果他有在一个中丢弃层而在另一个中没有,它将不再加载。 所以这样,它保持一致。
**问题** :BatchNorm之后使用dropout的直觉是什么? BatchNorm是否已经做好了正规化 [[19:12](https://youtu.be/0frKXR-2PBY%3Ft%3D19m12s)] 的工作? BatchNorm可以正常化,但如果你回想第1部分,我们讨论了一些事情,我们这样做是为了避免过拟合,添加BatchNorm就像数据增强一样。 但你完全有可能仍然过拟合。 关于 Dropout 的一个好处是,它有一个参数来说明 Dropout 的数量。 参数是特别重要的参数,决定了规则的多少,因为它可以让你构建一个漂亮的大参数化模型,然后决定规范它的程度。 Jeremy倾向于总是从`p=0`开始 Dropout ,然后当他添加正则化时,他可以改变 Dropout 参数而不用担心他是否保存了他想要能够加载它的模型,但如果他有在一个中丢弃层而在另一个中没有,它将不再加载。 所以这样,它保持一致。
现在我们有输入和目标,我们可以计算L1损失并添加交叉熵 [[20:39](https://youtu.be/0frKXR-2PBY%3Ft%3D20m39s)] :
......@@ -421,7 +421,7 @@ _分类器_是具有因变量的任何分类或二项式。 与_回归_相反,
![](../img/1_fPHmCosDHcrHmtKvWFK9Mg.png)
第二种方法是使用`nn.linear`而不是使用`nn.linear` ,如果相反,我们从ResNet卷积主干中获取并添加了一个`nn.Conv2d`和stride 2 [[31:32](https://youtu.be/0frKXR-2PBY%3Ft%3D31m32s)] ? 这将给我们一个`4x4x[# of filters]`张量 - 这里让我们使它成为`4x4x(4+c)`这样我们得到一个张量,其中元素的数量正好等于我们想要的元素数量。 现在,如果我们创建了一个`4x4x(4+c)`张量的损失函数,并将其映射到图像中的16个对象,并检查每个对象是否通过这些`4+c`激活正确表示,这也可以。 事实证明,这两种方法实际上都在使用 [[33:48](https://youtu.be/0frKXR-2PBY%3Ft%3D33m48s)] 。 输出是来自完全连接的线性层的一个大长量的方法被称为[YOLO(You Only Look Once)](https://arxiv.org/abs/1506.02640)的一类模型使用,在其他地方,卷积激活的方法被以某些东西开始的模型使用称为[SSD(单发探测器)](https://arxiv.org/abs/1512.02325) 。 由于这些事情在2015年末非常相似,所以事情已经转向SSD。 所以今天早上, [YOLO版本3](https://pjreddie.com/media/files/papers/YOLOv3.pdf)出现了,现在正在做SSD,这就是我们要做的事情。 我们还将了解为什么这也更有意义。
第二种方法是使用`nn.linear`而不是使用`nn.linear` ,如果相反,我们从ResNet卷积主干中获取并添加了一个`nn.Conv2d`和stride 2 [[31:32](https://youtu.be/0frKXR-2PBY%3Ft%3D31m32s)] ? 这将给我们一个`4x4x[# of filters]`张量 - 这里让我们使它成为`4x4x(4+c)`这样我们得到一个张量,其中元素的数量正好等于我们想要的元素数量。 现在,如果我们创建了一个`4x4x(4+c)`张量的损失函数,并将其映射到图像中的16个对象,并检查每个对象是否通过这些`4+c`激活正确表示,这也可以。 事实证明,这两种方法实际上都在使用 [[33:48](https://youtu.be/0frKXR-2PBY%3Ft%3D33m48s)] 。 输出是来自完全连接的线性层的一个大长量的方法被称为[YOLO(You Only Look Once)](https://arxiv.org/abs/1506.02640)的一类模型使用,在其他地方,卷积激活的方法被以某些东西开始的模型使用称为[SSD(单发探测器)](https://arxiv.org/abs/1512.02325) 。 由于这些事情在2015年末非常相似,所以事情已经转向SSD。 所以今天早上, [YOLO版本3](https://pjreddie.com/media/files/papers/YOLOv3.pdf)出现了,现在正在做SSD,这就是我们要做的事情。 我们还将了解为什么这也更有意义。
#### 锚箱 [[35:04](https://youtu.be/0frKXR-2PBY%3Ft%3D35m04s)]
......@@ -441,7 +441,7 @@ _分类器_是具有因变量的任何分类或二项式。 与_回归_相反,
![](../img/1_IgL2CMSit3Hh9N2Fq2Zlgg.png)
进行一次激活(在这种情况下,在maxpool层中)让我们看看它来自哪里 [[38:45](https://youtu.be/0frKXR-2PBY%3Ft%3D38m45s)] 。 在excel中,你可以执行公式→跟踪先例。 一直追溯到输入层,你可以看到它来自图像的这个6 x 6部分(以及过滤器)。 更重要的是,中间部分有很多权重从外面的细胞出来只有一个权重出来的地方。 因此,我们将这个6 x 6细胞称为我们选择的一次激活的感受野。
进行一次激活(在这种情况下,在maxpool层中)让我们看看它来自哪里 [[38:45](https://youtu.be/0frKXR-2PBY%3Ft%3D38m45s)] 。 在excel中,你可以执行公式→跟踪先例。 一直追溯到输入层,你可以看到它来自图像的这个6 x 6部分(以及过滤器)。 更重要的是,中间部分有很多权重从外面的细胞出来只有一个权重出来的地方。 因此,我们将这个6 x 6细胞称为我们选择的一次激活的感受野。
![](../img/1_cCBVbJ2WjiPMlqX4nA2bwA.png)
......@@ -469,10 +469,10 @@ _分类器_是具有因变量的任何分类或二项式。 与_回归_相反,
**SSD_Head**
1. 我们从ReLU和辍学开始
1. 我们从ReLU和 Dropout 开始
2. 然后迈步1卷积。 我们从步幅1卷积开始的原因是因为它根本不会改变几何 - 它只是让我们添加一个额外的计算层。 它让我们不仅创建一个线性层,而且现在我们在自定义头中有一个小的神经网络。 `StdConv`在上面定义 - 它执行卷积,ReLU,BatchNorm和dropout。 你看到的大多数研究代码都不会定义这样的类,而是一次又一次地写出整个事物。 不要那样。 重复的代码会导致错误和理解不足。
3. 跨步2卷积 [[44:56](https://youtu.be/0frKXR-2PBY%3Ft%3D44m56s)]
4. 最后,步骤3的输出为`4x4` ,并传递给`OutConv``OutConv`有两个独立的卷积层,每个卷层都是步长1,因此它不会改变输入的几何形状。 其中一个是类的数量的长度(现在忽略`k``+1`是“背景” - 即没有检测到对象),另一个的长度是4.而不是有一个输出`4+c`转换层,让我们有两个转换层,并在列表中返回它们的输出。 这允许这些层专门化一点点。 我们谈到了这个想法,当你有多个任务时,他们可以共享图层,但他们不必共享所有图层。 在这种情况下,我们创建分类器以及创建和创建边界框回归的两个任务共享除最后一个层之外的每个层。
4. 最后,步骤3的输出为`4x4` ,并传递给`OutConv``OutConv`有两个独立的卷积层,每个卷层都是步长1,因此它不会改变输入的几何形状。 其中一个是类的数量的长度(现在忽略`k``+1`是“背景” - 即没有检测到对象),另一个的长度是4.而不是有一个输出`4+c`转换层,让我们有两个转换层,并在列表中返回它们的输出。 这允许这些层专门化一点点。 我们谈到了这个想法,当你有多个任务时,他们可以共享层,但他们不必共享所有层。 在这种情况下,我们创建分类器以及创建和创建边界框回归的两个任务共享除最后一个层之外的每个层。
5. 最后,我们弄平了卷积,因为杰里米写了损失函数,期望压低张量,但我们可以完全重写它不要那样做。
#### [Fastai编码风格](https://github.com/fastai/fastai/blob/master/docs/style.md) [[42:58](https://youtu.be/0frKXR-2PBY%3Ft%3D42m58s)]
......@@ -842,9 +842,9 @@ anc_grids = [4, 2, 1] anc_zooms = [0.75, 1., 1.3] anc_ratios = [(1., 1.), (1.,
![](../img/1_C67J9RhTAiz9MCD-ebpp_w.png)
* 我们有一个地面实况的向量(4个边界框坐标和一个类的集合)
* 我们有一个神经网络,需要一些输入并出一些输出激活
* 我们有一个神经网络,需要一些输入并出一些输出激活
* 比较激活和基本事实,计算损失,找出其衍生物,并根据学习率的微分时间调整权重。
* 我们需要一个能够接受基本事实和激活的损失函数,并出一个数字,说明这些激活有多好。 要做到这一点,我们需要取`m`基础事实对象中的每一个,并决定哪一组`(4+c)`激活对该对象负责 [[1:21:58](https://youtu.be/0frKXR-2PBY%3Ft%3D1h21m58s)] - 我们应该比较哪一个来决定是否该类是正确的,边界框是否接近(匹配问题)。
* 我们需要一个能够接受基本事实和激活的损失函数,并出一个数字,说明这些激活有多好。 要做到这一点,我们需要取`m`基础事实对象中的每一个,并决定哪一组`(4+c)`激活对该对象负责 [[1:21:58](https://youtu.be/0frKXR-2PBY%3Ft%3D1h21m58s)] - 我们应该比较哪一个来决定是否该类是正确的,边界框是否接近(匹配问题)。
* 由于我们使用的是SSD方法,所以我们匹配的不是任意的 [[1:23:18](https://youtu.be/0frKXR-2PBY%3Ft%3D1h23m18s)] 。 我们希望匹配一组激活,这些激活的感受野具有真实物体所在的最大密度。
* 损失函数需要是一些一致的任务。 如果在第一个图像中,左上角的对象与前4 + c激活相对应,而在第二个图像中,我们扔掉了东西,突然它现在正在进行最后的4 + c激活,神经网络不知道是什么学习。
* 解决匹配问题后,其余部分与单个对象检测相同。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册