话不多说先用numpy表示出数据集

Y=['色泽','根蒂','敲声','纹理','脐部','触感','密度','含糖率','好瓜与否']
D=np.array([[2,1,2,3,3,1,0.697,0.406,1],\
[3,1,1,3,3,1,0.774,0.376,1],\
[3,1,2,3,3,1,0.634,0.264,1],\
[2,1,1,3,3,1,0.608,0.318,1],\
[1,1,2,3,3,1,0.556,0.215,1],\
[2,2,2,3,2,0,0.403,0.237,1],\
[3,2,2,2,2,0,0.481,0.149,1],\
[3,2,2,3,2,1,0.437,0.211,1],\
[3,2,1,2,2,1,0.666,0.091,0],\
[2,3,3,3,1,0,0.243,0.267,0],\
[1,3,3,1,1,1,0.245,0.057,0],\
[1,1,2,1,1,0,0.343,0.099,0],\
[2,2,2,2,3,1,0.639,0.161,0],\
[1,2,1,2,3,1,0.657,0.198,0],\
[3,2,2,3,2,0,0.360,0.370,0],\
[1,1,2,1,1,1,0.593,0.042,0],\
[2,1,1,2,2,1,0.719,0.103,0]])
lamuda=0.1
v=np.ones(shape=(8,8))
b=np.ones(shape=(8))
gama=np.ones(shape=(8))
w=np.ones(shape=(2,8))
y=np.ones(shape=(2))
sita=np.ones(shape=(2))

其中属性值的数字化图方便一律使用了值而不是向量,具体对应关系如下:

色泽:浅白 1,青绿 2,乌黑 3

根蒂:蜷缩 1,稍蜷 2,硬挺 3

敲声:沉闷 1,浊响 2,清脆 3

纹理:模糊 1,稍糊 2,清晰 3

脐部:平坦 1,稍凹 2,凹陷 3

触感:硬滑 1,软粘 0

敢使用值的原因也是这些属性基本都是存在一定的强弱关系的(清晰度、蜷曲度、凹陷度等),所以放心大胆123

先编写一个初始化函数对每个阈值和连接权进行初始化,各数组命名参考书上的图5.7。使用的是8输入8隐层2输出的网络结构,那么对于好瓜应该输出(1,0),坏瓜输出(0,1)

def initial():
for i in range(8):
for j in range(8):
v[i,j]=random.random()
gama[i]=random.random() for i in range(2):
for j in range(8):
w[i,j]=random.random()
sita[i]=random.random()
return

然后做主函数,主体和书上P104的图5.8一样,每个函数的内容后面再说,跳出条件依然先设置是循环一定的次数。

num=100
while(num):
num-=1
for k in range(16):#遍历每个输入
Y(k)
G(k)
ee()
ref(k)
print(v)
print(b)
print(gama)
print(w)
print(y)
print(sita)

Y(k)的作用是根据当前遍历到的第k个样本的属性值计算输出y,分两步走,先修改每个隐层神经元的输出,再修改每个输出神经元的输出,代码如下:

def Y(a):
for i in range(8):#修改每个隐层输出
b[i]=sigmoidb(a,i)
for i in range(2):
y[i]=sigmoidy(a,i)
return

sigmoidb与sigmoidy的作用就是求当前神经元的输出,累加输入与权重的乘积后减去阈值,然后返回sigmoid函数结果,注意sigmoid函数中的-次方。

def sigmoidb(a,c):
s=0
for i in range(8):#遍历第a个样本每个属性值
s=s+v[i,c]*D[a,i]
s=gama[c]-s
return 1/(1+math.exp(s)) def sigmoidy(a,c):
s=0
for i in range(8):
s=s+w[c,i]*b[i]
s=sita[c]-s
return 1/(1+math.exp(s))

回到主函数,下一步是更新两组推导出来的辅助计算的参数g和e,为了防止与之后要加的误差计算命名冲突就把e的更新函数改成了ee

更新方式很简单,按照书上现成的公式跑一跑就行了,具体推导过程可以自己试着写一下,难度还好。这里有个问题就是y的估计值,为了方便计算在原本的数据集中加了一列

在其中好瓜添加值0,坏瓜添加值1,与原本标记相反。代码中就表现为G中的样子。

def G(a):
for i in range(2):
g[i]=y[i]*(1-y[i])*(D[a,8+i]-y[i])
return

def ee():
for i in range(8):
s=b[i]*(1-b[i])
for j in range(2):
s=s*w[j,i]*g[j]
e[i]=s
return

