热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

西瓜书5.5编程实现BP神经网络——标准BP算法、累积BP算法

这里照着书上的公式,实现了一下标准BP算法,和累积BP算法,BP是errorBackPropagation的意思,误差逆传播。BP网络通常是指用BP算法训练的多层前馈神经网络。代码是照着

这里照着书上的公式,实现了一下标准BP算法,和累积BP算法,BP是error Back Propagation的意思,误差逆传播。BP网络通常是指用BP算法训练的多层前馈神经网络。代码是照着书本公式自己写的,没有参考网上的其他版本。

数据和代码地址:https://github.com/qdbszsj/BP

具体的理论证明和公式推导,见西瓜书P101-104。这里重点说一下我的数据处理和一些代码细节,以及一些重点知识。

西瓜数据集3.0,里面有离散属性,也有连续属性,除了密度、含糖量这样的属性,还有一些文字性描述的离散属性,因此我们先把离散属性转化为数字表示的属性。比如“色泽”这个属性下有三种属性:浅白、青绿、乌黑,我认为这三个属性有递进关系,类似于低中高,瘦均胖,因此就用一个值来表示他们,{0,0.5,1}这三个值表示这三个属性。同理,其他属性都用这种方法处理成0~1之间的小数。这里的属性都是有序的,没有无序的属性,如果有无序的属性,那么通常就要用一个K维的向量来表示,比如属性“瓜类”下分为“西瓜”、“黄瓜”、“南瓜”,显然这三个瓜是无序的,因此就用(0,0,1)、(0,1,0)、(0,0,1)这样的值来表示他们,其实就相当于把数据集拓宽了几列,列名由一个“瓜类”变为“是西瓜?”、“是黄瓜?”、“是南瓜?”,然后元素值是1和0。这里跟NLP的词向量处理方法有些接近,很多做NLP的词向量都是这样的。

然后是根据书P104的伪代码,先初始化了两组权值(输入->隐层、隐层->输出)和两组阈值(隐层、输出),都是随机的0-1的小数,这里命名方式我都是按照书本上的变量名,P101都有。然后书上有一个公式没写出来,那就是b=f(alpha-gamma),这个跟公式5.3道理是一样的,自己的输出=sigmoid(自己接受到的输入-自己的阈值),这个“自己”可以是隐层或者是输出层。

这里标准BP和累积BP我都实现了一下,区别很小,标准BP就是对于每一个输入的X个体,都更新一下网络,而累积BP就是把整个X集合都跑一遍,把各种要变化的值累加起来,再更新,累积BP类似于随机梯度下降法,每跑一遍整个集合,更新一次。

隐层神经元的个数:这里我是用的d+1个,就是比输入结点的个数多一个,这个个数目前没有定论,通常是靠试错法来决定,几个结点表现好,就用几个。

针对过拟合:通常有两种策略,一种就是“早停”,一边训练一边用测试集测试,如果发现训练集误差降低,而测试集误差升高,那么就停止训练。还有一种策略是“正则化”,根据书上公式5.17,误差评估时引入一个概念:网络的复杂程度。我们认为权值越小,网络约简单平滑,不容易过拟合,因此统计误差和网络复杂度都在误差评估的时候占一个百分比,which是一个可以调整的参数。

这里发现numpy真好用,各种矩阵相乘、相加相减想乘,都一行代码搞定

import pandas as pd
import numpy as np
dataset = pd.read_csv('/home/parker/watermelonData/watermelon_3.csv', delimiter=",")

#according to P54--3.2
#process the dataset
attributeMap={}
attributeMap['浅白']=0
attributeMap['青绿']=0.5
attributeMap['乌黑']=1
attributeMap['蜷缩']=0
attributeMap['稍蜷']=0.5
attributeMap['硬挺']=1
attributeMap['沉闷']=0
attributeMap['浊响']=0.5
attributeMap['清脆']=1
attributeMap['模糊']=0
attributeMap['稍糊']=0.5
attributeMap['清晰']=1
attributeMap['凹陷']=0
attributeMap['稍凹']=0.5
attributeMap['平坦']=1
attributeMap['硬滑']=0
attributeMap['软粘']=1
attributeMap['否']=0
attributeMap['是']=1
del dataset['编号']
dataset=np.array(dataset)
m,n=np.shape(dataset)
for i in range(m):
    for j in range(n):
        if dataset[i,j] in attributeMap:
            dataset[i,j]=attributeMap[dataset[i,j]]
        dataset[i,j]=round(dataset[i,j],3)

trueY=dataset[:,n-1]
X=dataset[:,:n-1]
m,n=np.shape(X)

