返回介绍

7.3 人工神经网络

发布于 2024-01-21 22:13:25 字数 10507 浏览 0 评论 0 收藏 0

人脑是一种强大的信息处理装置,在视觉、听觉、语言知识和学习方面是机器无法替代的。通过前面两节对回归问题的讲述,我们知道可以让机器“学习”使它拥有某种能力去为人类服务。而人脑与计算机最大的不同是计算机的处理器是有限的,而人脑包含着大量的神经元去传输信息。基于神经元的启发,科学家建立了一种新的运算模型,人工神经网络。神经网络是由大量的节点,或称为神经元,相互连接构成。信息经过输入层进入神经网络,在节点中不断进行信息传输与运算,最后到达输出层,得到最终处理后的信息。人工神经网络经过数据训练后,它就具有类似于人脑的能力,人工神经网络的研究使得“听歌识曲”,“图像识别”等应用得到高速发展。如果数据量足够用于训练和机器运算速度足够快的话,制造一个有人类智力的机器也是有可能的。

BP(Back Propagation)神经网络是一种处理分类和回归问题很有效的神经网络。本节我们重点介绍BP神经网络及其前向传播和反向传播的机制,相信通过本节的学习,读者能够对人工神经网络有一个快速的入门。

1.神经网络模型

图7-7展现了一个3层的神经网络。我们使用圆圈来表示神经网络的节点,标上“+1”的节点被称为偏置节点。第一层是网络的输入层,最后一层是输出层,其余的都称为隐藏层,图7-7只有一个隐藏层。我们可以看到输入层有3个输入单元(不包括偏置单元),3个隐藏单元和一个输出单元。

图7-7 神经网络模型

我们用nl 来表示网络的层数。本例中nl =3,我们将第l层记为Ll ,于是输入层记为L1 ,输出层记为Lnl ,我们用st 表示第l层的节点数。在本例中神经网络参数有(W,b)=(W(1) ,b(1) ,W(2) ,b(2) ), 表示第l层第j单元与第l+1层第i单元之间的连接系数(注意标号顺序), 是第l+1层第i单元的偏置项。在本例中,W(1) ,W(2)

2.前向传播

我们用 表示第l层第i单元的激活值。当l=1时, 。继续以图7-7的网络为例,给定参数集合(W,b)和激活函数f后,我们可以按照下面的公式计算第二层的激活值a(2):

我们用 表示第l层第i单元的加权和,如 ,则 。我们可以使用矩阵乘法对上面的过程进行简化:

具体地,在本例中:

hW,b (x)得出的结果就是输出层的输出。上面整个计算过程称为前向传播。设定参数矩阵和激活函数后,模型将信息一层层地从输入层往输出层传播,因此称为前向传播。常用的激活函数有下面几种,如表7-4所示。

表7-4 常用激活函数

我们一般以随机值初始化参数矩阵,后面我们将用数据训练网络。这是一个不断优化参数集合(W,b),使得在训练集处理的结果更优的过程。而BP神经网络训练参数的方法是反向传播。

3.反向传播

假设我们现有一个数据集{(x(1) ,y(1) ),…,(x(m) ,y(m) )},它包含了m个样本。我们首先设定代价函数,对于一个样例(x(i) ,y(i) ):

而对于整体代价函数我们定义为:

第一项表示残差平方和,第二项是正则化项,目的是为了防止权重过大以致过度拟合。这个代价函数经常用于分类和回归问题。在二分类问题中,我们用y=0和y=1代表两种类型的标签。我们可以在输出层使用sigmoid激活函数使得最终的输出结果在(0,1)之间,通过代价函数计算模型预测的误差。而对于回归问题,我们可以对真实的y值做一个变换,如使用sigmoid函数,使得样例y值的范围在(0,1)之间。接着输出层同样使用sigmoid激活函数,预测的y值也在(0,1)之间,最后使用代价函数计算误差。

有了代价函数,神经网络的任务就是使得“代价”尽量低。我们将使用梯度下降法 对参数(W,b)进行优化,每一步迭代更新(W,b)使得代价函数的值不断减少(如图7-8所示)。我们将使用W和b的偏导数对它们进行更新:

