|
应朋友之请写了一份python实现单隐层BP Ann model的code,好久没写博客,就顺便发上来。这篇代码比较干净利落,比较纯粹的描述了Ann的基本原理,初学机器学习的同学可以参考。
模型中几个比较重要的参数:
1.学习率
学习率是影响模型收敛的重要因素,一般来说要根据具体场景灵活调整,过高的学习率会使得函数快速发散。
2.隐元数量
一般来说,增加隐层中神经元的数量比直接增加隐层更加有效,这也是单隐层神经网络的特点。对于复杂程度不算太高的问题而言,单隐层的效果优于多隐层。
3.随机种子位数
代码中增加了这一参数,来控制初始化连接权与阈值的精度。由于神经网络中初始权重与阈值是随机生成的,那么其随机精度会对结果产生一定的影响。在输入元、隐元的数量较多时,调整随机精度会起到减小误差的作用。
代码中举了一个非常简单的训练示例,笔者自拟了一个规则:
输入两个变量,当变量A = 变量B时,返回类型1,矩阵化为[1,0]。当变量A != 变量B时,返回类型2,矩阵化为[0,1]。
让神经网络去学习这个simple的规则,并给出20条测试数据去验证。最终使用了5000条训练数据,就获得了100%的正确分类能力。
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
| #---Author:伍思磊---
#---Mail:wusilei@1006.tv---
#---2015/7/27---
import random
import math
#---神经网络Model---
class Ann:
#构造函数 初始化模型参数
def __init__(self, i_num, h_num, o_num):
#可调参数
self.learn_rate = 0.1 #学习率
self.num_long = 2 #输出结果位数
self.random_long = 10 #随机种子位数
#输入参数
self.input_num = i_num #输入层 数量
self.hidden_num = h_num #隐层 数量
self.output_num = o_num #输出层 数量
#模型参数
self.input = [] #输入层
self.hidden = [] #隐层
self.output = [] #输出层
self.error = [] #误差
self.expectation = [] #期望
self.weight_ih = self.__ini_weight(self.input_num, self.hidden_num) #输入层->隐层 连接权
self.weight_ho = self.__ini_weight(self.hidden_num, self.output_num) #隐层->输出层 连接权
self.threshold_h = self.__ini_threshold(self.hidden_num) #隐层 阈值
self.threshold_o = self.__ini_threshold(self.output_num) #输出层 阈值
#初始连接权生成器
def __ini_weight(self, x, y):
result = []
long = math.pow(10, self.random_long)
for i in range(0, x, 1):
res = []
for j in range(0, y, 1):
num = round(random.randint(-1*long,long)/long, self.random_long)
res.insert(j, num)
result.insert(i, res)
return result
#初始阈值生成器
def __ini_threshold(self, n):
result = []
long = pow(10, self.random_long)
for i in range(0, n, 1):
num = round(random.randint(-1*long,long)/long, self.random_long)
result.insert(i, num)
return result
#激励函数 sigma
def excitation(self, value):
sigma = 1/(1+(math.exp(-1*value)))
return sigma
#输入数据
def input_param(self, data, expectation = []):
self.input = []
for value in data:
self.input.append(value)
if(expectation):
self.expectation = []
for value in expectation:
self.expectation.append(value)
#隐层计算
def count_hidden(self):
self.hidden = []
for h in range(0, self.hidden_num, 1):
Hval = 0
for i in range(len(self.input)):
Hval += self.input * self.weight_ih[h]
Hval = self.excitation(Hval+self.threshold_h[h])
self.hidden.insert(h, Hval)
#输出层计算
def count_output(self):
self.output = []
for o in range(0, self.output_num, 1):
Oval = 0
for h in range(len(self.hidden)):
Oval += self.hidden[h] * self.weight_ho[h][o]
Oval += self.threshold_o[o]
Oval = round(Oval, self.num_long)
self.output.insert(o, Oval)
#误差计算
def count_error(self):
self.error = []
for key in range(len(self.output)):
self.error.insert(key, self.expectation[key] - self.output[key])
#连接权反馈训练 输入层->隐层
def train_weight_ih(self):
for i in range(len(self.weight_ih)):
for h in range(len(self.weight_ih)):
tmp = 0
for o in range(0, self.output_num, 1):
tmp += self.weight_ho[h][o] * self.error[o]
self.weight_ih[h] = self.weight_ih[h] + self.learn_rate * self.hidden[h] * (1 - self.hidden[h]) * self.input * tmp
#连接权反馈训练 隐层->输出层
def train_weight_ho(self):
for h in range(len(self.weight_ho)):
for o in range(len(self.weight_ho[h])):
self.weight_ho[h][o] = self.weight_ho[h][o] + self.learn_rate * self.hidden[h] * self.error[o]
#阈值反馈训练 隐层
def train_threshold_h(self):
for h in range(len(self.threshold_h)):
tmp = 0
for o in range(0, self.output_num, 1):
tmp += self.weight_ho[h][o] * self.error[o]
self.threshold_h[h] = self.threshold_h[h] + self.learn_rate * self.hidden[h] * (1 - self.hidden[h]) * tmp
#阈值反馈训练 输出层
def train_threshold_o(self):
for o in range(len(self.threshold_o)):
self.threshold_o[o] = self.threshold_o[o] + self.error[o]
#反馈训练
def train(self):
self.train_weight_ih()
self.train_weight_ho()
self.train_threshold_h()
self.train_threshold_o()
#归一化函数
def normal_num(self, max, min, data):
data = (data - min)/(max - min)
return data
#寻找集合的最大值和最小值
#---业务部分(示例)---
#要训练的规则,输入两个值,如果两值相等返回[1,0],反之返回[0,1]
def testFunc(val):
if(val[0] == val[1]):
return [1,0]
else:
return [0,1]
#构造神经网络模型
ann = Ann(2,3,2)
#生成训练数据,随机生成5000组[0,1][1,0][1,1][0,0]随机数组
data = []
for i in range(0, 10000, 1):
x = random.randint(0,1)
y = random.randint(0,1)
data.append([x,y])
#取得训练数据中的最大值和最小值
for i in range(len(data)):
for j in range(len(data)):
if(i == 0 and j == 0):
max = min = data[j]
elif(data[j] > max):
max = data[j]
elif(data[j] < min):
min = data[j]
#训练数据归一化
dataNormal = []
for i in range(len(data)):
dataNormal.insert(i, [])
for j in range(len(data)):
dataNormal.append(ann.normal_num(max, min, data[j]))
#计算训练数据期望值,并进行反馈训练
for i in range(len(data)):
#计算期望值
exp = testFunc(data)
#输入训练数据与期望
ann.input_param(dataNormal, exp)
#计算隐层
ann.count_hidden()
#计算输出层
ann.count_output()
#计算误差
ann.count_error()
#反馈训练
ann.train()
#生成测试数据,随机生成20组
testdata = []
for i in range(0, 20, 1):
x = random.randint(0,1)
y = random.randint(0,1)
testdata.append([x,y])
#进行测试,同时输出神经网络预测值与实际期望值
for i in range(len(testdata)):
exp = testFunc(testdata)
ann.input_param(testdata)
ann.count_hidden()
ann.count_output()
print("Ann:")
print(ann.output)
print("Exp:")
print(exp)
print("\r")
|
|
|