我是靠谱客的博主 落寞身影,最近开发中收集的这篇文章主要介绍西瓜书课后题——第五章(神经网络),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

课后题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算法优化的一些讨论。 

 

 

最后

以上就是落寞身影为你收集整理的西瓜书课后题——第五章(神经网络)的全部内容,希望文章能够帮你解决西瓜书课后题——第五章(神经网络)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部