#according to P101, init the parameters
import random
d=n   #the dimension of the input vector
l=1   #the dimension of the  output vector
q=d+1   #the number of the hide nodes
theta=[random.random() for i in range(l)]   #the threshold of the output nodes
gamma=[random.random() for i in range(q)]   #the threshold of the hide nodes
# v size= d*q .the connection weight between input and hide nodes
v=[[random.random() for i in range(q)] for j in range(d)]
# w size= q*l .the connection weight between hide and output nodes
w=[[random.random() for i in range(l)] for j in range(q)]
eta=0.2    #the training speed
maxIter=5000 #the max training times

import math
def sigmoid(iX,dimension):#iX is a matrix with a dimension
    if dimension==1:
        for i in range(len(iX)):
            iX[i] = 1 / (1 + math.exp(-iX[i]))
    else:
        for i in range(len(iX)):
            iX[i] = sigmoid(iX[i],dimension-1)
    return iX


# do the repeat----standard BP
while(maxIter>0):
    maxIter-=1
    sumE=0
    for i in range(m):
        alpha=np.dot(X[i],v)#p101 line 2 from bottom, shape=1*q
        b=sigmoid(alpha-gamma,1)#b=f(alpha-gamma), shape=1*q
        beta=np.dot(b,w)#shape=(1*q)*(q*l)=1*l
        predictY=sigmoid(beta-theta,1)   #shape=1*l ,p102--5.3
        E = sum((predictY-trueY[i])*(predictY-trueY[i]))/2    #5.4
        sumE+=E#5.16
        #p104
        g=predictY*(1-predictY)*(trueY[i]-predictY)#shape=1*l p103--5.10
        e=b*(1-b)*((np.dot(w,g.T)).T) #shape=1*q , p104--5.15
        w+=eta*np.dot(b.reshape((q,1)),g.reshape((1,l)))#5.11
        theta-=eta*g#5.12
        v+=eta*np.dot(X[i].reshape((d,1)),e.reshape((1,q)))#5.13
        gamma-=eta*e#5.14
    # print(sumE)

# #accumulated BP
# trueY=trueY.reshape((m,l))
# while(maxIter>0):
#     maxIter-=1
#     sumE=0
#     alpha = np.dot(X, v)#p101 line 2 from bottom, shape=m*q
#     b = sigmoid(alpha - gamma,2)  # b=f(alpha-gamma), shape=m*q
#     beta = np.dot(b, w)  # shape=(m*q)*(q*l)=m*l
#     predictY = sigmoid(beta - theta,2)  # shape=m*l ,p102--5.3
#
#     E = sum(sum((predictY - trueY) * (predictY - trueY))) / 2  # 5.4
#     # print(round(E,5))
#     g = predictY * (1 - predictY) * (trueY - predictY)  # shape=m*l p103--5.10
#     e = b * (1 - b) * ((np.dot(w, g.T)).T)  # shape=m*q , p104--5.15
#     w += eta * np.dot(b.T, g)  # 5.11 shape (q*l)=(q*m) * (m*l)
#     theta -= eta * g  # 5.12
#     v += eta * np.dot(X.T, e)  # 5.13 (d,q)=(d,m)*(m,q)
#     gamma -= eta * e  # 5.14


def predict(iX):
    alpha = np.dot(iX, v)  # p101 line 2 from bottom, shape=m*q
    b=sigmoid(alpha-gamma,2)#b=f(alpha-gamma), shape=m*q
    beta = np.dot(b, w)  # shape=(m*q)*(q*l)=m*l
    predictY=sigmoid(beta - theta,2)  # shape=m*l ,p102--5.3
    return predictY

print(predict(X))




推荐阅读
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 本文介绍了贝叶斯垃圾邮件分类的机器学习代码,代码来源于https://www.cnblogs.com/huangyc/p/10327209.html,并对代码进行了简介。朴素贝叶斯分类器训练函数包括求p(Ci)和基于词汇表的p(w|Ci)。 ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • IB 物理真题解析:比潜热、理想气体的应用
    本文是对2017年IB物理试卷paper 2中一道涉及比潜热、理想气体和功率的大题进行解析。题目涉及液氧蒸发成氧气的过程,讲解了液氧和氧气分子的结构以及蒸发后分子之间的作用力变化。同时,文章也给出了解题技巧,建议根据得分点的数量来合理分配答题时间。最后,文章提供了答案解析,标注了每个得分点的位置。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • Allegro总结:1.防焊层(SolderMask):又称绿油层,PCB非布线层,用于制成丝网印板,将不需要焊接的地方涂上防焊剂.在防焊层上预留的焊盘大小要比实际的焊盘大一些,其差值一般 ... [详细]
author-avatar
网络小爬虫
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有