概述
课后题5.5:编程实现一个标准bp算法和一个累积bp算法,用这两个算法训练一个带有单隐层的网络,并给出在西瓜数据集3.0上的效果
首先,单隐层网络,就是输入和输出层之间只有一层神经元的网络,见西瓜书P102图 5.7所示
标准bp算法,如书上P102-104所述,每次更新参数只使用一个样本,所以到达收敛所需要训练的次数会比较多。
累积bp算法,每次更新参数时,使用的是所有的训练样本,也就是一个epoch之后再进行参数更新。所以训练次数可能比较少。
下面给出实现这两个算法的代码:
import numpy as np
def dataSet():
# 西瓜数据集离散化
X = np.mat('2,3,3,2,1,2,3,3,3,2,1,1,2,1,3,1,2;
1,1,1,1,1,2,2,2,2,3,3,1,2,2,2,1,1;
2,3,2,3,2,2,2,2,3,1,1,2,2,3,2,2,3;
3,3,3,3,3,3,2,3,2,3,1,1,2,2,3,1,2;
1,1,1,1,1,2,2,2,2,3,3,3,1,1,2,3,2;
1,1,1,1,1,2,2,1,1,2,1,2,1,1,2,1,1;
0.697,0.774,0.634,0.668,0.556,0.403,0.481,0.437,0.666,0.243,0.245,0.343,0.639,0.657,0.360,0.593,0.719;
0.460,0.376,0.264,0.318,0.215,0.237,0.149,0.211,0.091,0.267,0.057,0.099,0.161,0.198,0.370,0.042,0.103
').T
X = np.array(X) # 样本属性集合,行表示一个样本,列表示一个属性
Y = np.mat('1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0')
Y = np.array(Y).T # 每个样本对应的标签
return X, Y
def sigmod(x):
return 1.0/(1.0+np.exp(-x))
def bpstand(hideNum): # 标准的反向传播算法
X,Y = dataSet()
V = np.random.rand(X.shape[1],hideNum) # 权值及偏置初始化
V_b = np.random.rand(1,hideNum)
W = np.random.rand(hideNum,Y.shape[1])
W_b = np.random.rand(1,Y.shape[1])
rate = 0.1
error = 0.001
maxTrainNum = 1000000
trainNum = 0
loss = 10
while (loss>error) and (trainNum < maxTrainNum):
for k in range(X.shape[0]): # 标准bp方法一次只处理一个样本
H = sigmod(X[k,:].dot(V)-V_b) # 因为书上一直给出的是减去阈值,所以这里用减号。
Y_ = sigmod(H.dot(W)-W_b) # 其实大部分情况下人们都用的是加上偏置b这种表达方式
loss = sum((Y[k]-Y_)**2)*0.5 # 改成加号后只需要在下面更新参数时也用加号即可
g = Y_*(1-Y_)*(Y[k]-Y_) # 计算相应的梯度,及更新参数。 此处特别注意维度的正确对应关系
e = H*(1-H)*g.dot(W.T)
W += rate*H.T.dot(g)
W_b -= rate*g
V += rate*X[k].reshape(1,X[k].size).T.dot(e)
V_b -= rate*e
trainNum += 1
print("总训练次数:",trainNum)
print("最终损失:",loss)
print("V:",V)
print("V_b:",V_b)
print("W:",W)
print("W_b:",W_b)
def bpAccum(hideNum): # 累积bp算法
X,Y = dataSet()
V = np.random.rand(X.shape[1],hideNum)
V_b = np.random.rand(1,hideNum)
W = np.random.rand(hideNum,Y.shape[1])
W_b = np.random.rand(1,Y.shape[1])
rate = 0.1
error = 0.001
maxTrainNum = 1000000
trainNum = 0
loss = 10
while (loss>error) and (trainNum<maxTrainNum):
H = sigmod(X.dot(V)-V_b)
Y_ = sigmod(H.dot(W)-W_b)
loss = 0.5*sum((Y-Y_)**2)/X.shape[0]
g = Y_*(1-Y_)*(Y-Y_) # 对应元素相乘,类似于matlab中的点乘
e = H*(1-H)*g.dot(W.T)
W += rate*H.T.dot(g)
W_b -= rate*g.sum(axis=0)
V += rate*X.T.dot(e)
V_b -= rate*e.sum(axis=0)
trainNum += 1
print("总训练次数:",trainNum)
print("最终损失:",loss)
print("V:",V)
print("V_b:",V_b)
print("W:",W)
print("W_b:",W_b)
if __name__ == '__main__':
bpstand(5)
bpAccum(5)
最终两种方法得到的损失以及训练次数分别是:
标准bp算法:
总训练次数: 65008
最终损失: [ 0.00099985]
累积bp算法:
总训练次数: 6578
最终损失: [ 0.00099987]
可以看出,在得到同样精度的情况下,累积bp算法的训练次数要比标准bp算法的训练次数少的多。
参考这篇博客:https://blog.csdn.net/u013527937/article/details/58637367
课后题5.6:动态调整学习率提高收敛速度。
关于这个问题,参见这篇博客对于BP算法优化的一些讨论。
最后
以上就是落寞身影为你收集整理的西瓜书课后题——第五章(神经网络)的全部内容,希望文章能够帮你解决西瓜书课后题——第五章(神经网络)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复