《机器学习实战:基于Scikit-Learn、Keras和TensorFlow》第二版中文解读第十章

标题基于keras的人工神经网络的介绍


前言

鸟儿启发我们飞翔,牛蒡激发了魔术贴的灵感,大自然激发了无数的发明。因此,通过观察大脑的结构来获得如何建造智能机器的灵感似乎是合乎逻辑的。这就是引发人工神经网络(ANNs)的逻辑:ANN是由我们大脑中发现的生物神经元网络所激发而组成的机器学习模式。然而,尽管飞机的灵感来自鸟类,但它们不需要扇动翅膀。同样地,ann也逐渐变得与它们的表亲(人类大脑神经元)截然不同。一些研究人员甚至认为我们应该完全放弃生物学上的类比(例如,用“单元”而不是“神经元”),以免我们把创造力限制在生物学上可行的系统上. ANNs是深度学习的核心。它们是多用途的、强大的和可扩展的,这些因素使它们成为处理大型和高度复杂的机器的理想工具学习任务,如分类数十亿的图像(如谷歌图像),支持语音识别服务(如苹果的Siri),每天向数亿用户推荐最好的视频(如YouTube),或学习在围棋比赛中击败世界冠军(如DeepMind的)AlphaGo。 本章的第一部分介绍了人工神经网络,首先快速浏览了最早的神经网络架构,最后介绍了多层神经网络感知器(**MLPs**),目前被大量使用(其他架构将在下一章探讨).在第二部分中,我们将了解如何使用流行的**Keras API**实现神经网络。这是一个设计精美、简单的高级API,用于构建、培训、评估和运行神经网络。但是不要被它的简单所迷惑:它的表现力和灵活性足以让您构建各种各样的神经网络架构。事实上,对于您的大多数用例来说,它可能已经足够了。如果您需要额外的灵活性,您总是可以使用底层API编写定制的Keras组件,我们将在第12章中看到。但首先,让我们回到过去看看人工神经网络是如何产生的!

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

令人惊讶的是,ANN已经存在很长一段时间了:它最早是由神经生理学家Warren McCulloch和数学家Walter Pitts在1943年引入的。在他们具有里程碑意义的论文《的逻辑演算》中McCulloch和Pitts提出了一个简化的计算模型,用来描述生物神经元如何在动物大脑中协同工作,利用命题逻辑进行复杂的计算。这是第一个人工神经网络架构。从那时起,许多其他的架构被发明出来,政所我们所看到那样。
ANN的早期成功让人们普遍相信,我们很快就能与真正的智能机器对话了。到了20世纪60年代,这一承诺将无法实现(至少在相当一段时间内)的事实变得明朗起来,于是资金流向了其他地方,ANNs进入了一个漫长的冬天。在20世纪80年代早期,新的结构被发明出来,更好的训练技术被开发出来,引发了对联结主义(神经网络的研究)的兴趣的复兴。但进展缓慢,到了20世纪90年代,出现了其他强大的机器学习技术,如支持向量机(见第5章)。这些技术似乎比人工神经网络提供了更好的结果和更坚实的理论基础,因此,对神经网络的研究再次被搁置。
但是目前,有几点原因使我们对神经网络的信心重燃起来:

  • 大量的训练数据
  • 计算能力的巨大增长(GPU)
  • 训练算法的改进
  • 神经网络的一些理论局限性在实践中被证明是良性的
  • ANNs进入了资金和发展的良性循环

1.生物神经元

