提交 dab131ff 编写于 作者: W wizardforcel

2020-09-07 10:55:47

上级 43de05e8
......@@ -30,7 +30,7 @@
# 问题定义
`MNIST`数据集已成为几乎规范的神经网络数据集。 该数据集由 60,000 个手写数字组成的图像,属于代表它们各自数字(10,1,2 ... 9)的 10 类。 由于此数据集变得如此普遍,因此许多深度学习框架都在 API 中内置了 MNIST 加载方法。 TensorFlow 和 Keras 都拥有一个,我们将使用 Keras MNIST 加载器使我们的生活更轻松。 但是,如果您想从原始数据中获取数据,或者想进一步了解 MNIST 的历史,可以在[这个页面](http://yann.lecun.com/exdb/mnist/)中找到更多信息。
`MNIST`数据集已成为几乎规范的神经网络数据集。 该数据集由 60,000 个手写数字组成的图像,属于代表它们各自数字`(0, 1, 2 ... 9)`的 10 类。 由于此数据集变得如此普遍,因此许多深度学习框架都在 API 中内置了 MNIST 加载方法。 TensorFlow 和 Keras 都拥有一个,我们将使用 Keras MNIST 加载器使我们的生活更轻松。 但是,如果您想从原始数据中获取数据,或者想进一步了解 MNIST 的历史,可以在[这个页面](http://yann.lecun.com/exdb/mnist/)中找到更多信息。
# 模型输入和输出
......@@ -38,9 +38,9 @@
# 拼合输入
每个输入观察都是一个 28 像素乘 28 像素的黑白图像。 像这样的一幅图像在磁盘上表示为 28x28 的矩阵,其值介于 0 到 255 之间,其中每个值都是该像素中黑色的强度。 至此,我们只知道如何在二维向量上训练网络(稍后我们将学习一种更好的方法); 因此我们将这个 28x28 矩阵展平为 1 x 784 输入向量。
每个输入观察都是一个 28 像素乘 28 像素的黑白图像。 像这样的一幅图像在磁盘上表示为`28x28`的矩阵,其值介于 0 到 255 之间,其中每个值都是该像素中黑色的强度。 至此,我们只知道如何在二维向量上训练网络(稍后我们将学习一种更好的方法); 因此我们将这个`28x28`矩阵展平为`1 x 784`输入向量。
一旦我们堆叠了所有这些 1x784 向量,就剩下 50,000 x 784 训练集。
一旦我们堆叠了所有这些`1x784`向量,就剩下`50,000 x 784`训练集。
如果您对卷积神经网络有丰富的经验,那么您可能现在正在翻白眼,如果您还没有,那么很快就会有更好的方法,但是不要太快地跳过本章。 我认为扁平化的`MNIST`是一个非常好的数据集,因为它的外观和行为与我们在许多投入领域(例如,物联网,制造业,生物,制药和医疗用例)中遇到的许多复杂的现实生活问题非常相似)。
......@@ -86,7 +86,7 @@
(train_X, train_y), (test_X, test_y) = mnist.load_data()
```
`train_X`的形状为 50,000 x 28 x28。正如我们在“模型输入和输出”部分中所述,我们将需要将 28x28 矩阵展平为 784 个元素向量。 NumPy 使这变得非常容易。 以下代码说明了此技术:
`train_X`的形状为`50,000 x 28 x 28`。正如我们在“模型输入和输出”部分中所述,我们将需要将`28x28`矩阵展平为 784 个元素向量。 NumPy 使这变得非常容易。 以下代码说明了此技术:
```py
train_X = train_X.reshape(-1, 784)
......@@ -139,7 +139,7 @@ prediction = Dense(10, activation='softmax', name="output")(x)
# Softmax 激活
想象一下,如果不是使用深层神经网络,而是使用`k` logistic 回归,其中每个回归都预测单个类中的成员。 逻辑回归的集合(每个类一个)如下所示:
想象一下,如果不是使用深层神经网络,而是使用`k`逻辑回归,其中每个回归都预测单个类中的成员。 逻辑回归的集合(每个类一个)如下所示:
![](img/692e8ef0-cac8-4075-88ce-2928f2998fc2.png)
......@@ -260,9 +260,9 @@ print(classification_report(test_y, y_hat))
# 通过辍学控制差异
减少深度神经网络过度拟合的一种非常好的方法是采用一种称为**丢弃法**的技术。 Dropout 完全按照其说的去做,它使神经元脱离隐藏层。 运作方式如下。
减少深度神经网络过度拟合的一种非常好的方法是采用一种称为**丢弃法**的技术。 丢弃法完全按照其说的去做,它使神经元脱离隐藏层。 运作方式如下。
通过每个小批量,我们将随机选择关闭每个隐藏层中的节点。 想象一下,我们在某个隐藏层中实施了 dropout,并且我们选择了 drop rate 为 0.5。 这意味着,对于每个小批量,对于每个神经元,我们都掷硬币以查看是否使用该神经元。 这样,您可能会随机关闭该隐藏层中大约一半的神经元:
通过每个小批量,我们将随机选择关闭每个隐藏层中的节点。 想象一下,我们在某个隐藏层中实施了丢弃,并且我们选择了丢弃率为 0.5。 这意味着,对于每个小批量,对于每个神经元,我们都掷硬币以查看是否使用该神经元。 这样,您可能会随机关闭该隐藏层中大约一半的神经元:
![](img/6bff492d-dbf6-4c35-aaef-2e8283c4afed.png)
......@@ -348,6 +348,6 @@ def build_network(input_features=None):
在本章中,我们实际上已经开始了解深度神经网络在进行多分类时的功能。 我们详细介绍了`softmax`功能,然后我们构建并训练了一个网络来将手写数字分为 10 个各自的类别。
最后,当我们注意到模型过度拟合时,我们尝试同时使用 dropout 和 L2 正则化来减少模型的方差。
最后,当我们注意到模型过度拟合时,我们尝试同时使用丢弃和 L2 正则化来减少模型的方差。
到目前为止,您已经看到深度神经网络需要很多选择,关于架构的选择,学习率,甚至是正则化率。 我们将在下一章中学习如何优化这些选择。
\ No newline at end of file
......@@ -74,7 +74,7 @@
**网格搜索**只是尝试尝试所有事物,或者至少尝试离散事物,然后报告我们用蛮力找到的最佳超参数的最佳组合。 可以保证在我们确定的参数空间中找到最佳解决方案,以及其他较差的解决方案。
网格搜索对于深度学习并不是很实用。 除了最基本的深度神经网络,我们无法现实地探索所有可能参数的每个可能值。 使用**随机搜索**,我们从每个参数分布中随机抽样,并尝试其中的`n`,其中(n x 每个示例训练时间)是我们愿意分配给这个问题的时间预算。
网格搜索对于深度学习并不是很实用。 除了最基本的深度神经网络,我们无法现实地探索所有可能参数的每个可能值。 使用**随机搜索**,我们从每个参数分布中随机抽样,并尝试其中的`n`,其中(`n x`每个示例训练时间)是我们愿意分配给这个问题的时间预算。
**贝叶斯优化**方法使用以前的观察结果来预测接下来要采样的超参数集。 尽管贝叶斯优化方法通常胜过蛮力技术,但目前的研究表明,与穷举方法相比,性能提升较小。 此外,由于贝叶斯方法取决于先前的经验,因此无论如何都不会令人尴尬地并行进行。
......@@ -104,7 +104,7 @@ def build_network(keep_prob=0.5, optimizer='adam'):
return model
```
在此示例中,我想搜索一个理想的 dropout 值,并且我想尝试几个不同的优化器。 为了实现这一点,我需要将它们作为参数包含在函数中,以便可以通过我们的随机搜索方法对其进行更改。 当然,我们可以使用相同的方法来参数化和测试许多其他网络体系结构选择,但是我们在这里保持简单。
在此示例中,我想搜索一个理想的丢弃值,并且我想尝试几个不同的优化器。 为了实现这一点,我需要将它们作为参数包含在函数中,以便可以通过我们的随机搜索方法对其进行更改。 当然,我们可以使用相同的方法来参数化和测试许多其他网络体系结构选择,但是我们在这里保持简单。
接下来,我们将创建一个函数,该函数返回一个字典,其中包含我们想搜索的所有可能的超参数及其值空间,如以下代码所示:
......@@ -137,7 +137,7 @@ search = RandomizedSearchCV(estimator=model, param_distributions=hyperparameters
拟合此`RandomizedSearchCV`对象后,它将从参数分布中随机选择值并将其应用于模型。 它将执行 10 次(`n_iter=10`),并且将尝试每种组合 3 次,因为我们使用了 3 倍交叉验证。 这意味着我们将总共拟合模型 30 次。 使用每次运行的平均准确性,它将返回最佳模型作为类属性`.best_estimator`,并且将返回最佳参数作为`.best_params_`
为了适合它,我们只需调用它的 fit 方法,就好像它是一个模型一样,如以下代码所示:
为了适合它,我们只需调用它的`fit`方法,就好像它是一个模型一样,如以下代码所示:
```py
search.fit(data["train_X"], data["train_y"])
......
......@@ -24,7 +24,7 @@
![](img/47bb2d29-6a4a-46d5-8193-51c49ee62817.jpg)
完成此操作后,我们将过滤器滑到一行上并执行相同的操作。 最后,我们将过滤器向下滑动,然后再次滑动。 卷积过程一旦完成,将使我们剩下 2x2 矩阵,如下图所示:
完成此操作后,我们将过滤器滑到一行上并执行相同的操作。 最后,我们将过滤器向下滑动,然后再次滑动。 卷积过程一旦完成,将使我们剩下`2x2`矩阵,如下图所示:
![](img/1ffeca84-f312-4324-bb86-19417a50f596.jpg)
......@@ -55,7 +55,7 @@ Conv2D(64, kernel_size=(3,3), activation="relu", name="conv_1")
假设我们确实使用了普通图层,以得到与之前讨论的相同的输出形状。 我们从`32 x 32 x 3`图像开始,所以总共有 3,072 个值。 我们剩下一个`30 x 30 x 64`矩阵。 总共有 57,600 个值。 如果我们要使用完全连接的层来连接这两个矩阵,则该层将具有 176,947,200 个可训练参数。 那是 1.76 亿。
但是,当我们使用上面的卷积层时,我们使用了 64 个`3 x 3 x 3`过滤器,这将导致 1,728 个可学习参数 +64 个偏差(总共 1,792 个参数)。
但是,当我们使用上面的卷积层时,我们使用了 64 个`3 x 3 x 3`过滤器,这将导致 1,728 个可学习权重加 64 个偏差(总共 1,792 个参数)。
因此,显然卷积层需要的参数要少得多,但是为什么这很重要呢?
......@@ -109,7 +109,7 @@ x = BatchNormalization(name="batch_norm_1")
CIFAR-10 数据集由属于 10 类的 60,000 张`32 x 32`彩色图像组成,每类 6,000 张图像。 我将使用 50,000 张图像作为训练集,使用 5,000 张图像作为验证集,并使用 5,000 张图像作为测试集。
卷积神经网络的输入张量层将为(N,32,32,3),我们将像以前一样将其传递给`build_network`函数。 以下代码用于构建网络:
卷积神经网络的输入张量层将为`(N, 32, 32, 3)`,我们将像以前一样将其传递给`build_network`函数。 以下代码用于构建网络:
```py
def build_network(num_gpu=1, input_shape=None):
......@@ -150,7 +150,7 @@ pool2 = MaxPooling2D(pool_size=(2, 2), name="pool_2")(batch2)
第二个块几乎相同。 但是,我将过滤器数量减半为 32。
尽管在该体系结构中有许多旋钮可以转动,但我首先要调整的是卷积的内核大小。 内核大小往往是一个重要的选择。 实际上,一些现代的神经网络架构(例如 Google 的**初始**)使我们可以在同一卷积层中使用多个过滤器大小。
尽管在该体系结构中有许多旋钮可以转动,但我首先要调整的是卷积的内核大小。 内核大小往往是一个重要的选择。 实际上,一些现代的神经网络架构(例如 Google 的 **Inception**)使我们可以在同一卷积层中使用多个过滤器大小。
# 全连接层
......@@ -269,7 +269,7 @@ model.fit(x=data["train_X"], y=data["train_y"],
在实践中,我们可以做的不仅仅是水平翻转。 当有意义时,我们也可以垂直翻转,移动和随机旋转图像。 这使我们能够人为地放大我们的数据集,并使它看起来比实际的更大。 当然,您只能将其推到目前为止,但这是在存在少量数据的情况下防止过度拟合的一个非常强大的工具。
# 硬 ImageDataGenerator
# Keras `ImageDataGenerator`
不久前,进行图像增强的唯一方法是对转换进行编码,并将其随机应用于训练集,然后将转换后的图像保存在磁盘上(上下坡,在雪中)。 对我们来说幸运的是,Keras 现在提供了`ImageDataGenerator`类,可以在我们训练时即时应用转换,而无需手工编码转换。
......@@ -292,7 +292,7 @@ def create_datagen(train_X):
如果您以前没有使用过生成器,则它就像迭代器一样工作。 每次调用`ImageDataGenerator` `.flow()`方法时,它都会产生一个新的训练小批量,并将随机变换应用于所馈送的图像。
Keras Model 类带有`.fit_generator()`方法,该方法使我们可以使用生成器而不是给定的数据集:
Keras `Model`类带有`.fit_generator()`方法,该方法使我们可以使用生成器而不是给定的数据集:
```py
model.fit_generator(data_generator.flow(data["train_X"], data["train_y"], batch_size=32),
......
......@@ -127,7 +127,7 @@ for layer in base_model.layers:
我们将首先从 [Kaggle](https://www.kaggle.com/c/dogs-vs-cats/data) 下载数据,然后将`train.zip`解压缩到本书的`Chapter08`目录中。 现在,您将拥有一个名为`train/`的目录,其中包含 25,000 张图像。 每个名称都将类似于`cat.number.jpg`
我们想移动这些数据,以便我们为 train,val 和 test 具有单独的目录。 这些目录中的每一个都应具有 cat and dog 目录。 这都是非常无聊且平凡的工作,因此,我创建了`data_setup.py`来为您执行此操作。 一旦运行它,数据将在本章的其余部分中全部格式化。
我们想移动这些数据,以便我们为训练,验证和测试创建单独的目录。 这些目录中的每一个都应具有猫和狗的目录。 这都是非常无聊且平凡的工作,因此,我创建了`data_setup.py`来为您执行此操作。 一旦运行它,数据将在本章的其余部分中全部格式化。
完成后,您将拥有一个具有以下结构的数据目录:
......@@ -137,7 +137,7 @@ for layer in base_model.layers:
快速浏览图像应使您确信我们的图像的分辨率和大小均不同。 正如您从第 7 章,“卷积神经网络”,所了解的那样,我们需要这些图像的大小与神经网络的输入张量一致。 这是一个非常现实的问题,您将经常面对计算机视觉任务。 虽然当然可以使用 [**ImageMagick**](http://www.imagemagick.org) 之类的程序来批量调整图像大小,但 Keras `ImageDataGenerator`类可用于快速调整图像大小,这就是我们要做的。
Inception-V3 期望 299 x 299 x 3 图像。 我们可以在数据生成器中指定此目标大小,如以下代码所示:
Inception-V3 期望`299 x 299 x 3`图像。 我们可以在数据生成器中指定此目标大小,如以下代码所示:
```py
train_datagen = ImageDataGenerator(rescale=1./255)
......
......@@ -147,7 +147,7 @@ LSTM 的另一个关键特性是内部自循环,使设备可以长期积累信
从可能可行的最简单模型开始。 有时这将是一个深层的神经网络,但通常情况会更简单一些,例如线性回归或 ARIMA 模型。 该模型的复杂性应通过其提供的提升来证明,通常越简单越好。 尽管整本书中多次重申,但在时间序列预测中,这一说法比其他任何话题都更为真实。
ARIMA 模型是三个部分的组合。 AR,即自回归部分,是根据自身的自相关性对序列进行建模的部分。 MA 部分尝试对时间序列中的本地突发事件或冲击建模。 I 部分涵盖了差异,我们刚刚介绍了差异。 ARIMA 模型通常采用三个超参数 p,d 和 q,分别对应于建模的自回归滞后的数量,微分度和模型的移动平均部分的顺序。
ARIMA 模型是三个部分的组合。 AR,即自回归部分,是根据自身的自相关性对序列进行建模的部分。 MA 部分尝试对时间序列中的本地突发事件或冲击建模。 I 部分涵盖了差异,我们刚刚介绍了差异。 ARIMA 模型通常采用三个超参数`p``d``q`,分别对应于建模的自回归滞后的数量,微分度和模型的移动平均部分的顺序。
ARIMA 模型在 R 的`auto.arima()`和预测包中实现得很好,这可能是使用 R 语言的唯一很好的理由之一。
......@@ -178,7 +178,7 @@ ARIMAX 模型允许在时间序列模型中包含一个或多个协变量。 您
1. 加载数据集并将纪元时间转换为熊猫日期时间。
2. 通过对日期范围进行切片来创建火车和测试集。
3. 区别我们的数据集。
4. 将差异缩放到更接近我们的激活功能的程度。 我们将使用-1 到 1,因为我们将使用`tanh`作为激活
4. 将差异缩放到更接近我们的激活功能的程度。 我们将使用 -1 到 1,因为我们将使用`tanh`作为激活
5. 创建一个训练集,其中每个目标`x[t]`都有一系列与之相关的滞后`x[t-1], ..., x[t-n]`。 在此训练集中,您可以将`x[t]`视为我们的典型因变量`y`。 滞后序列`x[t-1], ..., x[t-n]`可以看作是典型的`X`训练矩阵。
我将在接下来的主题中介绍每个步骤,并在进行过程中显示相关的代码。
......@@ -198,7 +198,7 @@ def read_data():
# 按日期切片和测试
现在,我们的数据帧已通过 datetime 时间戳编制索引,因此我们可以构造基于日期的切片函数。 为此,我们将定义一个布尔掩码,并使用该掩码选择现有的数据框。 虽然我们可以肯定地将其构造成一行,但我认为以这种方式阅读起来要容易一些,如以下代码所示:
现在,我们的数据帧已通过`datetime`时间戳编制索引,因此我们可以构造基于日期的切片函数。 为此,我们将定义一个布尔掩码,并使用该掩码选择现有的数据框。 虽然我们可以肯定地将其构造成一行,但我认为以这种方式阅读起来要容易一些,如以下代码所示:
```py
def select_dates(df, start, end):
......@@ -231,7 +231,7 @@ def diff_data(df):
# 缩放时间序列
在此示例中,我们将使用`MinMaxScaler`将每个差异数据点缩放为最小值为-1 且最大值为 1 的比例。这将使我们的数据与双曲线正切函数(`tanh` ),这是我们针对该问题的激活功能。 我们将使用以下代码缩放系列:
在此示例中,我们将使用`MinMaxScaler`将每个差异数据点缩放为最小值为 -1 且最大值为 1 的比例。这将使我们的数据与双曲线正切函数(`tanh` ),这是我们针对该问题的激活功能。 我们将使用以下代码缩放系列:
```py
......@@ -358,7 +358,7 @@ lstm2 = LSTM(100, activation='tanh', return_sequences=False,
output = Dense(1, activation='tanh', name='output')(lstm2)
```
要特别注意`return_sequences`参数。 连接两个 LSTM 层时,您需要前一个 LSTM 层来输出序列中每个时间步的预测,以便下一个 LSTM 层的输入是三维的。 但是,我们的 Dense 层仅需要二维输出即可预测其执行预测的确切时间步长。
要特别注意`return_sequences`参数。 连接两个 LSTM 层时,您需要前一个 LSTM 层来输出序列中每个时间步的预测,以便下一个 LSTM 层的输入是三维的。 但是,我们的密集层仅需要二维输出即可预测其执行预测的确切时间步长。
# 有状态与无状态 LSTM
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册