Conv2d的正向传播与反向传播

从Conv2D的正向传播说起

为了快速计算conv2d,需要将conv2d整理成两个矩阵相乘的形式,例如WX,或者其转置形式。这里以XW为例,X的每一列表示一张feature map的所有方格,也就是将一个feature map的某一个3X3或者5X5区域先展平(flatten)成行向量,再将所有的小区域的行向量纵向拼接起来组成一个大的矩阵,矩阵的维度是((map_s-filter_size+pad)/ filter_size + 1)**2X(filter_size**2)。再将所有feature map得到的列横向组合成一个大矩阵。对于权值矩阵,对应的方法处理,然后进行一次转置即可。当然,由于(AB)的转置等于B的转置乘以A的转置,上述img2col方式不是唯一的。完成img2col后,只需要进行一次矩阵相乘运算即可,矩阵相乘运算可以调用各种BLAS库在CPU或GPU上高速进行。当然,还要额外考虑的一个问题是,神经网络一般使用mini-batch进行训练,所以希望一次性把batch内的所有计算完成。可以这样思考:将batch内的多个样本看作同一个样本,也就是把输入样本全部concatenate在一起,然后就可以套用上面的过程了。再计算完成后再将不同batch的数据分开就可以了。根据上面的分析,WX的输出应该是这样的:每一列都是一个滤波器的全部输出,再回复成二维的形状即可。batch内不同样本的输出是纵向拼接在一起的,因此平均分割开即可。

代码组建思路:总的思路就是遍历,给转换后的矩阵的每一个位置赋值。有两种方式,第一种是对转换后的矩阵遍历,第一个维度是row,第二个维度是col,根据row和col的取值(当然也

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,我们需要定义一个卷积层的类,其中包含正向传播反向传播的函数。 ```python import numpy as np import theano import theano.tensor as T class ConvLayer(object): def __init__(self, rng, input_shape, filter_shape): self.input_shape = input_shape self.filter_shape = filter_shape fan_in = np.prod(filter_shape[1:]) fan_out = (filter_shape[0] * np.prod(filter_shape[2:])) W_bound = np.sqrt(6. / (fan_in + fan_out)) self.W = theano.shared( np.asarray( rng.uniform(low=-W_bound, high=W_bound, size=filter_shape), dtype=theano.config.floatX ), borrow=True ) self.b = theano.shared( np.zeros((filter_shape[0],), dtype=theano.config.floatX), borrow=True ) self.params = [self.W, self.b] def convolve(self, input): conv_out = T.nnet.conv2d( input=input, filters=self.W, filter_shape=self.filter_shape, input_shape=self.input_shape ) return T.nnet.sigmoid(conv_out + self.b.dimshuffle('x', 0, 'x', 'x')) def get_cost_updates(self, cost, learning_rate): grads = T.grad(cost, self.params) updates = [(param, param - learning_rate * grad) for param, grad in zip(self.params, grads)] return updates ``` 接下来,我们定义一个多层感知机的类,包含训练函数和预测函数。 ```python class MLP(object): def __init__(self, rng, input_shape, filter_shapes, hidden_sizes, output_size): self.x = T.tensor4('x') self.y = T.matrix('y') self.layers = [] self.params = [] layer_input = self.x input_shape = input_shape for i in range(len(filter_shapes)): filter_shape = filter_shapes[i] layer = ConvLayer(rng=rng, input_shape=input_shape, filter_shape=filter_shape) self.layers.append(layer) self.params += layer.params layer_output = layer.convolve(layer_input) layer_input = layer_output input_shape = (input_shape[0], filter_shape[0], input_shape[2] - filter_shape[2] + 1, input_shape[3] - filter_shape[3] + 1) flatten_layer_output = layer_output.flatten(2) hidden_layer_input = flatten_layer_output hidden_layer_size = input_shape[1] * input_shape[2] * input_shape[3] for hidden_size in hidden_sizes: W = theano.shared( np.asarray( rng.uniform(low=-np.sqrt(6. / (hidden_layer_size + hidden_size)), high=np.sqrt(6. / (hidden_layer_size + hidden_size)), size=(hidden_layer_size, hidden_size)), dtype=theano.config.floatX ), borrow=True ) b = theano.shared( np.zeros((hidden_size,), dtype=theano.config.floatX), borrow=True ) self.params += [W, b] hidden_layer_output = T.nnet.sigmoid(T.dot(hidden_layer_input, W) + b) hidden_layer_input = hidden_layer_output hidden_layer_size = hidden_size W = theano.shared( np.asarray( rng.uniform(low=-np.sqrt(6. / (hidden_layer_size + output_size)), high=np.sqrt(6. / (hidden_layer_size + output_size)), size=(hidden_layer_size, output_size)), dtype=theano.config.floatX ), borrow=True ) b = theano.shared( np.zeros((output_size,), dtype=theano.config.floatX), borrow=True ) self.params += [W, b] self.output = T.nnet.softmax(T.dot(hidden_layer_output, W) + b) self.prediction = T.argmax(self.output, axis=1) self.cost = -T.mean(T.log(self.output)[T.arange(self.y.shape[0]), self.y]) self.updates = self.layers[0].get_cost_updates(self.cost, learning_rate=0.1) for i in range(1, len(self.layers)): layer_updates = self.layers[i].get_cost_updates(self.cost, learning_rate=0.1) self.updates += layer_updates self.train = theano.function(inputs=[self.x, self.y], outputs=self.cost, updates=self.updates, allow_input_downcast=True) self.predict = theano.function(inputs=[self.x], outputs=self.prediction, allow_input_downcast=True) ``` 最后,我们可以使用以下代码来训练和测试模型。 ```python rng = np.random.RandomState(1234) train_x = np.random.rand(100, 1, 28, 28).astype(theano.config.floatX) train_y = np.random.randint(0, 10, size=(100,)).astype(np.int32) mlp = MLP(rng=rng, input_shape=(100, 1, 28, 28), filter_shapes=[(20, 1, 5, 5), (50, 20, 5, 5)], hidden_sizes=[500], output_size=10) for i in range(10): cost = mlp.train(train_x, train_y) print('Epoch %d, cost %f' % (i, cost)) test_x = np.random.rand(10, 1, 28, 28).astype(theano.config.floatX) test_y = np.random.randint(0, 10, size=(10,)).astype(np.int32) pred_y = mlp.predict(test_x) accuracy = np.mean(pred_y == test_y) print('Accuracy %f' % accuracy) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值