在我们讨论人工神经元之前,让我们快速看一下生物神经元(如图所示。正如我们高中生物课本上所描述的那样,它是一种外形奇特的细胞,主要存在于动物的大脑中。它是由一个包含细胞核的细胞体和细胞的大部分复杂成分,许多被称为树突的分支,加上一个非常长的延伸,被称为轴突。轴突的长度可能是细胞体的几倍,也可能是数万倍。靠近轴突的末端,轴突分裂成许多分支,这些分支的顶端是称为突触末端(或简称突触)的微小结构,它们与其他神经元的树突或细胞体相连。生物神经元产生称为动作电位(APs,简称信号)的短电脉冲,这些电脉冲沿着轴突传递,使突触释放称为神经递质的化学信号。当一个神经元在几毫秒内接收到足够数量的神经递质时,它就会发射自己的电脉冲(实际上,它取决于神经递质,因为它们中的一些可以抑制神经元的冲动)。生物神经元
因此,单个的生物神经元似乎以一种相当简单的方式活动,但它们是由数十亿个巨大的网络组织起来的,每个神经元通常与数千个其他神经元相连。高度复杂的计算可以由相当简单的神经元组成的网络来完成,就像简单蚂蚁的共同努力可以形成一个复杂的蚁丘一样。生物神经网络的结构(bnn)仍然是活跃的研究课题,但大脑的某些部分被映射,和神经元似乎经常组织在连续层,尤其是在大脑皮层(即你的大脑的外层),如图所示。
在这里插入图片描述

2.用神经元进行逻辑计算

McCulloch和Pitts提出了一个非常简单的生物神经元模型,后来被称为人工神经元:它有一个或多个二进制(开/关)输入和一个二进制输出。当超过一定数量的输入被激活时,人工神经元就会激活它的输出。在他们的论文中,他们展示了即使有这样一个简化的模型,也可以建立一个人工神经元网络来计算任何你想要的逻辑命题。为了了解这样的网络是如何工作的,让我们构建一些执行各种逻辑计算的ANN(见图),在这里我们假设一个神经元在至少两个输入是活跃的时候被激活。
在这里插入图片描述

  • 第一个神经元相当于恒等映射函数C=A
  • 第二个神经元相当于"与".即加法,当AB同时激活时C才激活
  • 第三个神经元是"或",仅需AB任意一个神经元是激活的,C就激活
  • 如图所示,第四个神经元是当A为激活.B不激活时候,C才激活

3.感知机

前向计算

感知机是一种最简单的ANN,如下图所示,有三个输入x1,x2,x3,它们想要进入一个逻辑单元里必须先与其对应的权值相乘,这里分别是**(w1,w2,w3),进入逻辑单元后相加到一起,然后经过一个阶跃函数**Step Function(也成激活函数Activation Function)后,得到最终的结果
在这里插入图片描述
常用激活函数:有Sigmoid、tanh、relu等,在这里我们用最简单的sgn函数
在这里插入图片描述
举个例子吧:
输入是x:1,2,3,对应的权值是w:1,-1,2,他们的结果相加就是1x1+2x(-1)+3x2=5,然后这个5进入了激活函数sgn,因为5>0,经过激活函数后这个逻辑单元给出的值就是1了.

上面我们使用一个逻辑单元得到一个输出,那如果我们有多个逻辑单元,有几个输出呢?答案显而易见,2个单元就有2个输出,3个就又3个,以此我们可以有很多个逻辑单元来进行我们的计算.

在这里要引入线性代数的概念了,因为我们有多个输出多个权值,把公式展开横着写估计要写很长(比如w1x2+w2x2+…+wnxn),但是我们用矩阵形式表示就会简单很多.
在这里插入图片描述
这里X对应的是输入矩阵,W对应的是权值矩阵,φ是激活函数,这样表示就简单很多了.

我们前面讨论了如何得出一个神经元的输出,那么只有输出我们也称不上学习呀,所以就要开始思考怎样用这个输出来影响后面的权值,逐渐调整权值来得到我们想要的完美结果.
那么感知器是如何训练的呢?Rosenblatt提出的感知器训练算法很大程度上受到了Hebbs规则的启发。在他1949年出版的《行为组织》(Wiley)一书中,Donald Hebb提出,当一个生物神经元经常触发另一个神经元时,这两个神经元之间的联系会变得更强。后来,齐格里德·洛维尔用一个朗朗上口的短语概括了赫布的观点:一起放电的细胞连接在一起;也就是说,当两个神经元同时放电时,它们之间的连接重量会增加。这个规则后来被称为赫伯规则(或赫伯学习)。感知器是用这个规则的一个变体来训练的,它考虑到网络在做预测时所犯的错误;感知器学习规则加强了有助于减少错误的联系。更具体地说,感知器每次输入一个训练实例,然后对每个实例进行预测。对于每一个产生错误预测的输出神经元,它都会加强来自输入的连接权重,而这些连接权重本来会有助于做出正确的预测。如公式所示
在这里插入图片描述

  • wi,j是神经元i和神经元j之间的连接权值
  • xi是第i个输入单元的当前输入值
  • yi是完美的输出值
  • ŷi是经过当前这个单元得到的输出值
  • η是学习率

我们进行学习的过程中,权值w是会根据我们的输入输出情况来调整的,如果我们的理想输出和实际输出的差值较大,w的调整大小也会较大.如果实际输出大了,w就要相应减小一点,这就是一个学习的过程.
多说无益,我们代码实战

import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import Perceptron #导入sklearn里面的感知机单元类
iris = load_iris()
X = iris.data[:, (2, 3)] # petal length, petal width
y = (iris.target == 0).astype(np.int) # Iris setosa?
per_clf = Perceptron()
per_clf.fit(X, y)
y_pred = per_clf.predict([[2, 0.5]])

4.多层感知机

有机器学习的知识小伙伴可能意识到,这不就是和梯度下降差不多吗,实际上sklearn的Perceptron等于SGDClassifier(loss=“perceptron”,learning_rate=“constant”, eta0=1,penalty=None).在简单问题上其实用逻辑回归更好,感知机是一个基于硬阈值的预测,一但你没达到那个阈值可能这个神经元就会把值给变成0,就啥都没有了.但是在复杂问题上,逻辑回归可能并不那么准确,我们又把目光放到了感知机上,其实感知机的层层堆叠形成所谓的多层感知机就可以处理很多复杂问题了.
在这里插入图片描述
如图所示,就是我们上面所描述的多个单元堆积起来的一个多层感知机MLP(Multilayer Perceptron),最上面是输出层,最下面的是输入层,而中间的我们通常称为隐层.1是我们的bias.

反向传播

1986年,David Rumelhart, Geoffrey Hinton和Ronald Williams发表了一篇开创性的论文,介绍了反向传播训练算法,这种算法至今仍在使用。简而言之,就是梯度下降使用一种有效的自动计算梯度的技术:在仅仅通过网络的两次(一个向前,一个向后),反向传播算法能够计算梯度的网络的误差对每一个单一的模型参数进行更新.
这个算法非常重要总的来说就是:对于每个训练实例,反向传播算法首先做一个预测(前向传递)并测量错误然后反向通过每一层来测量来自每个连接的错误贡献(反向传递),最后调整连接权重以减少错误(梯度下降)。想要了解详细内容推荐吴恩达老师的视频,讲的十分详细.
在MLP中我们不能再继续沿用上面那个简单的sgn激活函数,因为这个会导致梯度消失的问题,在这里我们采用sigmoid函数在这里插入图片描述
是不是看上去比较平滑,在0的邻域就可以很大程度避免梯度消失,还有其他激活函数也可以使用,比如relu函数虽然在0会有一个阶跃的梯度,但是它用来计算是十分快速的.
那么问题来了,我们为什么需要激活函数在我们的MLP中呢?
原因很简单,如果我们不用激活函数,无论你堆叠多少层,多深的网络,最终的计算也只是简单的线性计算,并没有像生物神经元那样有一个"激活"的作用.而在最后一层,我们通常是得到我们的输出结果,如果继续用sigmod函数就没有这么直观可以表达我们的输出,所以一般在线性任务中我们最后的输出层可以用一个Logistic激活,在多分类任务中我们可以用Softmax.而在反向传播中我们是通过一个LOSS function损失函数来计算我们的梯度
在这里插入图片描述

二、用Keras实现MLPs

1.安装

可以进入tf的官网按照对应的系统进行安装,这里就略过https://www.tensorflow.org/install/
这里给出keras的中文文档
https://keras.io/zh/
安装完毕后在IDLE上输入代码可以查看是否安装成功

>>> import tensorflow as tf
>>> from tensorflow import keras
>>> tf.__version__
'2.0.0'
>>> keras.__version__
'2.2.4-tf'

2.利用Sequential API来构建一个图像分类器

1).导入数据

