一、神经网络基础
神经网络(Neural Network)最早由心理学家和神经学家开创,旨在寻求开发和检验神经的计算模拟。它是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能模拟生物神经系统对真实世界物体所作出的交互反应。今天的“神经网络”已是一个相当大的、多学科交叉的学科领域。神经网络可以用于分类(预测给定元组的类标号)和数值预测(预测连续值输出)等。
神经元模型
神经网络中最基本的成分是神经元(Neuron)模型。生物神经网络中的每个神经元彼此互连,当它“兴奋”时,就会向相连的神经元发送化学物质,从而改变这些神经元内的电位。如果某神经元的电位超过一个阈值,它就会被激活,即“兴奋”起来,向其他神经元发送化学物质。
1943年,美国心理学家麦卡洛克(McCulloch)和数学家皮特斯(Pitts)按照生物神经元的结构和工作原理建立了M-P模型。在M-P模型中,为了使得建模更加简单,以便于进行形式化表达,我们忽略时间整合作用、不应期等复杂因素,并把神经元的突触时延和强度设为常数。M-P神经元模型如图:
M-P神经元模型和生物神经元的特性比较:
由于累加性,对全部输入信号进行累加整合,相当于生物神经元中的膜电位,其值为:
感知机与多层网络
感知机(Perceptron)由两层神经元组成,如图9-3所示。这个结构非常简单,它其实就是输入输出两层神经元之间的简单连接。
感知机(Perceptron)
1957年由Rosenblatt提出,是神经网络与支持向量机的基础;
输入为特征向量,输出为实例的类别,取+1和-1;
感知机对应于输入空间中将实例划分为正负两类的超平面,属于判别模型;
导入基于误分类的损失函数;
利用梯度下降法对损失函数进行极小化;
感知机学习算法具有简单而易于实现的优点,分为原始形式和对偶形式。
要解决非线性可分问题需要使用多层感知器(多层网络)来解决。多层感知机(Multilayer Perceptron,MLP)除了输入输出层,中间可以有多个隐层。最简单的MLP只含一个隐层,即三层的结构。更一般的,常见的神经网络是形如图9.4所示的机构这样的网络结构通常称为多层前馈神经网络(Multi-layer Feedforward Neural Networks)。
二、BP神经网络
多层网络的学习能力比单层感知机强很多,要训练多层网络,简单的感知机学习规则显然不够,需要更强大的学习算法。误差逆传播(Error BackPropagation)算法就是学习算法中的杰出代表。现实任务中使用神经网络时,大多是使用BP算法进行训练。需要注意的是,BP算法不仅可以用于多层前馈神经网络,还可以用于其他类型的神经网络。通常说BP网络时,常指利用BP算法训练的多层前馈神经网络。神经网络可以用于分类(预测给定元组的类标号)和数值预测(预测连续值输出)等。
多层前馈神经网络
多层前馈神经网络由一个输入层、一个或多个隐层和一个输出层组成,如图9-5所示。它利用后向传播算法迭代地学习用于元组类标号预测的一组权重。
后向传播算法
后向传播通过迭代地处理训练元组数据集,把每个元组的网络预测与实际已知的目标值相比较进行学习。对于每个训练样本,修改权重使得网络预测和实际目标值之间的均方误差最小。这种修改“后向”进行,即由输出层,经由每个隐层到第一个隐藏层。
BP算法的主要思想是把训练过程分为两个阶段:
1.第一阶段(正向传播过程)
2. 第二阶段(反向传播过程)
若在输出层不能得到期望的输出值,那么逐层递归地计算实际输出与期望输出的差值,以便根据差值调节权值。BP算法基于梯度下降(Gradient Descent)策略,以目标的负梯度方向对参数进行调整。
【例9-1】利用后向传播算法学习的样本计算。图9.6给出了一个多层前馈神经网络,令学习率为0.9,第一个训练元组为X={1,0,1},类标号Y=1。计算每个单元的净输入和输出。
(1)随机初始化参数值。
(2)根据BP算法中的前馈过程,计算净输入和输出的值。
(3)计算每个结点的误差。
(4)更新权重和偏倚。
BP神经网络应用
BP神经网络Python应用
import numpy as np
import math
import random
import string
import matplotlib as mpl
import matplotlib.pyplot as plt
#random.seed(0)
#生成区间[a,b]内的随机数
def random_number(a,b):
return (b-a)*random.random()+a
#生成一个矩阵,大小为m*n,并且设置默认零矩阵
def makematrix(m, n, fill=0.0):
a = []
for i in range(m):
a.append([fill]*n)
return a
#函数sigmoid(),这里采用tanh
def sigmoid(x):
return math.tanh(x)
#函数sigmoid的派生函数
def derived_sigmoid(x):
return 1.0 - x**2
#构造三层BP网络架构
class BPNN:
def __init__(self, num_in, num_hidden, num_out):
#输入层,隐藏层,输出层的结点数
self.num_in = num_in + 1 #增加一个偏置结点
self.num_hidden = num_hidden + 1 #增加一个偏置结点
self.num_out = num_out
#激活神经网络的所有结点(向量)
self.active_in = [1.0]*self.num_in
self.active_hidden = [1.0]*self.num_hidden
self.active_out = [1.0]*self.num_out
#创建权重矩阵
self.wight_in = makematrix(self.num_in, self.num_hidden)
self.wight_out = makematrix(self.num_hidden, self.num_out)
#对权值矩阵赋初值
for i in range(self.num_in):
for j in range(self.num_hidden):
self.wight_in[i][j] = random_number(-0.2, 0.2)
for i in range(self.num_hidden):
for j in range(self.num_out):
self.wight_out[i][j] = random_number(-0.2, 0.2)
#最后建立动量因子(矩阵)
self.ci = makematrix(self.num_in, self.num_hidden)
self.co = makematrix(self.num_hidden, self.num_out)
#信号正向传播
def update(self, inputs):
if len(inputs) != self.num_in-1:
raise ValueError('与输入层结点数不符')
#数据输入输入层
for i in range(self.num_in - 1):
#self.active_in[i] = sigmoid(inputs[i])
#或者先在输入层进行数据处理
self.active_in[i] = inputs[i] #active_in[]是输入数据的矩阵
#数据在隐藏层的处理
for i in range(self.num_hidden - 1):
sum = 0.0
for j in range(self.num_in):
sum = sum + self.active_in[i] * self.wight_in[j][i]
self.active_hidden[i] = sigmoid(sum)
#数据在输出层的处理
for i in range(self.num_out):
sum = 0.0
for j in range(self.num_hidden):
sum = sum + self.active_hidden[j]*self.wight_out[j][i]
self.active_out[i] = sigmoid(sum) #与上同理
return self.active_out[:]
#误差反向传播
def errorbackpropagate(self, targets, lr, m):
#lr是学习率, m是动量因子
if len(targets) != self.num_out:
raise ValueError('与输出层结点数不符!')
#首先计算输出层的误差
out_deltas = [0.0]*self.num_out
for i in range(self.num_out):
error = targets[i] - self.active_out[i]
out_deltas[i] = derived_sigmoid(self.active_out[i])*error
#然后计算隐藏层误差
hidden_deltas = [0.0]*self.num_hidden
for i in range(self.num_hidden):
error = 0.0
for j in range(self.num_out):
error = error + out_deltas[j]* self.wight_out[i][j]
hidden_deltas[i] = derived_sigmoid(self.active_hidden[i])*error
#首先更新输出层权值
for i in range(self.num_hidden):
for j in range(self.num_out):
change = out_deltas[j]*self.active_hidden[i]
self.wight_out[i][j] = self.wight_out[i][j] +lr*change + m*self.co[i][j]
self.co[i][j] = change
#然后更新输入层权值
for i in range(self.num_in):
for i in range(self.num_hidden):
change = hidden_deltas[j]*self.active_in[i]
self.wight_in[i][j] = self.wight_in[i][j] +lr*change + m* self.ci[i][j]
self.ci[i][j] = change
#计算总误差
error = 0.0
for i in range(len(targets)):
error = error + 0.5*(targets[i] - self.active_out[i])**2
return error
#测试
def test(self, patterns):
for i in patterns:
print(i[0], '->', self.update(i[0]))
#权重
def weights(self):
print("输入层权重")
for i in range(self.num_in):
print(self.wight_in[i])
print("输出层权重")
for i in range(self.num_hidden):
print(self.wight_out[i])
def train(self, pattern, itera=100000, lr = 0.1, m=0.1):
for i in range(itera):
error = 0.0
for j in pattern:
inputs = j[0]
targets = j[1]
self.update(inputs)
error = error + self.errorbackpropagate(targets, lr, m)
def demo():
patt = [
[[1,2,5],[0]],
[[1,3,4],[1]],
[[1,6,2],[1]],
[[1,5,1],[0]],
[[1,8,4],[1]]
]
#创建神经网络,3个输入结点,3个隐藏层结点,1个输出层结点
n = BPNN(3, 3, 1)
n.train(patt)#训练神经网络
n.test(patt) #测试神经网络
n.weights() #查阅权重值
if __name__ == '__main__':
demo()
[1, 2, 5] -> [0.0013332743419855546]
[1, 3, 4] -> [0.971213050049187]
[1, 6, 2] -> [0.9939366145510202]
[1, 5, 1] -> [0.0003095851699799309]
[1, 8, 4] -> [0.9999918539070392]
输入层权重
[-0.04014858021697668, 0.12134481609095138, -0.11077389845782193, -0.16408845249167597]
[-0.0922688521886562, 0.08537950316054382, -0.158347680207635, 0.05388831357258567]
[0.24664666024024634, -0.012119212976318211, 0.07378662593287749, 0.01690147654773505]
[-0.11422922783461352, 0.10834482357277547, -0.10209155959403589, -0.13675043301723339]
输出层权重
[8.78056297707082e-16]
[15.510488079620497]
[-9.26348498934457]
[-16.756512382661626]
三、深度学习
深度学习概述
理论上来说,参数越多的模型复杂度越高、容量越大,这意味着它能完成更复杂的学习任务。但一般情形下,复杂模型的训练效率低,易陷入过拟合。随着云计算、大数据时代的到来,计算能力的大幅提高可以缓解训练的低效性,训练数据的大幅增加可以降低过拟合风险。因此,以深度学习(Deep Learning,DL)为代表的复杂模型受到了关注。
深度学习是机器学习(Machine Learning,ML)领域中一个新的研究方向。它使机器模仿视听和思考等人类的活动,解决了很多复杂的模式识别难题,使得人工智能相关技术取得了很大进步。深度学习是一类模式分析方法的统称,就具体研究内容而言,主要涉及三类方法:
(1)基于卷积运算的神经网络系统,即卷积神经网络(Convolutional Neural Network,CNN)。
(2)基于多层神经元的自编码神经网络,包括自编码(Auto Encoder)以及近年来受到广泛关注的稀疏编码两类(Sparse Coding)。
(3)以多层自编码神经网络的方式进行预训练,进而结合鉴别信息进一步优化神经网络权值的深度置信网络(DBN)。
常用的深度学习算法
常见的深度学习算法主要包括卷积神经网络、循环神经网络和生成对抗神经网络(Generative Adversarial Network,GAN) 等。这些算法是深度学习的基础算法,在各种深度学习相关系统中均有不同程度的应用。
1.卷积神经网络
卷积神经网络(Convolutional Neural Network,CNN)是第一个被成功训练的多层神经网络结构,具有较强的容错、自学习及并行处理能力。CNN最初是为识别二维图像形状而设计的多层感知器,局部联结和权值共享网络结构类似于生物神经网络,降低神经网络模型的复杂度,减少权值数量,使网络对于输入具备一定的不变性。经典的LeNet-5卷积神经网络结构图如图9-7所示。
经典的LeNet-5卷积神经网络包括了输入层、卷积层、池化层、全连接层和输出层。
(1)输入层
(2)卷积层
(3)池化层
(4)全连接层
(5)输出层
2.循环神经网络
循环神经网络(Recurrent Neural Network, RNN)是一类以序列数据为输入,在序列的演进方向进行递归且所有结点(循环单元)按链式连接的递归神经网络(Recursive Neural Network)。之所以是“循环”,是因为其中隐含层结点的输出不仅取决于当前输入值,还与上一次的输入相关,即结点的输出可以指向自身,进行循环递归运算,在处理时间序列相关的场景时效果明显,在分析语音、视频、天气预报、股票走势预测等方面具有突出优势。
3.生成对抗网络
生成式对抗网络(Generative Adversarial Networks,GAN)是一种深度学习模型,是近年来复杂分布上无监督学习最具前景的方法之一。它解决的问题是从现有样本中学习并创建出新的样本,按照人类对事物的学习过程,逐渐总结规律,而并非使用大量数据训练,所以在新的任务处理中,只需要少量的标记样本就可以训练出高效的分类器。
GAN网络模型通过生成模型(Generative Model)和判别模型(Discriminative Model)的互相博弈学习产生相当好的输出。
四、小结
(1)神经网络是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能模拟生物神经系统会真实世界物体所作出的交互反应 。在机器学习中谈论神经网络时一般指的是“神经网络学习”。
(2)感知机感知器的概念类似于大脑基本处理单元神经元的工作原理。感知器具有许多输入(通常称为特征),这些输入被馈送到产生一个二元输出的线性单元中。因此,感知器可用于解决二元分类问题,其中样本将被识别为属于预定义的两个类之一。
(3)BP算法基于梯度下降策略,以目标的负梯度方向对网络参数进行调整。现实任务中使用神经网络时,大多是使用BP算法进行训练。BP算法不仅可以用于多层前馈神经网络,还可以用于其他类型的神经网络。通常所说的BP网络指利用BP算法训练的多层前馈神经网络。
(4)深度学习的概念源于人工神经网络的研究,含多个隐藏层的多层感知器就是一种深度学习结构。深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。研究深度学习的动机在于建立模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,例如图像,声音和文本等。
(5)卷积神经网络是针对二维数据设计的一种模拟“局部感受野”的局部连接的神经网络结构。它引入卷积运算实现局部连接和权值共享的特征提取,引入池化操作实现低功耗计算和高级特征提取。网络构造通过多次卷积和池化过程形成深度网络,网络的训练含有“权共享”和“稀疏”的特点,学习过程类似于BP算法。