然后就是根据公式更新连接权、阈值:

def ref(k):
for i in range(8):
for j in range(2):
w[j,i]=w[j,i]+lamuda*g[j]*b[i]
for i in range(2):
sita[i]=sita[i]-lamuda*g[i]
for i in range(8):
gama[i]=gama[i]-lamuda*e[i]
for j in range(8):
v[i,j]=v[i,j]+lamuda*e[j]*D[k,i]
return

主体大致就这样,循环完之后输出看一下参数就行。出现溢出的话多半是sigmoid里次方符号不对,这个计算应该没有特别大或者特别小的情况。

然后为了看眼误差,写个误差验算函数:

def E(k):
s=0
for i in range(2):
s=s+(y[i]-D[k,8+i])*(y[i]-D[k,8+i])
s/=2
return s

加到主函数里面,写个输出

print('第',100-num,'次',k,'样本误差:',E(k))

输出结果就不放了,可以看到误差是震荡的,而且似乎始终保持在0.16以上

这时候就要用到累积BP了。为了实现累计BP,我们要稍微修改一下前面的更新过程,如何修改呢?

先来看一下5.16,我们要用这个式子来代替5.4的式子套入到5.6-5.15的推到过程中去,来得到新的参数更新估计式。

5.16其实就是对所有样例的Ek做一个求平均,那么代入到5.10可以得到,新的参数更新估计式只要带上一个求平均的过程即可。

再看5.15,可以看到需要平均的项恰好也是gj,那就照原样计算就行。

首先更改一下主函数的结构,把eh和参数更新放到i的循环中,添加一个误差判别跳出,能得到一个较好的结果,记得修改函数的参数:

initial()
num=1000
avr()
Ee=1
while(num):
num-=1
set()
for k in range(16):#遍历每个输入
Y(k)
G(k)
ee()
ref()
aa=E()
if(aa>Ee):
print(aa)
break
Ee=aa

然后对G(k)做个手脚,使其最终得到所有样本的平均值:

def G(a):
for i in range(2):
g[i]=g[i]+y[i]*(1-y[i])*(D[a,8+i]-y[i])
if(a==15):
g[i]/=16
return

ee不用动,但为了计算△Vih,我们需要求一下所有样本属性的平均值,存放到一个数组里:

def avr():
for i in range(8):
avra[i]=0
for j in range(16):
avra[i]+=D[j,i]
avra[i]/=16
return

同时在程序开始时将g数组置零:

def set():
for i in range(2):
g[i]=0
return

修改更新函数:

def ref():
for i in range(8):
for j in range(2):
w[j,i]=w[j,i]+lamuda*g[j]*b[i]
for i in range(2):
sita[i]=sita[i]-lamuda*g[i]
for i in range(8):
gama[i]=gama[i]-lamuda*e[i]
for j in range(8):
v[i,j]=v[i,j]+lamuda*e[j]*avra[i]
return

修改求误差函数:

def E():
s=0
for j in range (16):
Y(j)
for i in range(2):
s=s+(y[i]-D[k,8+i])*(y[i]-D[k,8+i])/2
s/=16
return s

搞定,运行后可以看到误差最终停在0.12左右(但不及时跳出会稳定在0.25左右)。

