[机器学习实战] 阅读第十章

人工神经网络(ANN)

人工神经网络是深度学习的核心中的核心。它们通用、强大、可扩展,使得它成为解决大型和高度复杂的机器学习任务的理想选择。

通过第一个ANN架构的快速教程来介绍人工神经网络。

多层感知器(MLP)

从生物神经元到人工神经元

第一篇相关的论文,神经学家Warren McCulloch和数学家Walter Pitts提出
“A Logical Calculus of Ideas Immanent in Nervous Activity”(神经活动中内在思想的逻辑演算)
提出了一个简化过的计算模型来描述在动物的大脑中,神经元如何通过命题逻辑来实现复杂的计算。

ANN再次兴盛,:
1 在超大超复杂问题上ANN比其他的ML技术性能更佳。
2 飞速增长的计算能力使得在合理时间内训练大型神经网络成为可能。强大的GPU。
3 训练算法得到了很大提升。
4 ANN的一些理论限制在实践中被证明是可以接受的。
5 ANN似乎进入了资金和技术进步的良性循环。

生物神经元

神经元往往会按照连续的层次来组织。

具有神经元的逻辑计算

Warren McCulloch和Walter Pitts提出了一个生物神经元的简化模型,这种模型后来被称为人工神经元:它有一个或多个二进制(开/关)的输入和一个二进制输出。当一定量的输入都是激活状态时,人工神经元就会激活其输出。

感知器

线性阈值单元(LTU)

感知器是最简单的ANN架构之一。它基于一个稍微不同的被称为线性阈值单元(LTU)的人工神经元。
LTU会加权求和所有的输入(z=w1x1+w2x2+ …+wnxn=wT*x),然后对求值结果应用一个阶跃函数(step function)并产生最后的输出:hw(x)=step(z)=step(wT*x)。

感知器最常见的阶跃函数叫做Heaviside阶跃函数,有时候会使用带符号的函数。

阶跃函数是一种特殊的连续时间函数,是一个从0跳变到1的过程,属于奇异函数。
——https://baike.baidu.com/item/阶跃函数/7639820?fr=aladdin

公式10-1:感知器中常见的阶跃函数

在这里插入图片描述
Donald Hebb提到如果一个生物神经元总是触发另外的神经元,那么这两个神经元之间的连接就会变得更强。

这个想法后来被Siegrid Lowel总结为:同时处于激活状态的细胞是会连在一起的。

这个规律后来变成了著名的Hebb定律(又叫Hebbian学习):当两个神经元有相同的输出时,它们之间的连接权重就会增强。

感知器就是使用这个规则的变体进行训练,该变种还考虑了网络错误,对于导致错误输出的连接,它不会加强该连接的权重。更具体地说,感知器一次供给一个训练实例,并且对于每个实例它都会进行预测。对于产生错误预测的每个输出神经元,它加强了来自输入的连接权重,这将对正确的预测做出贡献。

公式10-2:感知器学习规则(权重更新)

在这里插入图片描述
在这里插入图片描述

感知器收敛定理

每个输出神经元的决策边界是线性的,所以感知器无法学习复杂的模式(这点和逻辑回归分类器一样)。Rosenblatt证明如果训练实例是线性可分的,这个算法会收敛到一个解。这被称为感知器收敛定理

Scikit-Learn提供了一个实现单一LTU网络的Perception(感知器)类。

import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import Perceptron

iris = load_iris()
X = iris.data[:, (2, 3)] # petal length, petal width
y = (iris.target == 0).astype(np.int) # Iris Setosa? 鸢尾花品种是山鸢尾吗
per_clf = Perceptron(random_state=42)
per_clf.fit(X, y)
y_pred = per_clf.predict([[2, 0.5]])

在Scikit-Learn里,Perceptron类的行为等同于使用以下超参数的SGDClassifier:loss=“perceptron”,learning_rate=“constant”,eta0=1(学习速率),以及penalty=None(不做正则化)

注意和逻辑回归分类器相反,感知器不输出某个类概率。它只能根据一个固定的阈值来做预测。这也是更应该使用逻辑回归而不是感知器的一个原因。

缺点:
无法处理一些很微小的问题,比如异或分类问题(XOR)。当然这个问题在其它任何线性分类模型中一样存在。

不过,事实证明感知器的一些限制可以通过将多个感知器堆叠起来的方式来消除,这种形式的ANN就是多层感知器(Multi-Layer Perceptron)。实践中,MLP可以解决异或问题。