图7-8 梯度下降法示意图

其中α是学习效率,其中关键在于计算偏导数。而反向传播算法是计算偏导数的一种有效方法。由于篇幅限制,我们不讲解公式的具体推导,直接讲述反向传播算法的计算步骤和推导得到的计算公式。给定一个样本(x(i) ,y(i) ),反向传播算法可以分为下面几个步骤:

1)利用前向传播算法,得到L2 ,L3 ,…直到输出层 的激活值。

2)计算输出层(第nt 层)的残差:

3)计算l=nt -1,nt -2,…,2的各层的残差:

4)计算最终需要的偏导数值:

当样本数量为m时,我们批量梯度下降法的迭代如下:

1)初始化,对于所有l,令ΔW(l) =0,Δb(l) =0。

2)对i=1到m:

a)使用反向传播算法计算

b)

c)

3)更新权重参数:

a)

b)

反复进行上述迭代,减少代价函数J(W,b)的值,进而求解我们的神经网络。

4.进行实验

我们尝试使用BP神经网络进行实验。数据集采用scikit-learn提供的make_moons数据集。产生的数据如图7-9所示,“+”表示女性病人,“x”表示男性病人,x和y轴表示两个指标。将数据分为训练集和测试集后,使用训练集训练神经网络,将训练好的神经网络作用于测试集,得到预测的错误率。BP神经网络的代码见代码清单7-4,我们需要设置网络层数和每层的节点数,学习速率α,正则化系数λ,迭代次数。对于此数据集我们采用[2,3,1]的网络,输入的节点数是2个,设置一个有3个节点的隐藏层。α设为0.2,λ设为0.005,迭代次数设为10000。程序得到的结果为:训练集的错误率为0.159375,测试集的错误率为0.15。BP神经网络的分类效果很不错,如果提高迭代次数,分类的效果还可以进一步提高。

图7-9 make_moons数据集

代码清单7-4 BP神经网络

# BP神经网络
Python实现
import numpy as np
from numpy import random
import math
import copy
import sklearn.datasets
import matplotlib.pyplot as plt
# 获取数据并分为训练集与测试集
trainingSet, trainingLabels = sklearn.datasets.make_moons(400, noise=0.20)
plt.scatter(trainingSet[trainingLabels==1][:,0], trainingSet[trainingLabels==1][:,1], s=40, c='r', marker='x',cmap=plt.cm.Spectral)
plt.scatter(trainingSet[trainingLabels==0][:,0], trainingSet[trainingLabels==0][:,1], s=40, c='y', marker='+',cmap=plt.cm.Spectral)
plt.show()
testSet = trainingSet[320:]
testLabels = trainingLabels[320:]
trainingSet = trainingSet[:320]
trainingLabels = trainingLabels[:320]
# 设置网络参数
layer =[2,3,1]          # 设置层数和节点数
Lambda = 0.005          # 正则化系数
alpha = 0.2          # 学习速率
num_passes = 20000          # 迭代次数
m = len(trainingSet)     # 样本数量
# 建立网络
# 网络采用列表存储每层的网络结构
,网络的层数和各层节点数都可以自由设定
b = [] # 偏置元
,共
layer-1个元素
,b[0]代表第一个隐藏层的偏置元
(向量形式
)
W = []
for i in range(len(layer)-1):
    W.append(random.random(size = (layer[i+1],layer[i]))) # W[i]表示网络第
i层到第
i+1层的转移矩阵
(NumPy数组
),输入层是第
0层
    b.append(np.array([0.1]*layer[i+1])) # 偏置元
b[i]的规模是
1*第
i+1个隐藏层节点数
a = [np.array(0)]*(len(W)+1) # a[0] = x,即输入
,a[1]=f(z[0]),a[len(W)+1] = 最终输出
z = [np.array(0)]*len(W) # 注意
z[0]表示网络输入层的输出,即未被激活的第一个隐藏层
W = np.array(W)
def costfunction(predict,labels):
    # 不加入正则化项的代价函数
    # 输入参数格式为
numpy的向量
    return sum((predict - labels)**2)
