Skip to content

Commit 52ee9a1

Browse files
committed
commit convolution_neural_network.py
1 parent 0e0e75d commit 52ee9a1

File tree

1 file changed

+343
-0
lines changed

1 file changed

+343
-0
lines changed

Diff for: Neural_Network/convolution_neural_network.py

+343
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
#-*- coding: utf-8 -*-
2+
3+
'''
4+
- - - - - -- - - - - - - - - - - - - - - - - - - - - - -
5+
Name - - CNN - Convolution Neural Network For Photo Recognizing
6+
Goal - - Recognize Handing Writting Word Photo
7+
Detail:Total 5 layers neural network
8+
* Convolution layer
9+
* Pooling layer
10+
* Input layer layer of BP
11+
* Hiden layer of BP
12+
* Output layer of BP
13+
Author: Stephen Lee
14+
Program: PYTHON
15+
Date: 2017.9.20
16+
- - - - - -- - - - - - - - - - - - - - - - - - - - - - -
17+
'''
18+
import numpy as np
19+
import matplotlib.pyplot as plt
20+
21+
22+
class CNN():
23+
conv1 = []
24+
w_conv1 = []
25+
thre_conv1 = []
26+
step_conv1 = 0
27+
size_pooling1 = 0
28+
num_bp1 = 0
29+
num_bp2 = 0
30+
num_bp3 = 0
31+
thre_bp1 = []
32+
thre_bp2 = []
33+
wkj = np.mat([])
34+
vji = np.mat([])
35+
rate_weight = 0
36+
rate_thre = 0
37+
38+
39+
def __init__(self,conv1_get,size_p1,bp_num1,bp_num2,bp_num3,rate_w=0.2,rate_t=0.2):
40+
'''
41+
:param conv1_get: [a,c,d],size, number, step of convolution kernel
42+
:param size_p1: pooling size
43+
:param bp_num1: units number of flatten layer
44+
:param bp_num2: units number of hidden layer
45+
:param bp_num3: units number of output layer
46+
:param rate_w: rate of weight learning
47+
:param rate_t: rate of threshold learning
48+
'''
49+
self.num_bp1 = bp_num1
50+
self.num_bp2 = bp_num2
51+
self.num_bp3 = bp_num3
52+
self.conv1 = conv1_get[:2]
53+
self.step_conv1 = conv1_get[2]
54+
self.size_pooling1 = size_p1
55+
self.rate_weight = rate_w
56+
self.rate_thre = rate_t
57+
self.w_conv1 = [np.mat(-1*np.random.rand(self.conv1[0],self.conv1[0])+0.5) for i in range(self.conv1[1])]
58+
self.wkj = np.mat(-1 * np.random.rand(self.num_bp3, self.num_bp2) + 0.5)
59+
self.vji = np.mat(-1*np.random.rand(self.num_bp2, self.num_bp1)+0.5)
60+
self.thre_conv1 = -2*np.random.rand(self.conv1[1])+1
61+
self.thre_bp2 = -2*np.random.rand(self.num_bp2)+1
62+
self.thre_bp3 = -2*np.random.rand(self.num_bp3)+1
63+
64+
65+
def save_model(self,save_path):
66+
#将模型保存
67+
import pickle
68+
model_dic = {'num_bp1':self.num_bp1,
69+
'num_bp2':self.num_bp2,
70+
'num_bp3':self.num_bp3,
71+
'conv1':self.conv1,
72+
'step_conv1':self.step_conv1,
73+
'size_pooling1':self.size_pooling1,
74+
'rate_weight':self.rate_weight,
75+
'rate_thre':self.rate_thre,
76+
'w_conv1':self.w_conv1,
77+
'wkj':self.wkj,
78+
'vji':self.vji,
79+
'thre_conv1':self.thre_conv1,
80+
'thre_bp2':self.thre_bp2,
81+
'thre_bp3':self.thre_bp3}
82+
with open(save_path, 'wb') as f:
83+
pickle.dump(model_dic, f)
84+
85+
print('模型已经保存: %s'% save_path)
86+
87+
88+
def paste_model(self,save_path):
89+
#实例方法,
90+
#虽然这么写一点也不简洁。。。。
91+
#卸载这个里面的话,只是用于修改已经存在的模型,要根据读取的数据返回实例的模型,再写一个吧
92+
import pickle
93+
with open(save_path, 'rb') as f:
94+
model_dic = pickle.load(f)
95+
self.num_bp1 = model_dic.get('num_bp1')
96+
self.num_bp2 = model_dic.get('num_bp2')
97+
self.num_bp3 = model_dic.get('num_bp3')
98+
self.conv1 = model_dic.get('conv1')
99+
self.step_conv1 = model_dic.get('step_conv1')
100+
self.size_pooling1 = model_dic.get('size_pooling1')
101+
self.rate_weight = model_dic.get('rate_weight')
102+
self.rate_thre = model_dic.get('rate_thre')
103+
self.w_conv1 = model_dic.get('w_conv1')
104+
self.wkj = model_dic.get('wkj')
105+
self.vji = model_dic.get('vji')
106+
self.thre_conv1 = model_dic.get('thre_conv1')
107+
self.thre_bp2 = model_dic.get('thre_bp2')
108+
self.thre_bp3 = model_dic.get('thre_bp3')
109+
print('已经成功读取模型')
110+
111+
@classmethod
112+
def ReadModel(cls,model_path):
113+
#类方法,读取保存的模型,返回一个实例。
114+
import pickle
115+
with open(model_path, 'rb') as f:
116+
model_dic = pickle.load(f)
117+
118+
conv_get= model_dic.get('conv1')
119+
conv_get.append(model_dic.get('step_conv1'))
120+
size_p1 = model_dic.get('size_pooling1')
121+
bp1 = model_dic.get('num_bp1')
122+
bp2 = model_dic.get('num_bp2')
123+
bp3 = model_dic.get('num_bp3')
124+
r_w = model_dic.get('rate_weight')
125+
r_t = model_dic.get('rate_thre')
126+
#创建实例
127+
conv_ins = CNN(conv_get,size_p1,bp1,bp2,bp3,r_w,r_t)
128+
#修改实例的参数
129+
conv_ins.w_conv1 = model_dic.get('w_conv1')
130+
conv_ins.wkj = model_dic.get('wkj')
131+
conv_ins.vji = model_dic.get('vji')
132+
conv_ins.thre_conv1 = model_dic.get('thre_conv1')
133+
conv_ins.thre_bp2 = model_dic.get('thre_bp2')
134+
conv_ins.thre_bp3 = model_dic.get('thre_bp3')
135+
return conv_ins
136+
137+
138+
def sig(self,x):
139+
return 1 / (1 + np.exp(-1*x))
140+
def do_round(self,x):
141+
return round(x, 3)
142+
#卷积
143+
def Convolute(self,data,convs,w_convs,thre_convs,conv_step):
144+
size_conv = convs[0]
145+
num_conv =convs[1]
146+
size_data = np.shape(data)[0]
147+
#得到原图像滑动的小图,data_focus
148+
data_focus = []
149+
for i_focus in range(0, size_data - size_conv + 1, conv_step):
150+
for j_focus in range(0, size_data - size_conv + 1, conv_step):
151+
focus = data[i_focus:i_focus + size_conv, j_focus:j_focus + size_conv]
152+
data_focus.append(focus)
153+
#计算所有卷积核得到的特征图,每个特征图以矩阵形式,存储为一个列表data_featuremap
154+
data_featuremap = []
155+
Size_FeatureMap = int((size_data - size_conv) / conv_step + 1)
156+
for i_map in range(num_conv):
157+
featuremap = []
158+
for i_focus in range(len(data_focus)):
159+
net_focus = np.sum(np.multiply(data_focus[i_focus], w_convs[i_map])) - thre_convs[i_map]
160+
featuremap.append(self.sig(net_focus))
161+
featuremap = np.asmatrix(featuremap).reshape(Size_FeatureMap, Size_FeatureMap)
162+
data_featuremap.append(featuremap)
163+
164+
#将data_focus中的focus展开为一维
165+
focus1_list = []
166+
for each_focus in data_focus:
167+
focus1_list.extend(self.Expand_Mat(each_focus))
168+
focus_list = np.asarray(focus1_list)
169+
return focus_list,data_featuremap
170+
171+
# 池化
172+
def Pooling(self,featuremaps,size_pooling):
173+
size_map = len(featuremaps[0])
174+
size_pooled = int(size_map/size_pooling)
175+
featuremap_pooled = []
176+
for i_map in range(len(featuremaps)):
177+
map = featuremaps[i_map]
178+
map_pooled = []
179+
for i_focus in range(0,size_map,size_pooling):
180+
for j_focus in range(0, size_map, size_pooling):
181+
focus = map[i_focus:i_focus + size_pooling, j_focus:j_focus + size_pooling]
182+
#平均池化
183+
map_pooled.append(np.average(focus))
184+
#最大池化
185+
#map_pooled.append(np.max(focus))
186+
map_pooled = np.asmatrix(map_pooled).reshape(size_pooled,size_pooled)
187+
featuremap_pooled.append(map_pooled)
188+
return featuremap_pooled
189+
190+
def Expand(self,datas):
191+
#将三元的数据展开为1为的list
192+
data_expanded = []
193+
for i in range(len(datas)):
194+
shapes = np.shape(datas[i])
195+
data_listed = datas[i].reshape(1,shapes[0]*shapes[1])
196+
data_listed = data_listed.getA().tolist()[0]
197+
data_expanded.extend(data_listed)
198+
#连接所有数据
199+
data_expanded = np.asarray(data_expanded)
200+
return data_expanded
201+
202+
def Expand_Mat(self,data_mat):
203+
#用来展开矩阵为一维的list
204+
data_mat = np.asarray(data_mat)
205+
shapes = np.shape(data_mat)
206+
data_expanded = data_mat.reshape(1,shapes[0]*shapes[1])
207+
return data_expanded
208+
209+
def Getpd_From_Pool(self,out_map,pd_pool,num_map,size_map,size_pooling):
210+
'''
211+
误差反传,从pooled到前一个map, 例如将池化层6*6的误差矩阵扩大为12*12的误差矩阵
212+
pd_pool: 是采样层的误差,list形式。。。。要改要改
213+
out_map: 前面特征图的输出,数量*size*size的列表形式
214+
return: pd_all:前面层所有的特征图的pd, num*size_map*size_map的列表形式
215+
'''
216+
pd_all = []
217+
i_pool = 0
218+
for i_map in range(num_map):
219+
pd_conv1 = np.ones((size_map, size_map))
220+
for i in range(0, size_map, size_pooling):
221+
for j in range(0, size_map, size_pooling):
222+
pd_conv1[i:i + size_pooling, j:j + size_pooling] = pd_pool[i_pool]
223+
i_pool = i_pool + 1
224+
pd_conv2 = np.multiply(pd_conv1,np.multiply(out_map[i_map],(1-out_map[i_map])))
225+
pd_all.append(pd_conv2)
226+
return pd_all
227+
228+
def trian(self,patterns,datas_train, datas_teach, n_repeat, error_accuracy,draw_e = bool):
229+
print('----------------------Start Training-------------------------')
230+
print(' - - Shape: Train_Data ',np.shape(datas_train))
231+
print(' - - Shape: Teach_Data ',np.shape(datas_teach))
232+
rp = 0
233+
all_mse = []
234+
mse = 10000
235+
while rp < n_repeat and mse >= error_accuracy:
236+
alle = 0
237+
print('-------------进行第%d次学习--------------'%rp)
238+
for p in range(len(datas_train)):
239+
#print('------------学习第%d个图像--------------'%p)
240+
data_train = np.asmatrix(datas_train[p])
241+
data_teach = np.asarray(datas_teach[p])
242+
data_focus1,data_conved1 = self.Convolute(data_train,self.conv1,self.w_conv1,
243+
self.thre_conv1,conv_step=self.step_conv1)
244+
data_pooled1 = self.Pooling(data_conved1,self.size_pooling1)
245+
shape_featuremap1 = np.shape(data_conved1)
246+
'''
247+
print(' -----original shape ', np.shape(data_train))
248+
print(' ---- after convolution ',np.shape(data_conv1))
249+
print(' -----after pooling ',np.shape(data_pooled1))
250+
'''
251+
data_bp_input = self.Expand(data_pooled1)
252+
# 计算第一层输入输出
253+
bp_out1 = data_bp_input
254+
# 计算第二层输入输出
255+
bp_net_j = np.dot(bp_out1,self.vji.T) - self.thre_bp2
256+
bp_out2 = self.sig(bp_net_j)
257+
# 计算第三层输入输出
258+
bp_net_k = np.dot(bp_out2 ,self.wkj.T) - self.thre_bp3
259+
bp_out3 = self.sig(bp_net_k)
260+
261+
# 计算一般化误差
262+
pd_k_all = np.multiply((data_teach - bp_out3), np.multiply(bp_out3, (1 - bp_out3)))
263+
pd_j_all = np.multiply(np.dot(pd_k_all,self.wkj), np.multiply(bp_out2, (1 - bp_out2)))
264+
pd_i_all = np.dot(pd_j_all,self.vji)
265+
266+
pd_conv1_pooled = pd_i_all / (self.size_pooling1*self.size_pooling1)
267+
pd_conv1_pooled = pd_conv1_pooled.T.getA().tolist()
268+
pd_conv1_all = self.Getpd_From_Pool(data_conved1,pd_conv1_pooled,shape_featuremap1[0],
269+
shape_featuremap1[1],self.size_pooling1)
270+
271+
#卷积层1的权重和阈值修正,每个卷积核的权重需要修正 12*12(map) 次
272+
#修正量为featuremap中点的偏导值 乘以 前一层图像focus, 整个权重模板一起更新
273+
for k_conv in range(self.conv1[1]):
274+
pd_conv_list = self.Expand_Mat(pd_conv1_all[k_conv])
275+
delta_w = self.rate_weight * np.dot(pd_conv_list,data_focus1)
276+
277+
self.w_conv1[k_conv] = self.w_conv1[k_conv] + delta_w.reshape((self.conv1[0],self.conv1[0]))
278+
279+
self.thre_conv1[k_conv] = self.thre_conv1[k_conv] - np.sum(pd_conv1_all[k_conv]) * self.rate_thre
280+
# 更新kj层的权重
281+
282+
self.wkj = self.wkj + pd_k_all.T * bp_out2 * self.rate_weight
283+
# 更新ji层的权重
284+
self.vji = self.vji + pd_j_all.T * bp_out1 * self.rate_weight
285+
# 更新阈值
286+
self.thre_bp3 = self.thre_bp3 - pd_k_all * self.rate_thre
287+
self.thre_bp2 = self.thre_bp2 - pd_j_all * self.rate_thre
288+
# 计算总误差
289+
errors = np.sum(abs((data_teach - bp_out3)))
290+
alle = alle + errors
291+
#print(' ----Teach ',data_teach)
292+
#print(' ----BP_output ',bp_out3)
293+
rp = rp + 1
294+
mse = alle/patterns
295+
all_mse.append(mse)
296+
def draw_error():
297+
yplot = [error_accuracy for i in range(int(n_repeat * 1.2))]
298+
plt.plot(all_mse, '+-')
299+
plt.plot(yplot, 'r--')
300+
plt.xlabel('Learning Times')
301+
plt.ylabel('All_mse')
302+
plt.grid(True, alpha=0.5)
303+
plt.show()
304+
print('------------------Training Complished---------------------')
305+
print(' - - Training epoch: ', rp, ' - - Mse: %.6f' % mse)
306+
if draw_e:
307+
draw_error()
308+
return mse
309+
310+
def produce(self,datas_test):
311+
#对验证和测试数据集进行输出
312+
produce_out = []
313+
print('-------------------Start Testing-------------------------')
314+
print(' - - Shape: Test_Data ',np.shape(datas_test))
315+
for p in range(len(datas_test)):
316+
print('--------测试第%d个图像----------' % p)
317+
data_test = np.asmatrix(datas_test[p])
318+
data_focus1, data_conved1 = self.Convolute(data_test, self.conv1, self.w_conv1,
319+
self.thre_conv1, conv_step=self.step_conv1)
320+
data_pooled1 = self.Pooling(data_conved1, self.size_pooling1)
321+
data_bp_input = self.Expand(data_pooled1)
322+
# 计算第一层输入输出
323+
bp_out1 = data_bp_input
324+
# 计算第二层输入输出
325+
bp_net_j = bp_out1 * self.vji.T - self.thre_bp2
326+
bp_out2 = self.sig(bp_net_j)
327+
# 计算第三层输入输出
328+
bp_net_k = bp_out2 * self.wkj.T - self.thre_bp3
329+
bp_out3 = self.sig(bp_net_k)
330+
produce_out.extend(bp_out3.getA().tolist())
331+
res = [list(map(self.do_round,each)) for each in produce_out]
332+
return np.asarray(res)
333+
334+
def convolution(self,data):
335+
#返回卷积和池化后的数据,用于查看图像
336+
data_test = np.asmatrix(data)
337+
data_focus1, data_conved1 = self.Convolute(data_test, self.conv1, self.w_conv1,
338+
self.thre_conv1, conv_step=self.step_conv1)
339+
data_pooled1 = self.Pooling(data_conved1, self.size_pooling1)
340+
341+
return data_conved1,data_pooled1
342+
343+

0 commit comments

Comments
 (0)