1 @staticmethod 2 def calculate_output_size(input_size, 3 filter_size, zero_padding, stride): 4 return (input_size - filter_size + 5 2 * zero_padding) / stride + 1
2.构造一个激活函数
此处用的是RELU激活函数,因此我们在activators.py里定义,forward是前向计算,backforward是计算公式的导数:
1 class ReluActivator(object): 2 def forward(self, weighted_input): max(0, weighted_input) backward(self, output): 7 return 1 if output > 0 else 0
其他常见的激活函数我们也可以放到activators里,如sigmoid函数,我们可以做如下定义:
1 class SigmoidActivator(object): 2 def forward(self, weighted_input): 3 return 1.0 / (1.0 + np.exp(-weighted_input)) backward(self, output): 6 return output * (1 - output)
如果我们需要自动以其他的激活函数,都可以在activator.py定义一个类即可。
3.定义一个类,保存卷积层的参数和梯度
1 class Filter(object): (self, width, height, depth): self.weights = np.random.uniform(-1e-4, 1e-4, 5 (depth, height, width)) self.bias = 0 8 self.weights_grad = np.zeros( 9 self.weights.shape) 10 self.bias_grad = 0 (self): % ( 14 repr(self.weights), repr(self.bias)) get_weights(self): 17 return self.weights get_bias(self): 20 return self.bias update(self, learning_rate): 23 self.weights -= learning_rate * self.weights_grad 24 self.bias -= learning_rate * self.bias_grad
4.卷积层的前向传播
1).获取卷积区域
get_patch(input_array, i, j, filter_width, 3 filter_height, stride): 从输入数组中获取本次卷积的区域, 6 自动适配输入为2D和3D的情况 start_i = i * stride 9 start_j = j * stride 10 if input_array.ndim == 2: 11 input_array_conv = input_array[ 12 start_i : start_i + filter_height, 13 start_j : start_j + filter_width] ,input_array_conv 15 return input_array_conv input_array.ndim == 3: 18 input_array_conv = input_array[:, 19 start_i : start_i + filter_height, 20 start_j : start_j + filter_width] ,input_array_conv 22 return input_array_conv
2).进行卷积运算
1 def conv(input_array, 2 kernel_array, 3 output_array, 4 stride, bias): 计算卷积,自动适配输入为2D和3D的情况 channel_number = input_array.ndim 9 output_width = output_array.shape[1] 10 output_height = output_array.shape[0] 11 kernel_width = kernel_array.shape[-1] 12 kernel_height = kernel_array.shape[-2] 13 for i in range(output_height): 14 for j in range(output_width): 15 output_array[i][j] = ( 16 get_patch(input_array, i, j, kernel_width, 17 kernel_height, stride) * kernel_array 18 ).sum() + bias
3).增加zero_padding