前言
神经网络作为如今机器学习的主流方法论,也是自动缺陷识别中的重要技术,它的历史、原理因何而来?它又是如何进行应用的?本文通过一个简单的识别案例进行了概述。
神经网络基础想要了解人工神经网络(ArtificialNeuralNetwork,ANN),需要先从组成神经网络的神经元讲起。19世界末20世纪初,卡米洛·高尔基、圣地亚哥·拉蒙·卡哈尔等人通过染色法发现生物体中的神经元后,研究者对其结构和功能进行了深入的研究,发现神经元细胞有树突和轴突两种突起:树突短而分枝多,直接由细胞体扩张突出,形成树枝状,可以接受来自其他神经元轴突的神经冲动,并传递给细胞体,当神经元接收到足够多的神经冲动后,它就处于兴奋状态,产生电脉冲;轴突长而分枝少,为粗细均匀的细长突起,可以将细胞体产生电脉冲传递给其他神经元。
根据生物神经元的这一结构,年心理学家沃伦·麦卡洛克(WarrenMcCulloch)和数学家沃尔特·皮茨(WalterPitts)提出了MP神经元模型,在该模型中,神经元接受n个输入信号
、
、
……
,按照一定权重将所有输入求和后,通过激活函数(ActivationFunction)
处理后,就获得了神经元的输出
如图1所示。
图1、MP神经元模型
可能出乎很多人意料的是,现代神经网络中的神经元和MP神经元的结构并无太多变化,最大的区别是使用的激活函数不同,MP神经元中使用的是跃迁函数,如图2所示,它将输入值映射为输出值“0”或“1”,分别对应生物神经元抑制状态和兴奋状态。现代神经网络中的神经元中使用的激活函数通常要求是连续可导的,以便于使用基于梯度下降的方法对神经元参数的优化,常用的激活函数有Sigmoid函数、ReLU函数等。另一方面上,MP神经元的权重、阈值需要研究者提前设定好,而现代神经网络中的神经元参数通常都是使用梯度反向传播训练的方式得到的,毕竟在现代神经网络中,往往有成千上万的神经元,人工设定每个神经元的参数几乎是不可能实现的,这是MP神经元与现代神经元之间在思想上的重大差别。
图2、跃迁函数
MP神经元可以用于构建感知机。感知机由两层神经元组成,输入层和输出层。输入层用于接收信号,输出层使用MP神经元,用于处理从输入层获得的信号以获得输出信号。对于简单的逻辑运算就可以使用感知机实现。比如对于一个“与”的逻辑运算,两个输入都为1时,输出1,否则输出0,其真值表如表1所示。
表1、“与”操作的真值表
如何构建一个使用跃迁函数作为激活函数的感知机呢?关键在于选取MP神经元的参数(权重和偏置),这里我们选择一组参数
=0.5,
=0.5,
=-0.8,感知机结构如图3所示。
图3、感知机结构
类似地,对于“或”的逻辑运算,只要有一个输入信号是1,输出就为1,否则输出0,其真值表如表2所示,可以为MP神经元选取如下参数
=0.5,
=0.5,
=-0.3,即可解决“或”的逻辑运算问题。
表2、“或”操作的真值表
对于“异或”的逻辑运算,仅当
或
中的一方为1时,才会输出1,真值表如表3所示,由于“异或”问题属于线性不可分问题,此时使用单层感知器模型就无法解决了。要想解决这一问题,可以增加感知机的层数,在输入层和输出层中间增加一层神经元,即隐藏层,就能增强感知机的表达能力,如图4所示,此时感知机中三个MP神经元的参数分别是
=1,
=-1,
=-0.5;
=-1,
=1,
=-0.5;
=1,
=1,
=-0.5。
表3、“异或”操作的真值表
图4、“异或”的逻辑运算的感知机结构
在此基础上,可以增加隐藏层的数量,并调整每个隐藏层中神经元的个数(输入层和输出层的神经元数量是确定的),即形成多层感知器(Multi-LayerPerceptron,MLP)。更一般的,使用连续激活函数的多层感知器,各神经元分别属于不同的层。每一层的神经元可以接收前一层神经元的信号,并产生信号输出到下一层。第一层称为输入层,最后一层称为输出层,其他中间层称为隐藏层。整个网络中没有同层连接,也没有跨层连接,信号从输入层向输出层单向传播,称之为多层前馈神经网络,如图5所示。
图5、多层前馈神经网络
根据通用近似定理(Universalapproximationtheorem),前馈神经网络可以用来近似任意函数的,并且可以达到任意近似精准度。但它并没有告诉我们如何选择神经网络参数(权重、神经元数量、神经层层数等等)来达到我们想近似的目标函数。在实际的应用中,通过增加神经元数量和神经网络层数,可以增加神经网络的拟合能力,但是这样很容易出现过拟合的问题,需要使用者根据情况不断调整神经网络的结构,直至获得合适的网络结构。
我们以MNIST手写数字图片数据集为例,介绍前馈神经网络的应用。MNIST数据集共包含0~9共10类数字,每个类别有张图片。这些数字已经通过尺寸标准化并位于图像中心,图像是固定大小(28×28像素),如图6所示。对于人类来说,能轻而易举的分辨出每张图片上的数字是什么,但是如何让机器也能分辨出图片上的数字呢?我们通过建立一个前馈神经网络来实现这一点,其包含一个输入层,一个输出层和一个隐藏层,结构如图7所示。这里为简单起见,模型输入的每张图像都被平展并转换为(28×28)的一维向量,因此输入层包含个神经元,代表28×28图像中每个像素的值,输入层包含10个神经元,使用Softmax激活函数,代表图像属于0~9这10个数字的概率,中间的隐藏层包含个神经元,使用ReLU激活函数。可以看出,该网络的结构与之前解决“异或”问题的感知器的结构十分类似,都是单隐藏层的前馈神经网络,区别在于神经网络中每层神经元的数量不同,以及使用的激活函数不同。
图6、MNIST数据集的输入样例
图7、手写数字识别网络
这里我们使用keras(一个用Python编写的高级神经网络API)来建立上述的神经网络。
fromtensorflow.keras.modelsimportSequential
fromtensorflow.keras.layersimportDense,Dropout
fromtensorflow.python.keras.utilsimportnp_utils
fromtensorflow.keras.datasetsimportmnist
#载入数据
(X_train,y_train),(X_test,y_test)=mnist.load_data()
#将X展开为向量,并归一化
X_train=X_train.reshape(len(X_train),-1)
X_test=X_test.reshape(len(X_test),-1)
X_train=X_train.astype(float32)/
X_test=X_test.astype(float32)/
#将y展开为one-hot变量
y_train=np_utils.to_categorical(y_train)
y_test=np_utils.to_categorical(y_test)
#使用Sequential构架网络
model=Sequential()
model.add(Dense(,input_shape=(28*28,),activation=relu))
model.add(Dropout(0.5))
model.add(Dense(10,activation=softmax))
model.