def error_rate(predict,labels):
    # 计算错误率
,针对二分类问题
,分类标签为
0或
1
    # 输入参数格式为
numpy的向量
    error =0.0
    for i in range(len(predict)):
        predict[i] = round(predict[i]) 
        if predict[i]!=labels[i]:
            error+=1
    return error/len(predict)
def sigmoid(z):  # 激活函数
sigmoid
    return 1/(1+np.exp(-z))
def diff_sigmoid(z): # 激活函数
sigmoid的导数
    return sigmoid(z)*(1-sigmoid(z))
activation_function = sigmoid  # 设置激活函数
diff_activation_function = diff_sigmoid # 设置激活函数的导数
# 开始训练
BP神经网络
a[0] = np.array(trainingSet).T # 这里一列为一个样本,一行代表一个特征
y = np.array(trainingLabels)
for v in range(num_passes):
    # 前向传播
    for i in range(len(W)):
        z[i] = np.dot(W[i],a[i])
        for j in range(m):
            z[i][:,j]+=b[i] # 加上偏置元
        a[i+1] = activation_function(z[i]) # 激活节点
    predict = a[-1][0] # a[-1]是输出层的结果
,即为预测值
    # 反向传播
    delta = [np.array(0)]*len(W) # delta[0]是第一个隐藏层的残差,
delta[-1]是输出层的残差
    # 计算输出层的残差
    delta[-1] = -(y-a[-1])*diff_activation_function(z[-1])
    # 计算第二层起除输出层外的残差
    for i in range(len(delta)-1):
        delta[-i-2] = np.dot(W[-i-1].T,delta[-i-1])*diff_activation_function(z [-i-2]) # 这里是倒
# 序遍历
        # 设下标
-i-2代表第
L层,则
W[-i-1]是第
L层到
L+1层的转移矩阵,
delta[-i-1]是
    # 第
L+1层的残差,而
z[-i-2]是未激活的第
L层
    # 计算最终需要的偏导数值
    delta_w = [np.array(0)]*len(W)
    delta_b = [np.array(0)]*len(W)
    for i in range(len(W)):
        # 使用矩阵运算简化公式
,下面两行代码已将全部样本反向传播得到的偏导数值求
#和
        delta_w[i] = np.dot(delta[i],a[i].T) 
        delta_b[i] = np.sum(delta[i],axis=1) 
    # 更新权重参数
    for i in range(len(W)):
        W[i] -= alpha*(Lambda*W[i]+delta_w[i]/m)
        b[i] -= alpha/m*delta_b[i]
print '训练样本的未正则化代价函数值
:',costfunction(predict,np.array(trainingLabels))
print '训练样本错误率
:',error_rate(predict,np.array(trainingLabels)) 
# 使用测试集测试网络
a[0] = np.array(testSet).T # 一列为一个样本,一行代表一个特征
# 前向传播
m = len(testSet)
for i in range(len(W)):
    z[i] = np.dot(W[i],a[i])
    for j in range(m):
        z[i][:,j]+=b[i].T[0]
    a[i+1] = activation_function(z[i])
predict = a[-1][0]
print '测试样本的未正则化代价函数值
:',costfunction(predict,np.array(testLabels))
print '测试样本错误率
:',error_rate(predict,np.array(testLabels))


*代码详见:示例程序/code/7-3.py
5.其他神经网络
卷积神经网络 (Convolutional Neual Network,CNN)是一种前馈神经网络,与BP神经网络不同的是,它包括卷积层 (Alternating Convolutional Layer)和池层 (Pooling Layer),在图像处理方面有很好的效果,经常用作解决计算机视觉问题。递归神经网络 (RNN)分为时间递归神经网络 (Recurrent Neural Network)和结构递归神经网络 (Recursive Neural Network)。RNN主要用于处理序列数据。在BP神经网络中,输入层到输出层各层间是全连接的,但同层之间的节点却是无连接的。这种网络对于处理序列数据效果很差,忽略了同层间节点的联系,而在序列中同层间节点的关系是很密切的。CNN和RNN是深度学习中著名的两种结构,建议读者借助其他书籍熟悉它们。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文