当前位置: 代码迷 >> 综合 >> 西瓜书课后题——第五章(神经网络)
  详细解决方案

西瓜书课后题——第五章(神经网络)

热度:91   发布时间:2023-11-22 04:02:33.0

课后题5.5:编程实现一个标准bp算法和一个累积bp算法,用这两个算法训练一个带有单隐层的网络,并给出在西瓜数据集3.0上的效果

首先,单隐层网络,就是输入和输出层之间只有一层神经元的网络,见西瓜书P102图 5.7所示

标准bp算法,如书上P102-104所述,每次更新参数只使用一个样本,所以到达收敛所需要训练的次数会比较多。

累积bp算法,每次更新参数时,使用的是所有的训练样本,也就是一个epoch之后再进行参数更新。所以训练次数可能比较少。

下面给出实现这两个算法的代码:

import numpy as npdef 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\').TX = 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, Ydef 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.1error = 0.001maxTrainNum = 1000000trainNum = 0loss = 10while (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*gV += rate*X[k].reshape(1,X[k].size).T.dot(e)V_b -= rate*etrainNum += 1print("总训练次数:",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.1error = 0.001maxTrainNum = 1000000trainNum = 0loss = 10while (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 += 1print("总训练次数:",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算法优化的一些讨论。 

 

 

  相关解决方案