多层感知器和反向传播

一个MLP包含一个(透传)输入层,一个或者多个被称为隐藏层的LTU层,以及一个被称为输出层的LTU组成的最终层。除了输出层以外,每层都包含了一个偏移神经元,并且与下一层完全相连。

如果一个ANN有2个以及2个以上的隐藏层,则被称为深度神经网络(DNN)。

反向自动微分的梯度下降法

反向传播训练算法,现在称其为使用了反向自动微分的梯度下降法

对于每一个训练实例,算法将其发送到网络中并计算每个连续层中的每个神经元的输出(这是正向过程,与做预测的过程一样)。然后它会度量网络的输出误差(对比期望值和实际的网络输出),然后它会计算最后一个隐藏层中的每个神经元对输出神经元的误差的贡献度。之后它继续测量这些误差贡献中有多少来自前一个隐藏层中的每个神经元,这个过程一直持续到输入层(也就是第一层)。这个反向传递过程通过在网络中向后传播误差梯度有效的测量网络中所有连接权重的误差梯度(这也是它名字的来源)。反向传播的正向和反向传递都只是简单的执行反向模式的自动微分。反向传播算法的最后一步是对网络中所有连接权重执行梯度下降法,使用之前度量的误差梯度。
在这里插入图片描述
在这里插入图片描述

https://www.cnblogs.com/lfri/p/10479353.html

Keras: Deep Learning for humans
https://github.com/keras-team/keras
Keras主页
https://keras.io/

n-1层中的误差有多少是来自n-2,n-2中的误差又有多少是来自n-3,一直反向迭代到第0层。

对于每个训练实例,反向传播算法先做一次预测(正向过程),度量误差,然后反向的遍历每个层来度量每个连接的误差贡献度(反向过程),最后再微调每个连接的权重来降低误差(梯度下降)。

为了让这个算法正常工作,作者对MLP架构做了一个关键的调整:把阶跃函数改成了逻辑函数σ(z)=1/(1+exp(-z))。这是非常关键的一步,因为阶跃函数只包含平面,所以没有梯度(梯度无法在平面上移动),但是逻辑函数则有着定义良好的偏导,梯度下降可以在每一步都做调整。处理逻辑函数,反向传播算法还可以和其他激活函数一起使用。

最流行的两个激活函数是:

双曲正切函数(z)=2σ(2z)-1
与逻辑函数类似,它是一个S形曲线,连续且可微分,不过它的输出是-1到1之间的值(逻辑是0到1之间的值),这会让每层的输出在训练开始时或多或少地标准化(以0为中心)。这通常有助于快速融合。

ReLU函数
ReLU(z)=max(0,z),这个函数也是连续的,不过在z=0时不可微分(坡度的突然变化可以使梯度下降反弹)。不过实践中它工作良好,而且计算速度很快。最重要的是,由于它没有输出最大值,对于消除梯度下降的一些问题很有帮助。

MLP常常被用来做分类,每个输出对应一个不同的二进制分类(比如,垃圾邮件/正常邮件、紧急/非紧急,等等)。当每个分类是互斥的情况下(比如将图片分类为数字0~9的场景),输出层通常被修改成一个共享的soft-max函数。每个神经元的输出对应于相应分类的估计概率。注意信号是单向流动的(从输入流向输出),所以这种架构是前馈神经网络(FNN)的一个范例。

在数学,尤其是概率论和相关领域中,Softmax函数,或称归一化指数函数,是逻辑函数的一种推广
——https://baike.baidu.com/item/Softmax函数/22772270?fr=aladdin
softmax激活函数详解
——https://www.cnblogs.com/alexanderkun/p/8098781.html

生物神经元貌似实现了一个粗糙的S形激活函数,所以研究者
花了很长时间在S形函数上。但事实证明,ReLU激活函数通常在
ANN中工作得更好,这是被生物类比误导的案例之一。

用TensorFlow的高级API来训练MLP

最简单的方式是使用它的高级API TF.Learn,这和Scikit-Learn的API非常相似。用DNNClassifier类来训练一个有着任意数量隐藏层,并包含一个用来计算类别概率的softmax输出层的深度神经网络都易如反掌。

#训练一个用于
#分类有两个隐藏层(一个有300个神经元,另一个有100个),以及一
#个softmax输出层的具有10个神经元的DNN

import tensorflow as tf