fashion_mnist = keras.datasets.fashion_mnist
(X_train_full, y_train_full), (X_test, y_test) = fashion_mnist.load_data()

这里用可keras的datasets来导入fashion_mnist数据,详情可以查看keras文档,还有很多练手数据可以导入在这里插入图片描述

>>> X_train_full.shape
(60000, 28, 28)
>>> X_train_full.dtype
dtype('uint8')

训练数据有6W张 28x28像素大小的图片,编码是uint8编码
与以往机器学习的步骤一样,需要划分验证集:

X_valid, X_train = X_train_full[:5000] / 255.0, X_train_full[5000:] /
255.0
y_valid, y_train = y_train_full[:5000], y_train_full[5000:]

这里/255.0是为了把原始像素(0-255)变成(0-1)的范围内方便我们的激活函数工作.
由于Fashion MNIST有十个类别,而且分别是用数字表示,比如1代表T-shirt,所以我们要构建一个列表来方便表示标签

class_names = ["T-shirt/top", "Trouser", "Pullover", "Dress", "Coat",
"Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot"]

例如训练集的第一张图片标签为

>>> class_names[y_train[0]]
'Coat'

在这里插入图片描述

2).构建模型

现在我们可以开始构建一个MLP了!!!

model = keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=[28, 28]))
model.add(keras.layers.Dense(300, activation="relu"))
model.add(keras.layers.Dense(100, activation="relu"))
model.add(keras.layers.Dense(10, activation="softmax"
  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 25
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值