神经网络入门

1神经网络剖析

训练神经网络主要围绕以下四个方面
       层,多个层组合成网络(或模型)。
       输入数据和相应的目标。
       损失函数,即用于学习的反馈信号。
      优化器,决定学习过程如何进行。

       多个层链接在一起组成了网络,将输入数据映射为预测值。然后损失函数将这些预测值与目标进行比较,得到损失值,用于衡量网络预测值与预期结果的匹配程度。优化器使用这个损失值来更新网络的权重。

1.1层:深度学习的基础组件

神经网络的基本数据结构是层。

层是一个数据处理模块,将一个或多个输入张量转换为一个或多个输出张量。有些层是无状态的,但大多数的层是有状态的,即层的权重(利用随机梯度下降学到的一个或多个张量,其中包含网络的知识)。

不同的张量格式与不同的数据处理类型需要用到不同的层。

        1.简单的向量数据保存在形状为 (samples, features) 的 2D 张量中,通常用密集连接层[densely connected layer,也叫全连接层(fully connected layer)或密集层(dense layer),对应于 Keras 的 Dense 类]来处理。

        2.序列数据保存在形状为 (samples, timesteps, features) 的 3D 张量中,通常用循环
层(recurrent layer,比如 Keras 的 LSTM 层)来处理。

        3.图像数据保存在 4D 张量中,通常用二维卷积层(Keras 的 Conv2D )来处理。

       在 Keras 中,构建深度学习模型就是将相互兼容的多个层拼接在一起,以建立有用的数据变换流程。这里层兼容性(layer compatibility)具体指的是每一层只接受特定形状的输入张量,并返回特定形状的输出张量,向模型中添加的层都会自动匹配输入层的形状。

      第二层没有输入形状( input_shape )的参数,相反,它可以自动推导出输入形状等
于上一层的输出形状

1.2模型:层构成的网络

        深度学习模型是层构成的有向无环图。最常见的例子就是层的线性堆叠,将单一输入映射
为单一输出。
常见的网络拓扑结构:
        1.双分支(two-branch)网络
        2.多头(multihead)网络
        3.Inception 模块
        在预先定义好的可能性空间中,利用反馈信号的指引来寻找输入数据的有用表示。

1.3损失函数与优化器:配置学习过程的关键

确定了网络架构后,需要选择:
        1.损失函数(目标函数)——在训练过程中需要将其最小化(衡量当前任务是否已成功完成)
        2.优化器——决定如何基于损失函数对网络进行更新(执行的是随机梯度下降(SGD)的某个变体)

        梯度下降过程必须基于单个标量损失值。具有多个输出的神经网络可能具有多个损失函数(每个输出对应一个损失函数),这种网络,需要将所有损失函数取平均,变为一个标量值。

        网络的目的是使损失尽可能最小化,如果目标函数与成功完成当前任务不完全相关,那么网络最终得到的结果可能会不符合预期。

对于二分类问题,你可以使用二元交叉熵(binary crossentropy)损
失函数;对于多分类问题,可以用分类交叉熵(categorical crossentropy)损失函数;对于回归
问题,可以用均方误差(mean-squared error)损失函数;对于序列学习问题,可以用联结主义
时序分类(CTC,connectionist temporal classification)损失函数,

2Keras简介

目的:快速实验

特性:
        1.相同的代码可以在 CPU 或 GPU 上无缝切换运行。
        2.具有用户友好的 API,便于快速开发深度学习模型的原型。
        3.内置支持卷积网络(用于计算机视觉)、循环网络(用于序列处理)以及二者的任意组合。
        4.支持任意网络架构:多输入或多输出模型、层共享、模型共享等,能构建任意深度学习模型,无论是生成式对抗网络还是神经图灵机。
        5.Keras与所有版本的 Python 都兼容(从 Python 2.7 到 Python 3.6 都兼容)

        Keras 是一个模型级(model-level)的库,为开发深度学习模型提供了高层次的构建模块,依赖于一个专门的、高度优化的张量库(后端引擎)来完成运算,以模块化的方式处理这个问题(见图 3-3),开发过程可以无缝切换后端

        Keras 有三个后端实现:TensorFlow 后端(大部分深度学习任务的默认后端,应用最广泛,可扩展,而且可用于生产环境)、Theano 后端和微软认知工具包(CNTK,Microsoft cognitive toolkit)后端。

