自定义Lasagne逐元素乘积层遇维度不匹配问题求助
问题描述
我有一个形状为**(序列长度19 × 特征数21)的输入序列,输入神经网络后需要一个能对输入与权重执行逐元素乘法(而非点积)**的层,输出形状规则如下:
- 若单元数为1,输出形状保持(19×21)
- 若单元数为8,输出形状应为(8,19,21)(批量维度在前时为(None,8,19,21),对应扁平化后的(None,8,399))
我尝试基于Lasagne自定义层,但运行时出现维度不匹配错误,以下是详细代码与错误信息:
自定义层代码
class ElementwiseMulLayer(lasagne.layers.Layer): def __init__(self, incoming, num_units, W=lasagne.init.Normal(0.01),**kwargs): super(ElementwiseMulLayer, self).__init__(incoming, **kwargs) self.num_inputs = self.input_shape[1] self.num_units = num_units self.W = self.add_param(W, (self.num_inputs,num_units), name='W') def get_output_for(self, input, **kwargs): #return T.dot(input, self.W) result=input*self.W return result def get_output_shape_for(self, input_shape): return (input_shape[0], self.num_units,self.num_inputs)
神经网络结构代码
l_in_2 = lasagne.layers.InputLayer(shape=(None, 9*19*21)) l_reshape_l_in_2 = lasagne.layers.ReshapeLayer(l_in_2, (-1, 9,19,21)) l_reshape_l_in_2_EL = lasagne.layers.ExpressionLayer(l_reshape_l_in_2, lambda X: X[:,0,:,:], output_shape='auto') l_reshape_l_in_2_EL = lasagne.layers.ReshapeLayer(l_reshape_l_in_2_EL, (-1, 19*21)) l_out1 = ElementwiseMulLayer(l_reshape_l_in_2_EL, num_units=8, name='my_EW_layer') l_out1 = lasagne.layers.ReshapeLayer(l_out1, (-1, 8*399)) l_out = lasagne.layers.DenseLayer(l_out1, num_units = 19*21, W = lasagne.init.Normal(), nonlinearity = lasagne.nonlinearities.rectify)
网络结构摘要(批量大小64)
| Layer | Layer_name | output_shape | # parameters |
|---|---|---|---|
| 0 | InputLayer | (None, 3591) | 0 |
| 1 | ReshapeLayer | (None, 9, 19, 21) | 0 |
| 2 | ExpressionLayer | (None, 19, 21) | 0 |
| 3 | ReshapeLayer | (None, 399) | 0 |
| 4 | ElementwiseMulLayer | (None, 8, 399) | 3192 |
| 5 | ReshapeLayer | (None, 3192) | 3192 |
| 6 | DenseLayer | (None, 399) | 1277199 |
初始错误信息
ValueError: GpuElemwise. Input dimension mis-match. Input 1 (indices start at 0) has shape[0] == 399, but the output's size on that axis is 64. Apply node that caused the error: GpuElemwise{mul,no_inplace}(GpuReshape{2}.0, my_dot_layer.W) Toposort index: 23 Inputs types: [GpuArrayType<None>(float32, matrix), GpuArrayType<None>(float32, matrix)] Inputs shapes: [(64, 399), (399, 8)] Inputs strides: [(14364, 4), (32, 4)] Inputs values: ['not shown', 'not shown'] Outputs clients: [[GpuReshape{2}(GpuElemwise{mul,no_inplace}.0, TensorConstant{[ -1 3192]})]]
修改W形状后的错误
我尝试将W的形状改为(self.num_inputs,num_units, self.num_inputs),仍出现维度不匹配:
ValueError: GpuElemwise. Input dimension mis-match. Input 1 (indices start at 0) has shape[1] == 8, but the output's size on that axis is 64. Apply node that caused the error: GpuElemwise{mul,no_inplace}(InplaceGpuDimShuffle{x,0,1}.0, my_EW_layer.W) Toposort index: 26 Inputs types: [GpuArrayType<None>(float32, (True, False, False)), GpuArrayType<None>(float32, 3D)] Inputs shapes: [(1, 64, 399), (399, 8, 399)] Inputs strides: [(919296, 14364, 4), (12768, 1596, 4)] Inputs values: ['not shown', 'not shown'] Outputs clients: [[GpuReshape{2}(GpuElemwise{mul,no_inplace}.0, TensorConstant{[ -1 3192]})]]
解决方案
问题出在维度广播不匹配:输入是(batch_size, num_inputs)即(64,399),原W是(399,8),直接逐元素乘时无法对齐维度。需要调整W的形状并对输入做维度扩展,让广播机制正确工作:
修改自定义层的代码如下:
class ElementwiseMulLayer(lasagne.layers.Layer): def __init__(self, incoming, num_units, W=lasagne.init.Normal(0.01),**kwargs): super(ElementwiseMulLayer, self).__init__(incoming, **kwargs) self.num_inputs = self.input_shape[1] self.num_units = num_units # 调整W的形状为(num_units, num_inputs),对应每个单元一组输入维度的权重 self.W = self.add_param(W, (self.num_units, self.num_inputs), name='W') def get_output_for(self, input, **kwargs): # 把输入从(batch, num_inputs)扩展为(batch, 1, num_inputs) input_expanded = input.dimshuffle(0, 'x', 1) # W的形状是(num_units, num_inputs),广播后变为(1, num_units, num_inputs) # 相乘后得到(batch, num_units, num_inputs),符合预期输出形状 result = input_expanded * self.W return result def get_output_shape_for(self, input_shape): return (input_shape[0], self.num_units, self.num_inputs)
原理说明
输入扩展维度后形状变为(64,1,399),W的形状是(8,399),Lasagne的广播机制会自动将W扩展为(1,8,399),和输入逐元素相乘后得到(64,8,399)的输出,与定义的输出形状一致,后续Reshape操作也能正常执行。
内容的提问来源于stack exchange,提问作者HATEM EL-AZAB
相关产品推荐
相关产品推荐