西瓜书 5.5 编写过程(标准BP与累计BP)的更多相关文章

  1. 决策树ID3原理及R语言python代码实现(西瓜书)

    决策树ID3原理及R语言python代码实现(西瓜书) 摘要: 决策树是机器学习中一种非常常见的分类与回归方法,可以认为是if-else结构的规则.分类决策树是由节点和有向边组成的树形结构,节点表示特 ...

  2. 串口调试助手vc源程序及其详细编写过程

    串口调试助手vc源程序及其详细编写过程   目次: 1.建立项目 2.在项目中插入MSComm控件 3.利用ClassWizard定义CMSComm类控制变量 4.在对话框中添加控件 5.添加串口事件 ...

  3. Mol Cell Proteomics. |马臻| psims-一个用于编写HUPO-PSI标准下的mzML和mzIdentML的python库

    大家好,本周分享的是发表在MCP(MOLECULAR&CRLLULAR PROTEOMICS)上的一篇关于质谱数据处理和识别的文章,题目是psims - A Declarative Write ...

  4. LASSO回归与L1正则化 西瓜书

    LASSO回归与L1正则化 西瓜书 2018年04月23日 19:29:57 BIT_666 阅读数 2968更多 分类专栏: 机器学习 机器学习数学原理 西瓜书   版权声明:本文为博主原创文章,遵 ...

  5. Selenium2学习-018-WebUI自动化实战实例-016-自动化脚本编写过程中的登录验证码问题

    日常的 Web 网站开发的过程中,为提升登录安全或防止用户通过脚本进行黄牛操作(宇宙最贵铁皮天朝魔都的机动车牌照竞拍中),很多网站在登录的时候,添加了验证码验证,而且验证码的实现越来越复杂,对其进行脚 ...

  6. 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览

    ### 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览 http://segmentfault.com/a/1190000002583569

  7. ARM Linux驱动篇 学习温度传感器ds18b20的驱动编写过程

    ARM Linux驱动篇 学习温度传感器ds18b20的驱动编写过程 原文地址:http://www.cnblogs.com/NickQ/p/9026545.html 一.开发板与ds18b20的入门 ...

  8. python实现简单决策树(信息增益)——基于周志华的西瓜书数据

    数据集如下: 色泽 根蒂 敲声 纹理 脐部 触感 好瓜 青绿 蜷缩 浊响 清晰 凹陷 硬滑 是 乌黑 蜷缩 沉闷 清晰 凹陷 硬滑 是 乌黑 蜷缩 浊响 清晰 凹陷 硬滑 是 青绿 蜷缩 沉闷 清晰 ...

  9. 【lombok】使用lombok注解,在代码编写过程中可以调用到get/set方法,但是在编译的时候无法通过,提示找不到get/set方法

    错误如题:使用lombok注解,在代码编写过程中可以调用到get/set方法,但是在编译的时候无法通过,提示找不到get/set方法 报错如下: 解决方法: 1.首先查看你的lombok插件是否下载安 ...

  10. 朴素贝叶斯python代码实现(西瓜书)

    朴素贝叶斯python代码实现(西瓜书) 摘要: 朴素贝叶斯也是机器学习中一种非常常见的分类方法,对于二分类问题,并且数据集特征为离散型属性的时候, 使用起来非常的方便.原理简单,训练效率高,拟合效果 ...

随机推荐

  1. 关于protobuf报错'tr1/unordered_map' file not found

    这个问题的话,查了很多资料,总的来说就是C++版本的问题,新版本的namespace结构变化了,C++库的层级结构变化了 1.config.h HASH_MAP_H    HASH_SET_H 新版本 ...

  2. 在CentOS 7.4下配置VNC Server服务

    安装步骤 1. 查询系统是否安装vnc-server [root@localhost ~]# rpm –qa | grep vnc 如果有返回值,类似于vnc-server-的值,说明已经安装了vnc ...

  3. macOS Big Sur 设置JAVA_HOME

    默认JAVA_HOME指向的是: /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home 这个不是我们自己安装的jdk,另外本 ...

  4. J V M大概理解

    jvm的大致流程:他把一个Class文件 通过类加载机制 装载到jvm里面,然后放到不同的运行时数据区(Runtime Data Areas),通过编译器来编译. 第一部分,我们可以关注class文件 ...

  5. 线性斜压模式LBM学习&安装实录

    本文基本参照了LBM的用户手册进行. 环境:Ubuntu 18.04LTS (Windows Subsystem Linux) 编译器:gfortran 7.5.0 安装包: lapack-3.9.0 ...

  6. reids哨兵机制

    宏观上的哨兵机制 监控:哨兵不断的检查master和slave是否正常的运行. 通知:当监控的某台Redis实例发生问题时,可以通过API通知系统管理员和其他的应用程序. 自动故障转移:如果一个mas ...

  7. 关系型数据库,基表Guid 主键设值

    在我们开发过程,为了自动适应新增修改,可以对基表,Guid 类型进行如下设置: public bool IsTransient() {       return this.Id == Guid.Emp ...

  8. gdb 常用命令总结

    安装插件 1. 安装GDB增强工具 (gef) * wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh2. ...

  9. logrotate配置记录

    对于一些比较频繁又没有太大意义的log,可以设定出更严格的切割策略 see https://blog.csdn.net/liuxiao723846/article/details/100120058 ...

  10. vscode 开发Vue项目

    写在开头 Vue作为前端项目,本身不依赖IDE,完全可以使用任何文本编辑器进行开发.我使用vscode仅是因为比较习惯,vscode几乎可以作为任何项目的开发IDE. 环境安装 安装nodejs,去官 ...