最常见的:单一损失函数

典型的 Keras 工作流程:
(1) 定义训练数据:输入张量和目标张量。
(2) 定义层组成的网络(或模型),将输入映射到目标。
(3) 配置学习过程:选择损失函数、优化器和需要监控的指标。
(4) 调用模型的 fit 方法在训练数据上进行迭代。

定义模型有两种方法:

一种是使用 Sequential 类(仅用于层的线性堆叠,这是目前最常见的网络架构)

另一种是函数式 API(functional API,用于层组成的有向无环图,构建任意形式的架构)。

利用函数式 API,可以操纵模型处理的数据张量,并将层应用于这个张量,好像这些层是函数一样

学习过程就是通过 fit() 方法将输入数据的 Numpy 数组(和对应的目标数据)传入模型

3建立深度学习工作站

 Windows 用户,最简单的解决方案就是安装 Ubuntu双系统

笔记本(notebook):

是 Jupyter Notebook 应用生成的文件,可以在浏览器中编辑。

可以执行 Python 代码,具有丰富的文本编辑功能,可以对代码进行注释。

可以将冗长的实验代码拆分为可独立执行的短代码,这使得开发具有交互性

4二分类问题

将结果分为正面与负面两种情况

4.1数据集

为什么要将训练集和测试集分开?使模型面对未知数据也能很准确

与 MNIST 数据集一样,IMDB 数据集也内置于 Keras 库

 train_labels 和 test_labels 都是 0 和 1 组成的列表,其中 0代表负面(negative),1 代表正面(positive)。

4.2准备数据

需要将列表转换为张量输入神经网络

转换方法有以下两种。
1.填充列表,使其具有相同的长度,再将列表转换成形状为 (samples, word_indices)
的整数张量,然后网络第一层使用能处理这种整数张量的层(即 Embedding 层)。

2.对列表进行 one-hot 编码,将其转换为 0 和 1 组成的向量。举个例子,序列 [3, 5] 将会
被转换为 10 000 维向量,只有索引为 3 和 5 的元素是 1,其余元素都是 0。然后网络第
一层可以用 Dense 层,它能够处理浮点数向量数据。

4.3构建网络

输入数据是向量,而标签是标量(1 和 0)

带有 relu 激活的全连接层( Dense )的简单堆叠在二分类问题上表现很好

传入 Dense 层的参数(16)是该层隐藏单元的个数。

一个隐藏单元(hidden unit)是该层表示空间的一个维度。

每个带有 relu 激活的 Dense 层都实现了下列张量运算:output = relu(dot(W, input) + b)

16 个隐藏单元对应的权重矩阵 W 的形状为 (input_dimension, 16) ,与 W 做点积相当于
将输入数据投影到 16 维表示空间中(然后再加上偏置向量 b 并应用 relu 运算)。

可以将表示空间的维度直观地理解为“网络学习内部表示时所拥有的自由度”。隐藏单元越多(即更高维的表示空间),网络越能够学到更加复杂的表示,但网络的计算代价也变得更大,而且可能会导致学到不好的模式(这种模式会提高训练数据上的性能,但不会提高测试数据上的性能)。

对于这种 Dense 层的堆叠,需要确定以下两个关键架构:
1.网络有多少层;
2.每层有多少个隐藏单元。

需要相信下列架构:
        两个中间层,每层都有 16 个隐藏单元;
        第三层输出一个标量,预测当前评论的情感。
