0%

python实现bp神经网络

简介

本篇blog是基于python的bp神经网络代码实现,本身没有借助任何包,主要是想对该算法进行一个深入了解。基于马疝病数据集的一个二分类,结构相对简单,准确性不是很高,但是对神经网络的深入理解有很大的启发

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
from tqdm import tqdm
import numpy as np
'''
用户手册——by clever_bobo
本函数是基于bp神经网络的二分类项目,(输出层激活函数为sigmod)是最基本的3层网络,暂时没有设置纠错选项,请谨慎输入
多分类,输出层激活函数请使用线性整流函数ReLU或者不设置激活函数
输入项分别为训练数据集,模型数据集,隐藏层节点数量,训练次数,学习率
为方便显示,特加入tqdm模块,加个显示条

学习随笔:
目前的主要问题:
bp神经网络核心还是基于梯度下降法优化的,但是此时损失函数是非凸的,也就是说局部最小不一定是全局最小,有可能会到一个跟全局最小差别很大的局部最小点或者鞍点

梯度消失问题(鞍点?激活函数引起的尤其是sigmod,tanh)

计算时间长(目前大部分人都吐槽的问题)


优化(本代码均未使用):
初始化一般随机化参数,满足均值为0的正态分布,方差一般取2/(N+M),N为上一层节点数量,M为下一层节点数量
随机梯度下降增加动量(加速收敛,减少震荡)
'''
#读取数据
def Readdata(filename):
#创建指向文件的指针,用于打开文件
fp=open(filename)
#创建放置数据和标签的空列表
dataset,datalabel=[],[]
#读取文件
for i in fp.readlines():
#文件按行读取,每一行存为一个字符串,根据数据记录格式对其进行切割
databuff=i.strip().split()
#将数据和标签(每行最后一个)分别放入对应的列表,这里使用的是append函数,千万不要用extend函数
dataset.append([float(j) for j in databuff[:-1]])
datalabel.append(float(databuff[-1]))
#返回读取的数据和标签
return dataset,datalabel

#设置参数,本代码使用的是3层神经网络,暂时不支持多层
def Para_Init(input,hidden=3,output=3):
#设置隐藏层单元的权重,参数大小服从标准正态分布
input_hidden=np.random.randn(input,hidden)
#设置输出单元的权重
hidden_output=np.random.randn(hidden,output)
#设置隐藏层的偏置值
hidden_bias=np.random.randn(1,hidden)
#设置输出层的偏置值
output_bias=np.random.randn(1,output)
#返回参数
return input_hidden,hidden_output,hidden_bias,output_bias

#设置激活函数,本函数使用的是sigmod函数,该函数主要用于二分类
def sigmod(z):
return 1/(1+np.exp(-z))


#设置sigmod函数的微分项,后面对参数纠正时候会用到
def D_sigmod(z):
return np.multiply(z,(1-z))

#训练函数,用于训练参数,参数设置依次为数据,标签,权重,偏置,学习率
# 核心算法在这部分,纠正参数部分看不懂就自己推导一遍公式
def Train(dataset,datalabel,input_hidden,hidden_output,hidden_bias,output_bias,learn_rate=0.01):
#for循环就是
for i in range(len(datalabel)):
#设置输入值
input_value=np.mat(dataset[i])
#设置样本中的标签值
output_label=np.mat(datalabel[i])
#计算隐藏层的单元值得大小
hidden_value=sigmod(np.dot(input_value,input_hidden)-hidden_bias)
#计算神经网络的输出,因为本样本是二分类,所以采用sigmod激活
output_value=sigmod(np.dot(hidden_value,hidden_output)-output_bias)
#更新参数
#函数求导
d_output_value=D_sigmod(output_value)
#计算误差
error=output_label-output_value
#计算输出层层权重+偏置更新量
hidden_output_change=learn_rate*np.dot(np.transpose(hidden_value),np.multiply(error,d_output_value))
output_bias_change=-learn_rate*np.multiply(error,d_output_value)
#更新隐藏层权重+偏置
d_hidden_value=D_sigmod(hidden_value)
t2=np.transpose(np.dot(hidden_output,np.multiply(error,d_output_value)))
input_hidden_change=learn_rate*np.dot(np.transpose(input_value),np.multiply(t2,d_hidden_value))
hidden_bias_change=-learn_rate*t2
#数值更新
hidden_bias +=hidden_bias_change
hidden_output +=hidden_output_change
input_hidden +=input_hidden_change
output_bias += output_bias_change
return hidden_bias,hidden_output,input_hidden,output_bias

#测试模型的准确程度(本次测试仅限于二分类的情况,多分类在输出层激活函数不要用sigmod函数)
def Testing(dataset,datalabel,hidden_bias,hidden_output,input_hidden,output_bias):
rightnum=0
#num0,num1=0,0
for i in range(len(dataset)):
input_value=np.mat(dataset[i])
output_label=np.mat(datalabel[i])
hidden_value=sigmod(np.dot(input_value,input_hidden)-hidden_bias)
output_value=sigmod(np.dot(hidden_value,hidden_output)-output_bias)
if abs(output_value-output_label)<0.5:
print("本次判断正确!模型判断为%d,实际为%d"%(datalabel[i],datalabel[i]))
rightnum += 1
else:
t=abs(datalabel[i]-1.0)
print("失败了失败了!模型判断为%d,实际为%d"%(t,datalabel[i]))

return rightnum*1.0/len(datalabel)
if __name__ =="__main__":
dataset, datalabel = Readdata(r'C:\Users\97751\Desktop\BP神经网络(马疝病数据集)\horseColicTraining.txt')
#datatest,labeltest =Readdata(r"C:\Users\97751\Desktop\BP神经网络(马疝病数据集)\horseColicTest.txt")
hidden=int(input("神经网络设置多少个隐藏节点:"))
input_hidden,hidden_output,hidden_bias,output_bias=Para_Init(len(dataset[0]),hidden,output=1)
time=int(input("训练次数?"))
learn_rate=float(input("学习率?"))
for i in tqdm(range(time)):
hidden_bias,hidden_output,input_hidden,output_bias=Train(dataset,datalabel,input_hidden,hidden_output,hidden_bias,output_bias,learn_rate)
#error=Testing(datatest,labeltest,hidden_bias,hidden_output,input_hidden,output_bias)
error=Testing(dataset, datalabel,hidden_bias,hidden_output,input_hidden,output_bias)
print("正确率为:%.4f"%(error))

实验结果

本代码的准确率大概在80%左右,不算高,没有任何优化,纯粹作为理解算法原理使用,使用的数据集暂时放在百度云盘上(以后可能会直接放在github仓库),链接如下:
链接:https://pan.baidu.com/s/17vhkmKcf-C_qDREX7Fujjw 提取码:tgha
如若想要真正应用建议使用当前的python的机器学习库,里面集成了很多算法模型!

如果对您有用的话,这里可以打赏哦~