1 # -*- coding: utf-8 -*- 2 """ 3 Created on Sun Mar 4 09:21:41 2018 4 5 @author: markli 6 """ 7 import numpy as np; 8 9 def ReLU(x): 10 return max(0,x); 11 12 def logistic(x): 13 return 1/(1 + np.exp(-x)); 14 15 def logistic_derivative(x): 16 return logistic(x)*(1-logistic(x)); 17 18 class ConvolutionLayer: 19 """ 20 卷積神經網絡中的卷積層 21 """ 22 def __init__(self,shape,padding,filters,stride): 23 """ 24 shape 卷積層形狀,元組 (行,列,通道數) 25 padding 填充零個數的大小 26 filters 過濾器的形狀,元組 (行,列,通道數,個數) 27 stride 步長 28 """ 29 self.shape = shape; 30 self.padding = padding; 31 self.stride = stride; 32 self.fileters = filters[:3]; 33 self.fileternum = filters[3]; 34 self.weights = []; 35 for i in range(filters[3]): 36 self.weights.append(np.random.randn(shape[2],filters[0],filters[1])); 37 self.baises = list(np.random.randn(filters[3])); 38 39 self.convlutionsize = (int((shape[0] + 2*padding - filters[0])/stride + 1),int((shape[1] + 2*padding - filters[1])/stride + 1)); 40 self.conv = np.ones((filters[3],self.convlutionsize[0],self.convlutionsize[1])); 41 42 def Convolute(self,Data): 43 """ 44 Data 三維數組,若只有兩維則通道數設為1. 45 """ 46 if(self.padding != 0): 47 for c in range(self.shape[2]): 48 ones = np.zeros((self.shape[0]+2*self.padding,self.shape[1]+2*self.padding)); 49 ones[self.padding:self.padding+self.shape[0],self.padding:self.padding+self.shape[1]] = Data[c]; 50 Data[c] = ones; 51 c,m,n = Data.shape; 52 53 54 #遍歷每一個過濾器 55 for f in range(self.fileternum): 56 t_conv = self.conv[f]; #取出第f個過濾器卷積后的臨時容器 57 w = self.weights[f]; #取出第f個過濾器的權值集合 58 b = self.baises[f]; #取出第f個過濾器的偏倚 59 #卷積運算,所有通道一起遍歷 60 row = 0; 61 for i in range(self.convlutionsize[0]): 62 col = 0; 63 for j in range(self.convlutionsize[1]): 64 data = Data[:,row:row+self.fileters[0],col:col+self.fileters[1]]; #取出卷積運算的數據立方體 65 s = 0; #存放卷積立方體的乘積的和 66 #對取出的臨時數據的每個通道進行卷積運算 67 for t_c in range(c): 68 t_w = w[t_c]; 69 t_data = data[t_c]; 70 temp = sum(np.multiply(t_w,t_data)); 71 s = temp + s; 72 t_conv[i,j] = ReLU(s+b); 73 #向右移動過濾器 74 col = col + self.stride; 75 #向下移動過濾器 76 row = row + self.stride; 77 #更新卷積結果容器 78 self.conv[f] = t_conv; 79 80 class PoolLayer: 81 """池化層""" 82 def __init__(self,shape,poolsize,stride,classic="max"): 83 """ 84 shape 池化目標的形狀, 元組(行,列,通道數) 85 poolsize 池化矩陣的形狀,元組 (行,列) 86 stride 步長 一般情況下池化的步長等於池化大小 87 classic 池化方式 max,average 88 """ 89 self.shape = shape; 90 self.stride = stride; 91 self.poolsize = poolsize; 92 self.classic = classic; 93 #生成池化結果矩陣形狀 94 self.pool = np.ones((shape[2],(shape[0]-poolsize[0])/stride + 1,(shape[1]-poolsize[1])/stride + 1)); 95 #生成過度池化矩陣形狀 96 self.c_poolsize = ((shape[0]-poolsize[0])/stride + 1,(shape[1]-poolsize[1])/stride + 1); 97 98 def Pool(self,Data): 99 """ 100 Data 三維數組,若只有兩維則通道數設為1. 101 """ 102 c,m,n = Data.shape; 103 104 #在每個通道上進行池化操作 105 for k in range(c): 106 p_temp = Data[k]; 107 row = 0; 108 for i in range(self.c_poolsize[0]): 109 col = 0; 110 for j in range(self.c_poolsize[1]): 111 temp = p_temp[row:row+self.poolsize[0],col:col+self.poolsize[1]]; 112 if(self.classic == "average"): 113 self.pool[k][i][j] = np.sum(temp) / (self.poolsize[0] * self.poolsize[1]); 114 if(self.classic == "max"): 115 self.pool[k][i][j] = np.max(temp); 116 else: 117 print("the classic does not exist"); 118 119 col = col + self.stride; 120 121 row = row + self.stride; 122 123 class FullConnectLayer: 124 """全連接層""" 125 def __init__(self,n_in,n_out,action_fun=logistic,action_fun_der=logistic_derivative,flag): 126 """ 127 n_in 輸入層的單元數 128 n_out 輸出單元個數 及緊鄰下一層的單元數 129 action_fun 激活函數 130 action_fun_der 激活函數的導函數 131 flag 初始化權值和偏倚的標記 normal,larger,smaller 132 """ 133 self.action_fun = action_fun; 134 self.action_fun_der = action_fun_der; 135 self.n_in = n_in; 136 self.n_out = n_out; 137 init_weight_biase(flag); 138 139 def init_weight_biase(self,init_flag): 140 if(init_flag == "noraml"): 141 self.weight = np.random.randn(self.n_out,self.n_in);#weight 取值服從N(0,1) 分布 142 self.biase = np.random.randn(self.n_out,1); 143 elif(init_flag == "larger"): 144 self.weight = 2*np.random.randn(self.n_out,self.n_in)-1; #weight 取值范圍(-1,1) 145 self.biases = 2*np.random.randn(self.n_out,1)-1 ; #b 取值范圍(-1,1) 146 elif(init_flag == "smaller"): 147 self.weight = np.random.randn(self.n_out,self.n_in)/np.sqrt(self.n_out) ; #weight 取值服從N(0,1/x) 分布 148 self.biase = np.random.randn(self.n_out,1); 149 150 def Forward(self,inpt): 151 """全連接層的前饋傳播""" 152 self.inpt = np.dot(self.weight,inpt) + self.biase; 153 self.outpt = self.action_fun(self.inpt); 154 155 156 """Softmax Layer"""
后向傳播的實現還是沒有頭緒,三層之間如何銜接不知道該怎么設計。本人能力水平有限,歡迎交流。本人微信號 markli52024