中间层使用 relu 作为激活函数,最后一层使用 sigmoid 激活以输出一个 0~1 范围内的概率
值(表示样本的目标值等于 1 的可能性,即评论为正面的可能性)。

relu (rectified linear unit,整流线性单元)函数将所有负值归零

 sigmoid 函数则将任意值“压缩”到 [0,1] 区间内,其输出值可以看作概率值。

激活函数

 最后选择损失函数和优化器

由于是一个二分类问题,网络输出是一个概率值(网络最后一层使用 sigmoid 激活函数,仅包含一个单元),最好使用 binary_crossentropy (二元交叉熵)损失,还可以使用 mean_squared_error (均方误差)。但对于输出概率值的模型,交叉熵(是来自于信息论领域的概念,用于衡量概率分布之间的距离)往往是最好的选择。

例:用 rmsprop 优化器和 binary_crossentropy 损失函数来配置模型

上述代码将优化器、损失函数和指标作为字符串传入,这是因为 rmsprop 、 binary_
crossentropy 和 accuracy 都是 Keras 内置的一部分。有时希望配置自定义优化器的参数(可通过向 optimizer 参数传入一个优化器类实例来实现,如代码清单 3-5 所示)

 或者传入自定义的损失函数或指标函数(后者可通过向 loss 和 metrics 参数传入函数对象来实现,如代码清单 3-6 所示)。

4.4验证

为了在训练过程中监控模型在前所未见的数据上的精度,需将原始训练数据留出样本作为验证集。

 

调用 model.fit() 返回一个 History 对象,有一个成员 history (一个字典)包含训练过程中所有数据 

字典中包含 4 个条目,对应训练过程和验证过程中监控的指标。由于网络的随机初始化不同,结果可能会略有不同。 

使用 Matplotlib 在同一张图上绘制训练损失和验证损失(见图 3-7)

以及训练精度和验证精度(见图 3-8)

 训练损失每轮都在降低,训练精度每轮都在提升。这就是梯度下降优化的预期结果——你想要最小化的量随着每次迭代越来越小。但验证损失和验证精度并非如此:似乎在第四轮达到最佳值。

模型在训练数据上的表现越来越好,但在前所未见的数据上不一定表现得越来越好。准确地说,是过拟合(overfit):在第二轮之后,对训练数据过度优化,最终学到的表示仅针对于训练数据,无法泛化到训练集之外的数据。为了防止过拟合,你可以在 3 轮之后停止训练。

4.5生成结果

用 predict 方法来得到评论为正面的可能性大小,预测所需结果出现的可能性大小

4.6进一步实验

通过以下实验,可以确信前面选择的网络架构是非常合理的,虽然仍有改进的空间。
前面使用了两个隐藏层。你可以尝试使用一个或三个隐藏层,然后观察对验证精度和测
试精度的影响。
尝试使用更多或更少的隐藏单元,比如 32 个、64 个等。
尝试使用 mse 损失函数代替 binary_crossentropy 。
尝试使用 tanh 激活(这种激活在神经网络早期非常流行)代替 relu 。

4.7小结

应该从这个例子中学到的要点。
通常需要对原始数据进行大量预处理,以便将其转换为张量输入到神经网络中。单词序
列可以编码为二进制向量,但也有其他编码方式。
带有 relu 激活的 Dense 层堆叠,可以解决很多种问题(包括情感分类),你可能会经
常用到这种模型。
对于二分类问题(两个输出类别),网络的最后一层应该是只有一个单元并使用 sigmoid
激活的 Dense 层,网络输出应该是 0~1 范围内的标量,表示概率值。
对于二分类问题的 sigmoid 标量输出,你应该使用 binary_crossentropy 损失函数。
无论你的问题是什么, rmsprop 优化器通常都是足够好的选择。这一点你无须担心。
随着神经网络在训练数据上的表现越来越好,模型最终会过拟合,并在前所未见的数据
上得到越来越差的结果。一定要一直监控模型在训练集之外的数据上的性能。

5多分类问题

