TheAlgorithms-Python
357 строк · 14.0 Кб
1"""
2- - - - - -- - - - - - - - - - - - - - - - - - - - - - -
3Name - - CNN - Convolution Neural Network For Photo Recognizing
4Goal - - Recognize Handing Writing Word Photo
5Detail: Total 5 layers neural network
6* Convolution layer
7* Pooling layer
8* Input layer layer of BP
9* Hidden layer of BP
10* Output layer of BP
11Author: Stephen Lee
12Github: 245885195@qq.com
13Date: 2017.9.20
14- - - - - -- - - - - - - - - - - - - - - - - - - - - - -
15"""
16
17import pickle18
19import numpy as np20from matplotlib import pyplot as plt21
22
23class CNN:24def __init__(25self, conv1_get, size_p1, bp_num1, bp_num2, bp_num3, rate_w=0.2, rate_t=0.226):27"""28:param conv1_get: [a,c,d], size, number, step of convolution kernel
29:param size_p1: pooling size
30:param bp_num1: units number of flatten layer
31:param bp_num2: units number of hidden layer
32:param bp_num3: units number of output layer
33:param rate_w: rate of weight learning
34:param rate_t: rate of threshold learning
35"""
36self.num_bp1 = bp_num137self.num_bp2 = bp_num238self.num_bp3 = bp_num339self.conv1 = conv1_get[:2]40self.step_conv1 = conv1_get[2]41self.size_pooling1 = size_p142self.rate_weight = rate_w43self.rate_thre = rate_t44rng = np.random.default_rng()45self.w_conv1 = [46np.asmatrix(-1 * rng.random((self.conv1[0], self.conv1[0])) + 0.5)47for i in range(self.conv1[1])48]49self.wkj = np.asmatrix(-1 * rng.random((self.num_bp3, self.num_bp2)) + 0.5)50self.vji = np.asmatrix(-1 * rng.random((self.num_bp2, self.num_bp1)) + 0.5)51self.thre_conv1 = -2 * rng.random(self.conv1[1]) + 152self.thre_bp2 = -2 * rng.random(self.num_bp2) + 153self.thre_bp3 = -2 * rng.random(self.num_bp3) + 154
55def save_model(self, save_path):56# save model dict with pickle57model_dic = {58"num_bp1": self.num_bp1,59"num_bp2": self.num_bp2,60"num_bp3": self.num_bp3,61"conv1": self.conv1,62"step_conv1": self.step_conv1,63"size_pooling1": self.size_pooling1,64"rate_weight": self.rate_weight,65"rate_thre": self.rate_thre,66"w_conv1": self.w_conv1,67"wkj": self.wkj,68"vji": self.vji,69"thre_conv1": self.thre_conv1,70"thre_bp2": self.thre_bp2,71"thre_bp3": self.thre_bp3,72}73with open(save_path, "wb") as f:74pickle.dump(model_dic, f)75
76print(f"Model saved: {save_path}")77
78@classmethod79def read_model(cls, model_path):80# read saved model81with open(model_path, "rb") as f:82model_dic = pickle.load(f) # noqa: S30183
84conv_get = model_dic.get("conv1")85conv_get.append(model_dic.get("step_conv1"))86size_p1 = model_dic.get("size_pooling1")87bp1 = model_dic.get("num_bp1")88bp2 = model_dic.get("num_bp2")89bp3 = model_dic.get("num_bp3")90r_w = model_dic.get("rate_weight")91r_t = model_dic.get("rate_thre")92# create model instance93conv_ins = CNN(conv_get, size_p1, bp1, bp2, bp3, r_w, r_t)94# modify model parameter95conv_ins.w_conv1 = model_dic.get("w_conv1")96conv_ins.wkj = model_dic.get("wkj")97conv_ins.vji = model_dic.get("vji")98conv_ins.thre_conv1 = model_dic.get("thre_conv1")99conv_ins.thre_bp2 = model_dic.get("thre_bp2")100conv_ins.thre_bp3 = model_dic.get("thre_bp3")101return conv_ins102
103def sig(self, x):104return 1 / (1 + np.exp(-1 * x))105
106def do_round(self, x):107return round(x, 3)108
109def convolute(self, data, convs, w_convs, thre_convs, conv_step):110# convolution process111size_conv = convs[0]112num_conv = convs[1]113size_data = np.shape(data)[0]114# get the data slice of original image data, data_focus115data_focus = []116for i_focus in range(0, size_data - size_conv + 1, conv_step):117for j_focus in range(0, size_data - size_conv + 1, conv_step):118focus = data[119i_focus : i_focus + size_conv, j_focus : j_focus + size_conv120]121data_focus.append(focus)122# calculate the feature map of every single kernel, and saved as list of matrix123data_featuremap = []124size_feature_map = int((size_data - size_conv) / conv_step + 1)125for i_map in range(num_conv):126featuremap = []127for i_focus in range(len(data_focus)):128net_focus = (129np.sum(np.multiply(data_focus[i_focus], w_convs[i_map]))130- thre_convs[i_map]131)132featuremap.append(self.sig(net_focus))133featuremap = np.asmatrix(featuremap).reshape(134size_feature_map, size_feature_map135)136data_featuremap.append(featuremap)137
138# expanding the data slice to One dimenssion139focus1_list = []140for each_focus in data_focus:141focus1_list.extend(self.Expand_Mat(each_focus))142focus_list = np.asarray(focus1_list)143return focus_list, data_featuremap144
145def pooling(self, featuremaps, size_pooling, pooling_type="average_pool"):146# pooling process147size_map = len(featuremaps[0])148size_pooled = int(size_map / size_pooling)149featuremap_pooled = []150for i_map in range(len(featuremaps)):151feature_map = featuremaps[i_map]152map_pooled = []153for i_focus in range(0, size_map, size_pooling):154for j_focus in range(0, size_map, size_pooling):155focus = feature_map[156i_focus : i_focus + size_pooling,157j_focus : j_focus + size_pooling,158]159if pooling_type == "average_pool":160# average pooling161map_pooled.append(np.average(focus))162elif pooling_type == "max_pooling":163# max pooling164map_pooled.append(np.max(focus))165map_pooled = np.asmatrix(map_pooled).reshape(size_pooled, size_pooled)166featuremap_pooled.append(map_pooled)167return featuremap_pooled168
169def _expand(self, data):170# expanding three dimension data to one dimension list171data_expanded = []172for i in range(len(data)):173shapes = np.shape(data[i])174data_listed = data[i].reshape(1, shapes[0] * shapes[1])175data_listed = data_listed.getA().tolist()[0]176data_expanded.extend(data_listed)177data_expanded = np.asarray(data_expanded)178return data_expanded179
180def _expand_mat(self, data_mat):181# expanding matrix to one dimension list182data_mat = np.asarray(data_mat)183shapes = np.shape(data_mat)184data_expanded = data_mat.reshape(1, shapes[0] * shapes[1])185return data_expanded186
187def _calculate_gradient_from_pool(188self, out_map, pd_pool, num_map, size_map, size_pooling189):190"""191calculate the gradient from the data slice of pool layer
192pd_pool: list of matrix
193out_map: the shape of data slice(size_map*size_map)
194return: pd_all: list of matrix, [num, size_map, size_map]
195"""
196pd_all = []197i_pool = 0198for i_map in range(num_map):199pd_conv1 = np.ones((size_map, size_map))200for i in range(0, size_map, size_pooling):201for j in range(0, size_map, size_pooling):202pd_conv1[i : i + size_pooling, j : j + size_pooling] = pd_pool[203i_pool
204]205i_pool = i_pool + 1206pd_conv2 = np.multiply(207pd_conv1, np.multiply(out_map[i_map], (1 - out_map[i_map]))208)209pd_all.append(pd_conv2)210return pd_all211
212def train(213self, patterns, datas_train, datas_teach, n_repeat, error_accuracy, draw_e=bool214):215# model training216print("----------------------Start Training-------------------------")217print((" - - Shape: Train_Data ", np.shape(datas_train)))218print((" - - Shape: Teach_Data ", np.shape(datas_teach)))219rp = 0220all_mse = []221mse = 10000222while rp < n_repeat and mse >= error_accuracy:223error_count = 0224print(f"-------------Learning Time {rp}--------------")225for p in range(len(datas_train)):226# print('------------Learning Image: %d--------------'%p)227data_train = np.asmatrix(datas_train[p])228data_teach = np.asarray(datas_teach[p])229data_focus1, data_conved1 = self.convolute(230data_train,231self.conv1,232self.w_conv1,233self.thre_conv1,234conv_step=self.step_conv1,235)236data_pooled1 = self.pooling(data_conved1, self.size_pooling1)237shape_featuremap1 = np.shape(data_conved1)238"""239print(' -----original shape ', np.shape(data_train))
240print(' ---- after convolution ',np.shape(data_conv1))
241print(' -----after pooling ',np.shape(data_pooled1))
242"""
243data_bp_input = self._expand(data_pooled1)244bp_out1 = data_bp_input245
246bp_net_j = np.dot(bp_out1, self.vji.T) - self.thre_bp2247bp_out2 = self.sig(bp_net_j)248bp_net_k = np.dot(bp_out2, self.wkj.T) - self.thre_bp3249bp_out3 = self.sig(bp_net_k)250
251# --------------Model Leaning ------------------------252# calculate error and gradient---------------253pd_k_all = np.multiply(254(data_teach - bp_out3), np.multiply(bp_out3, (1 - bp_out3))255)256pd_j_all = np.multiply(257np.dot(pd_k_all, self.wkj), np.multiply(bp_out2, (1 - bp_out2))258)259pd_i_all = np.dot(pd_j_all, self.vji)260
261pd_conv1_pooled = pd_i_all / (self.size_pooling1 * self.size_pooling1)262pd_conv1_pooled = pd_conv1_pooled.T.getA().tolist()263pd_conv1_all = self._calculate_gradient_from_pool(264data_conved1,265pd_conv1_pooled,266shape_featuremap1[0],267shape_featuremap1[1],268self.size_pooling1,269)270# weight and threshold learning process---------271# convolution layer272for k_conv in range(self.conv1[1]):273pd_conv_list = self._expand_mat(pd_conv1_all[k_conv])274delta_w = self.rate_weight * np.dot(pd_conv_list, data_focus1)275
276self.w_conv1[k_conv] = self.w_conv1[k_conv] + delta_w.reshape(277(self.conv1[0], self.conv1[0])278)279
280self.thre_conv1[k_conv] = (281self.thre_conv1[k_conv]282- np.sum(pd_conv1_all[k_conv]) * self.rate_thre283)284# all connected layer285self.wkj = self.wkj + pd_k_all.T * bp_out2 * self.rate_weight286self.vji = self.vji + pd_j_all.T * bp_out1 * self.rate_weight287self.thre_bp3 = self.thre_bp3 - pd_k_all * self.rate_thre288self.thre_bp2 = self.thre_bp2 - pd_j_all * self.rate_thre289# calculate the sum error of all single image290errors = np.sum(abs(data_teach - bp_out3))291error_count += errors292# print(' ----Teach ',data_teach)293# print(' ----BP_output ',bp_out3)294rp = rp + 1295mse = error_count / patterns296all_mse.append(mse)297
298def draw_error():299yplot = [error_accuracy for i in range(int(n_repeat * 1.2))]300plt.plot(all_mse, "+-")301plt.plot(yplot, "r--")302plt.xlabel("Learning Times")303plt.ylabel("All_mse")304plt.grid(True, alpha=0.5)305plt.show()306
307print("------------------Training Complished---------------------")308print((" - - Training epoch: ", rp, f" - - Mse: {mse:.6f}"))309if draw_e:310draw_error()311return mse312
313def predict(self, datas_test):314# model predict315produce_out = []316print("-------------------Start Testing-------------------------")317print((" - - Shape: Test_Data ", np.shape(datas_test)))318for p in range(len(datas_test)):319data_test = np.asmatrix(datas_test[p])320data_focus1, data_conved1 = self.convolute(321data_test,322self.conv1,323self.w_conv1,324self.thre_conv1,325conv_step=self.step_conv1,326)327data_pooled1 = self.pooling(data_conved1, self.size_pooling1)328data_bp_input = self._expand(data_pooled1)329
330bp_out1 = data_bp_input331bp_net_j = bp_out1 * self.vji.T - self.thre_bp2332bp_out2 = self.sig(bp_net_j)333bp_net_k = bp_out2 * self.wkj.T - self.thre_bp3334bp_out3 = self.sig(bp_net_k)335produce_out.extend(bp_out3.getA().tolist())336res = [list(map(self.do_round, each)) for each in produce_out]337return np.asarray(res)338
339def convolution(self, data):340# return the data of image after convoluting process so we can check it out341data_test = np.asmatrix(data)342data_focus1, data_conved1 = self.convolute(343data_test,344self.conv1,345self.w_conv1,346self.thre_conv1,347conv_step=self.step_conv1,348)349data_pooled1 = self.pooling(data_conved1, self.size_pooling1)350
351return data_conved1, data_pooled1352
353
354if __name__ == "__main__":355"""356I will put the example on other file
357"""
358