feature_columns = tf.contrib.learn.infer_real_valued_columns_from_input(X_train)
dnn_clf = tf.contrib.learn.DNNClassifier(hidden_units=
[300, 100], n_classes=10,
feature_columns=feature_columns)
dnn_clf.fit(x=X_train, y=y_train, batch_size=50, steps=40000)

DNNClassifier类基于ReLU激活函数(通过设置activation_fn超参数来调整)创建所有的神经元层次。输出层依赖于softmax函数,成本函数是交叉熵。

使用纯TensorFlow训练DNN

如果相对网络的架构有更多的控制,可以使用TensorFlow的低级python API。

构建阶段

从本地加载mnist数据集

https://www.cnblogs.com/ypzhai/p/9997856.html

对书中示例代码的分析:
https://blog.csdn.net/az9996/article/details/90412581

微调神经网络的超参数

可以使用具有交叉验证的网格搜索来查找正确的超参数。不过由于需要调整的超参数太多、训练神经网络模型很耗时,在有限的时间内,你可能只探索了很小一部分超参数。

随机搜索法会更好一些

还有一个选项是使用像Oscar这样的工具,它实现了更复杂的算法,帮助你更快的找出超参数集。

隐藏层的个数

人们发现只要神经元个数足够多,仅有一个隐藏层的MLP都可以建模大部分复杂的函数。

后来人们认识到深层网络比浅层网络有更高的参数效率:深层网络可以用非常少的神经元来建模复杂函数,因此训练起来更加迅速。

现实世界的数据往往会按照层次结构组织,而DNN天生的就很擅长处理这种数据:低级隐藏层用以建模底层结构(比如,各种形状和方向的线段),中级隐藏层组合这些低层结构来建模中层结构(比如,正方形、圆形等),高级隐藏层和输出层组合这些中层结构来建模高层结构(比如,人脸)

分层的架构不但可以帮助DNN更快的归纳出好方案,还可以提高对于新数据集的泛化能力。比如,你已经训练出一个可以识别人脸的模型,现在你想要训练一个新的模型来识别发型,你可以完全重用第一个模型中的低层神经网络。不必随机初始化新的网络中低层的权重和偏差,你可以直接用第一个网络的低层神经网络。这样新网络无须从头在图片中学习所有低层的结构,而只需要从高层结构学习即可(比如发型)。

对于大多数问题来说,只需要一个或两个隐藏层来处理(对于MNIST数据集,一个拥有数百个神经元的隐藏层就可以达到97%的精度,而用同样数量神经元构建的两层隐藏层就可以获得超过98%的精度,而且训练时间基本相同)。
对于更复杂的问题,你可以逐渐增减隐藏层的层次,直到在训练集上产生过度拟合。
非常复杂的问题,比如大图片的分类,或者语音识别,通常需要数十层的隐藏层(甚至数百层,非全连接的层),当然它们需要超大的训练数据集。不过,很少会从头构建这样的网络:更常见的是重用别人训练好的用来处理类似任务的网络。这样训练就会快很多,而且需要的数据量也会少很多。

每个隐藏层中的神经元个数

输入输出层中的神经元数由任务要求的输入输出类型决定。
例:MNIST任务需要28*28=784个输入神经元和10个输出神经元。

对于隐藏层来说,一个常用的实践是以漏斗型来定义其尺寸,每层神经元数依次减少:原因是许多低级功能可以合并成数量更少的高级功能。与层次的数量一样,你可以逐步添加神经元的数量,直到出现过度拟合。通常来说,通过增加每层的神经元数量比增加层数会产生更多的消耗。不幸的是,正如你所看到的,找到完美的神经元数量仍然是黑科技
一个更简单的做法是使用(比实际所需)更多的层次和神经元,然后提前结束训练来避免过度拟合(以及其他的正则化技术,特别是dropout)。这被称为“弹力裤”方法。无需花费时间找刚好适合你的裤子,随便挑弹力裤,它会缩小到合适的尺寸。

激活函数

大多数情况下,你可以在隐藏层中使用ReLU激活函数(或其变种)。它比其他激活函数要快一些,因为梯度下降对于大输入值没有上限,会导致它无法终止(与逻辑函数或者双曲正切函数刚好相反,它们会在1处饱和)。

对于输出层,softmax激活函数对于分类任务(如果分类是互斥的)来说是一个很不错的选择。对于回归任务,完全可以不使用激活函数

Convolutional Neural Networks(CNN)

对CNN中 输入层、卷积层、池化层、沉积层、全连接层(输出层)的理解
https://blog.csdn.net/az9996/article/details/90513877#Fully_connected_layers_55

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值