因为有多个类别,所以这是多分类(multiclass classification)问题的一个例子。

因为每个数据点只能划分到一个类别,所以,这是单标签、多分类(single-label, multiclass classification)问题的一个例子。

如果每个数据点可以划分到多个类别(主题),那它就是一个多标签、多分类(multilabel,
multiclass classification)问题。

5.1数据集

与 IMDB 和 MNIST 类似,路透社数据集也内置为 Keras 的一部分

5.2准备数据

将标签向量化有两种方法:

可以将标签列表转换为整数张量,或者使用 one-hot 编码。

one-hot 编码是分类数据广泛使用的一种格式,也叫分类编码(categorical encoding)。在这个例子中,标签的one-hot编码就是将每个标签表示为全零向量,只有标签索引对应的元素为 1。

5.3构建网络

对于 Dense 层的堆叠,每层只能访问上一层输出的信息。如果某一层丢失了与分类问题相关的一些信息,那么这些信息无法被后面的层找回,也就是说,每一层都可能成为信息瓶颈。维度较小的层可能成为信息瓶颈,无法区分类别,永久地丢失相关信息。

关于这个架构还应该注意
网络的最后一层是大小为 46 的 Dense 层。这意味着,对于每个输入样本,网络都会输
出一个 46 维向量。这个向量的每个元素(即每个维度)代表不同的输出类别。
最后一层使用了 softmax 激活。网络将输出在 46个不同输出类别上的概率分布——对于每一个输入样本,网络都会输出一个 46 维向量,其中 output[i] 是样本属于第 i 个类别的概率。46 个概率的总和为 1。
        对于这个例子,最好的损失函数是 categorical_crossentropy (分类交叉熵)。它用于
衡量两个概率分布之间的距离,这里两个概率分布分别是网络输出的概率分布和标签的真实分
布。通过将这两个分布的距离最小化,训练网络可使输出结果尽可能接近真实标签。 

5.4验证

 

 

5.5生成结果

5.6处理标签和损失的另一种方法

对于另一种编码方法,将其转换为整数张量,唯一需要改变的是损失函数的选择。对于代码清单 3-21 使用的损失函数 categorical_crossentropy ,标签应该遵循分类编码。对于整数标签,你应该使用 

5.7中间层维度足够大的重要性

现在网络的验证精度下降的主要原因在于,将大量信息(这些信息足够恢复 46 个类别的分割超平面)压缩到维度很小的中间空间。网络能够将大部分必要信息塞入这个四维表示中,但并不是全部信息。

5.8进一步实验

尝试使用更多或更少的隐藏单元,比如 32 个、128 个等。
前面使用了两个隐藏层,现在尝试使用一个或三个隐藏层。

5.9小结

下面是这个例子中学到的要点。
如果要对 N 个类别的数据点进行分类,网络的最后一层应该是大小为 N 的 Dense 层。
对于单标签、多分类问题,网络的最后一层应该使用 softmax 激活,这样可以输出在 N
个输出类别上的概率分布。
这种问题的损失函数几乎总是应该使用分类交叉熵。它将网络输出的概率分布与目标的
真实分布之间的距离最小化。
处理多分类问题的标签有两种方法。
通过分类编码(也叫 one-hot 编码)对标签进行编码,然后使用 categorical_
crossentropy 作为损失函数。
将标签编码为整数,然后使用 sparse_categorical_crossentropy 损失函数。
如果你需要将数据划分到许多类别中,应该避免使用太小的中间层,以免在网络中造成
信息瓶颈。

6回归问题

不要将回归问题与 logistic 回归算法混为一谈。logistic 回归不是回归算法,而是分类算法。

6.1数据集

要预测 20 世纪 70 年代中期波士顿郊区房屋价格的中位数,已知当时郊区的一些数据点,比如犯罪率、当地房产税率等。本节用到的数据集包含的数据点相对较少,输入数据的每个特征(比如犯罪率)都有不同的取值范围

6.2准备数据

