本篇讲述该书关于神经网络方面的知识点。
人工神经网络(Artificial Neural Networks,ANNS),简称神经网络(NeuralNetworks,NNS)或类神经网络,是一种模仿生物神经网络结构和功能的数学模型或计算模型,用于对函数进行估计或近似。神经网络由大量神经元及各层之间的连接关系构成,每个神经元都包含一种特定的输出函数,称为激励函数或激活函数(Activation Function):每两个节点之间的连接都用权重来代表信号连接的强度,这相当于人工神经网络的记忆。网络的输出则因网络连接方式、权重和激励函数的不同而不同。神经网络通常是对自然界中的某种事物的逼近,也可能是对一种逻辑策略的表达。
感知机(Percepton),一种单层网络特性的神经网络结构,它是解释大脑神经元如何工作的简化数学模型:取一组二进制输入值(附近的神经元),将每个输入值乘以一个连续权重(每个附近的神经元的突触强度),并设置一个阈值,如果这些加权输入值的和超过该阈值,就输出1,否则输出0,这样的假设类似于神经元是否放电。
感知机 学习策略:感知机学习的目标就是求得一个能够将训练数据的正负实例点完全分开的分离超平面,即最终求得参数参数w和b,其中w是超平面S的法向量,b是超平面的截距,超平面S称为分离超平面。
感知机学习算法:感知机学习是误分类驱动的,具体采用随机梯度下降法。首先,随机设置模型参数,b的初值,然后使用梯度下降法不断极小化目标函数,极小化过程不是一次性地选取 M中的所有误分类点使其梯度下降,而是一次随机选取一个误分类点使其梯度下降。感知机的学习策略虽然比较简单,但是具备基本的学习能力,能够通过训练数据学习得到区分数据类别的模型参数,因此为后续的多层神经网络奠定了理论和编程实现的基础。
组合多个神经元,形成一个网状结构,以实现复杂的数据分析功能。当多个神经元被组织在一起时,有些神经元的输出是另一些神经元的输入,但前面的神经元输出应该是什么值、如何计算误差等都成了问题,因此神经网络的训练是一个有待解决的难题。反向传播算法的引入解决了多层神经网络的训练问题。
神经元:神经元和感知器本质上是一样的,只不过提到感知器时,其激活函数是阶跃函数;而神经元的激活函数往往选为 sigmoid 函数或 tanh 函数。神经元的结构和示意如下图所示
图1:神经元的结构与示意
计算一个神经元的输出的方法与计算一个感知机的输出的方法是一样的。假设神经元的输入是向量x,权重向量是",激活函数是 sigmoid函数,则神经元的输出y定义为
式中,sigmoid 函数的定义为
sigmoid函数曲线如下,sigmoid函数是非线性函数,其值域是(0,1),其导数比较特殊,可用sigmoid函数自身表示。这样一旦计算出sigmod函数的值,计算其导数就非常方便。
神经网络其实就是按照一定的规则连接起来的多个神经元。其规则如下:
●神经元按照层来布局。
●最左边的层称为输入层,负责接收输入数据。
●最右边的层称为输出层,可以从该层获取神经网络的输出数据。
●输入层和输出层之间的层称为隐藏层,因为它们对外部来说是不可见的。
●同一层的神经元之间没有连接。
●第 N层的每个神经元和第N-1层的所有神经元输入层相连(这就是全连接的含义),第N-1层神经元的输出就是第N层神经元的输入;每个连接都有一个权重。
还存在其他结构的神经网络,如卷积神经网络(Conwvohmional NeuralNewoks,CNs)、循环神经网络(Recurent Neural Networks,RNNs)等它们有着不同的连接规则。
神经网络正向算法和反向传播算法涉及到较多公式推演,用到高等数学方面知识,可自行对其要点梳理学习了解。这里简单讲下激活函数。
在逻辑斯蒂回归算法中,输入的特征经过加权、求和后,还要通过一个sigmoid逻辑函数,将线性回归值归一化到区间[0,1]上,进而体现分类概率值。这个逻函数在神经网络中被称为激活务数图为它源自生物神经系统中神经元被激活的过程。在神经网络中,不仅最后的分类输出层需要激活商数,而且每一层都需要被激活,然后向下一层输入被激活后的值。由于神经元需要激活后才能向后传播,因此激活是必要的。
使用激活函数后,神经网络可以通过改变权重来实现任意分离超平面的变化。神经网络越复杂能够拟合的形状就越复杂,这就是著名的神经网络万有逼近定理。神经网络使用的激活函数都是线性的,每个激活函数都输入一个值,然后做一种特定的数学运算得到一个结果。
书中讲到了sigmoid激活函数;tanh激活函数;ReLU激活函数。
下面通过程序演示如何将数学公式转换成程序的循环、判计算等基本操作,以及如何使用 NumPy等第三方库。为了测试、演示程序的执行,首先生成一些例数据。
import numpy as np
from sklearn import datasets, linear_model
import matplotlib.pyplot as plt
#生成样本数据
np.random.seed(0)
X,y=datasets.make_moons(200,noise =0.20)
y_true =np.array(y).astype(float)
#生成神经网络输出目标
t=np.zeros((X.shape[0],2))
t[np.where(y==0),0]=1
t[np.where(y==1),1]=1
#数据可视化
plt.scatter(X[:,0],X[:,1],c=y,cmap = plt.cm.Spectral)
plt.rcParams['font.sans-serif']=['SimHei']
plt.title("样本数据")
plt.show()
样本数据可视化图
多层神经网络训练程序
'''''''''''''''''''''多层神经网络模型'''''''''''''''''''''
#生成神经网络模型
class NN_Model:
epsilon=0.01 #学习率
n_epoch=1000 #迭代数
nn=NN_Model()
nn.n_input_dim = X.shape[1]#输入尺寸
nn.n_output_dim=2
#输出节点大小
nn.n_hide_dim=8
#隐藏节点大小
nn.X=X
nn.y=y
#初始化权重数组
nn.W1 =np.random.randn(nn.n_input_dim, nn.n_hide_dim)/np.sqrt(nn.n_input_dim)
nn.b1 =np.zeros((1,nn.n_hide_dim))
nn.W2 =np.random.randn(nn.n_hide_dim, nn.n_output_dim)/np.sqrt(nn.n_hide_dim)
nn.b2 =np.zeros((1,nn.n_output_dim))
#定义 sigmoid 及其导数函数
def sigmoid(X):
return 1.0/(1+np.exp(-X))
#网络正向运算
def forward(n,X):
n.z1=sigmoid(X.dot(n.W1)+ n.b1)
n.z2=sigmoid(n.z1.dot(n.W2)+ n.b2)
return n
#使用随机权重进行预测
forward(nn,X)
y_pred = np.argmax(nn.z2, axis = 1)
#数据可视化
plt.scatter(X[:,0],X[:,1],c= y_pred, cmap = plt.cm.Spectral)
plt.rcParams['font.sans-serif']=['SimHei']
plt.title("随机初始化模型参数对示例数据预测的结果")
plt.show()
随机初始化参数数据预测结果
反向传播算法,对网络进行训练,通过可视化,反应真实值与预测值。代码如下:
'''''''''''''''''''''多层神经网络的反向传播'''''''''''''''''''''
from sklearn.metrics import accuracy_score
#反向传播
def backpropagation(n,X,y):
for i in range(n.n_epoch):
#正向计算每个节点的输出
forward(n,X)
# 打印loss,accuracy
L=np.sum((n.z2-y)**2)
y_pred =np.argmax(nn.z2,axis=1)
acc = accuracy_score(y_true, y_pred)
print("epoch[%4d]L=%f,acc=%f"%(i,L, acc))
#计算误差
d2 =n.z2*(1-n.z2)*(y-n.z2)
d1 =n.z1*(1-n.z1)*(np.dot(d2,n.W2.T))
#更新权重
n.W2 +=n.epsilon*np.dot(n.z1.T, d2)
n.b2 +=n.epsilon *np.sum(d2,axis=0)
n.W1 +=n.epsilon *np.dot(X.T,d1)
n.b1 +=n.epsilon *np.sum(d1,axis=0)
nn.n_epoch = 2000
backpropagation(nn,X,t)
#数据可视化
y_pred =np.argmax(nn.z2,axis=1)
plt.scatter(X[:,0],X[:,1],c=nn.y, cmap = plt.cm.Spectral)
plt.rcParams['font.sans-serif']=['SimHei']
plt.title("真实值")
plt.show()
plt.scatter(X[:,0],X[:,1],c=y_pred, cmap = plt.cm.Spectral)
plt.rcParams['font.sans-serif']=['SimHei']
plt.title("预测值")
plt.show()
神经网络训练后对数据进行预测得到的结果
上面使用神经网络的正向计算、反向传播。此外,可以用类的方法封装多层神经网络,可以改进程序的封装方式,对理解和调用神经网络较友好。可参阅书籍做进一步了解,这里不赘述。
softmax函数与交叉熵代价函数
在机器学习中,尤其是在深度学习中,sofmax函数是一个重要函数,在多分类的场景中使用广sotmax函数将一些输入映射为区间[0,1]内的实数并归一化,以保证和为1,进而满足多分类的之和为1的要求。
sotmax函数也称归一化指数函数,一般在神经网络中作为分类任务的输出层。其实,我们可以认为sofmax函数输出的是样本属于每个类别的概率。例如,一个分类任务要分为三个类别,sofmax函数可以根据它们的相对大小,输出属于三个类别的概率,且概率之和为1。
神经网络的权重更新需要一个代价函数来表示真实值与网络估计值的偏差,而对代价函数取偏g数可得到权重的更新量。人在学习和分析新事物时,发现自己犯的错误越大,改近的力度也就越大。人们设计了交又焰(价医数,其主要优点是求导结果比较简单,工计算,并且能解决某些代价函数学习缓慢问题。
本章介绍了感知器模型及其学习、多层神经网络的构建和训练、常用激活函数,以及sofm与交叉熵代价函数等。此外,还通过程序演示了机器学习中的神经网络正向计算和误差的反向传播。总的来说受益匪浅,收获良多。