将取值范围差异很大的数据输入到神经网络中,这是有问题的。网络可能会自动适应这种
取值范围不同的数据,但学习肯定变得更加困难。对于这种数据,普遍采用的最佳实践是对每
个特征做标准化,即对于输入数据的每个特征(输入数据矩阵中的列),减去特征平均值,再除
以标准差,这样得到的特征平均值为 0,标准差为 1。用 Numpy 可以很容易实现标准化。

注意,用于测试数据标准化的均值和标准差都是在训练数据上计算得到的。在工作流程中,
你不能使用在测试数据上计算得到的任何结果

6.3构建网络

由于样本数量很少,将使用一个非常小的网络,其中包含两个隐藏层,每层有 64 个单元。

一般来说,训练数据越少,过拟合会越严重,而较小的网络可以降低过拟合。

        网络的最后一层只有一个单元,没有激活,是一个线性层。这是标量回归(标量回归是预
测单一连续值的回归)的典型设置。添加激活函数将会限制输出范围。例如,如果向最后一层
添加 sigmoid 激活函数,网络只能学会预测 0~1 范围内的值。这里最后一层是纯线性的,所以
网络可以学会预测任意范围内的值。
        注意,编译网络用的是 mse 损失函数,即均方误差(MSE,mean squared error),预测值与目标值之差的平方。这是回归问题常用的损失函数。
        在训练过程中还监控一个新指标:平均绝对误差(MAE,mean absolute error)。它是预测值与目标值之差的绝对值。

6.4验证

        验证分数可能会有很大波动,这取决于你所选择的验证集和训练集,验证集的划分方式可能会造成验证分数上有很大的方差,这样就无法对模型进行可靠的评估。
        在这种情况下,最佳做法是使用 K 折交叉验证(见图 3-11)。将可用数据划分为 K个分区(K 通常取 4 或 5),实例化 K 个相同的模型,将每个模型在 K-1 个分区上训练,并在剩下的一个分区上进行评估。模型的验证分数等于 K 个验证分数的平均值。

        每次运行模型得到的验证分数有很大差异,平均分数是比单一分数更可靠的指标——这就是 K 折交叉验证的关键。让训练时间更长一点,为了记录模型在每轮的表现,修改训练循环,以保存每轮的验证分数记录。

纵轴的范围较大,且数据方差相对较大,所以难以看清这张图的规律。重新绘制一张图。
删除前 10 个数据点,因为它们的取值范围与曲线上的其他点不同。
将每个数据点替换为前面数据点的指数移动平均值,以得到光滑的曲线 

 

6.5小结

下面是你应该从这个例子中学到的要点。
回归问题使用的损失函数与分类问题不同。回归常用的损失函数是均方误差(MSE)。
同样,回归问题使用的评估指标也与分类问题不同。显而易见,精度的概念不适用于回
归问题。常见的回归指标是平均绝对误差(MAE)。
如果输入数据的特征具有不同的取值范围,应该先进行预处理,对每个特征单独进行
缩放。
如果可用的数据很少,使用 K 折验证可以可靠地评估模型。
如果可用的训练数据很少,最好使用隐藏层较少(通常只有一到两个)的小型网络,以
避免严重的过拟合。

总结

现在可以处理关于向量数据最常见的机器学习任务:二分类问题、多分类问题和标
量回归问题。

学到的要点:
在将原始数据输入神经网络之前,通常需要对其进行预处理。
如果数据特征具有不同的取值范围,那么需要进行预处理,将每个特征单独缩放。
随着训练的进行,神经网络最终会过拟合,并在前所未见的数据上得到更差的结果。
如果训练数据不是很多,应该使用只有一两个隐藏层的小型网络,以避免严重的过拟合。
如果数据被分为多个类别,那么中间层过小可能会导致信息瓶颈。
回归问题使用的损失函数和评估指标都与分类问题不同。
如果要处理的数据很少,K 折验证有助于可靠地评估模型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值