我有一些需要转换为Pytorch的keras代码。我是pytorch的新手,我无法像在keras中一样将头放在如何接受输入上。我在此上花费了许多时间,非常感谢您提供任何提示或帮助。
这是我正在处理的keras代码。输入形状为(5000,1)
def build(input_shape, classes):
model = Sequential()
filter_num = ['None',32,64,128,256]
kernel_size = ['None',8,8,8,8]
conv_stride_size = ['None',1,1,1,1]
pool_stride_size = ['None',4,4,4,4]
pool_size = ['None',8,8,8,8]
# Block1
model.add(Conv1D(filters=filter_num[1], kernel_size=kernel_size[1], input_shape=input_shape,
strides=conv_stride_size[1], padding='same',
name='block1_conv1'))
model.add(BatchNormalization(axis=-1))
model.add(ELU(alpha=1.0, name='block1_adv_act1'))
model.add(Conv1D(filters=filter_num[1], kernel_size=kernel_size[1],
strides=conv_stride_size[1], padding='same',
name='block1_conv2'))
model.add(BatchNormalization(axis=-1))
model.add(ELU(alpha=1.0, name='block1_adv_act2'))
model.add(MaxPooling1D(pool_size=pool_size[1], strides=pool_stride_size[1],
padding='same', name='block1_pool'))
model.add(Dropout(0.1, name='block1_dropout'))
# Block 2
model.add(Conv1D(filters=filter_num[2], kernel_size=kernel_size[2],
strides=conv_stride_size[2], padding='same',
name='block2_conv1'))
model.add(BatchNormalization())
model.add(Activation('relu', name='block2_act1'))
model.add(Conv1D(filters=filter_num[2], kernel_size=kernel_size[2],
strides=conv_stride_size[2], padding='same',
name='block2_conv2'))
model.add(BatchNormalization())
model.add(Activation('relu', name='block2_act2'))
model.add(MaxPooling1D(pool_size=pool_size[2], strides=pool_stride_size[3],
padding='same', name='block2_pool'))
model.add(Dropout(0.1, name='block2_dropout'))
# Block 3
model.add(Conv1D(filters=filter_num[3], kernel_size=kernel_size[3],
strides=conv_stride_size[3], padding='same',
name='block3_conv1'))
model.add(BatchNormalization())
model.add(Activation('relu', name='block3_act1'))
model.add(Conv1D(filters=filter_num[3], kernel_size=kernel_size[3],
strides=conv_stride_size[3], padding='same',
name='block3_conv2'))
model.add(BatchNormalization())
model.add(Activation('relu', name='block3_act2'))
model.add(MaxPooling1D(pool_size=pool_size[3], strides=pool_stride_size[3],
padding='same', name='block3_pool'))
model.add(Dropout(0.1, name='block3_dropout'))
# Block 4
model.add(Conv1D(filters=filter_num[4], kernel_size=kernel_size[4],
strides=conv_stride_size[4], padding='same',
name='block4_conv1'))
model.add(BatchNormalization())
model.add(Activation('relu', name='block4_act1'))
model.add(Conv1D(filters=filter_num[4], kernel_size=kernel_size[4],
strides=conv_stride_size[4], padding='same',
name='block4_conv2'))
model.add(BatchNormalization())
model.add(Activation('relu', name='block4_act2'))
model.add(MaxPooling1D(pool_size=pool_size[4], strides=pool_stride_size[4],
padding='same', name='block4_pool'))
model.add(Dropout(0.1, name='block4_dropout'))
# FC #1
model.add(Flatten(name='flatten'))
model.add(Dense(512, kernel_initializer=glorot_uniform(seed=0), name='fc1'))
model.add(BatchNormalization())
model.add(Activation('relu', name='fc1_act'))
model.add(Dropout(0.7, name='fc1_dropout'))
#FC #2
model.add(Dense(512, kernel_initializer=glorot_uniform(seed=0), name='fc2'))
model.add(BatchNormalization())
model.add(Activation('relu', name='fc2_act'))
model.add(Dropout(0.5, name='fc2_dropout'))
# Classification
model.add(Dense(classes, kernel_initializer=glorot_uniform(seed=0), name='fc3'))
model.add(Activation('softmax', name="softmax"))
return model
这是来自keras代码的model.summary()的结果
Layer (type) Output Shape Param #
=================================================================
block1_conv1 (Conv1D) (None, 5000, 32) 288
_________________________________________________________________
batch_normalization_1 (Batch (None, 5000, 32) 128
_________________________________________________________________
block1_adv_act1 (ELU) (None, 5000, 32) 0
_________________________________________________________________
block1_conv2 (Conv1D) (None, 5000, 32) 8224
_________________________________________________________________
batch_normalization_2 (Batch (None, 5000, 32) 128
_________________________________________________________________
block1_adv_act2 (ELU) (None, 5000, 32) 0
_________________________________________________________________
block1_pool (MaxPooling1D) (None, 1250, 32) 0
_________________________________________________________________
block1_dropout (Dropout) (None, 1250, 32) 0
_________________________________________________________________
block2_conv1 (Conv1D) (None, 1250, 64) 16448
_________________________________________________________________
batch_normalization_3 (Batch (None, 1250, 64) 256
_________________________________________________________________
block2_act1 (Activation) (None, 1250, 64) 0
_________________________________________________________________
block2_conv2 (Conv1D) (None, 1250, 64) 32832
_________________________________________________________________
batch_normalization_4 (Batch (None, 1250, 64) 256
_________________________________________________________________
block2_act2 (Activation) (None, 1250, 64) 0
_________________________________________________________________
block2_pool (MaxPooling1D) (None, 313, 64) 0
_________________________________________________________________
block2_dropout (Dropout) (None, 313, 64) 0
_________________________________________________________________
block3_conv1 (Conv1D) (None, 313, 128) 65664
_________________________________________________________________
batch_normalization_5 (Batch (None, 313, 128) 512
_________________________________________________________________
block3_act1 (Activation) (None, 313, 128) 0
_________________________________________________________________
block3_conv2 (Conv1D) (None, 313, 128) 131200
_________________________________________________________________
batch_normalization_6 (Batch (None, 313, 128) 512
_________________________________________________________________
block3_act2 (Activation) (None, 313, 128) 0
_________________________________________________________________
block3_pool (MaxPooling1D) (None, 79, 128) 0
_________________________________________________________________
block3_dropout (Dropout) (None, 79, 128) 0
_________________________________________________________________
block4_conv1 (Conv1D) (None, 79, 256) 262400
_________________________________________________________________
batch_normalization_7 (Batch (None, 79, 256) 1024
_________________________________________________________________
block4_act1 (Activation) (None, 79, 256) 0
_________________________________________________________________
block4_conv2 (Conv1D) (None, 79, 256) 524544
_________________________________________________________________
batch_normalization_8 (Batch (None, 79, 256) 1024
_________________________________________________________________
block4_act2 (Activation) (None, 79, 256) 0
_________________________________________________________________
block4_pool (MaxPooling1D) (None, 20, 256) 0
_________________________________________________________________
block4_dropout (Dropout) (None, 20, 256) 0
_________________________________________________________________
flatten (Flatten) (None, 5120) 0
_________________________________________________________________
fc1 (Dense) (None, 512) 2621952
_________________________________________________________________
batch_normalization_9 (Batch (None, 512) 2048
_________________________________________________________________
fc1_act (Activation) (None, 512) 0
_________________________________________________________________
fc1_dropout (Dropout) (None, 512) 0
_________________________________________________________________
fc2 (Dense) (None, 512) 262656
_________________________________________________________________
batch_normalization_10 (Batc (None, 512) 2048
_________________________________________________________________
fc2_act (Activation) (None, 512) 0
_________________________________________________________________
fc2_dropout (Dropout) (None, 512) 0
_________________________________________________________________
fc3 (Dense) (None, 101) 51813
_________________________________________________________________
softmax (Activation) (None, 101) 0
=================================================================
Total params: 3,985,957
Trainable params: 3,981,989
Non-trainable params: 3,968
这是我用火炬制成的东西
class model(torch.nn.Module):
def __init__(self, input_channels, kernel_size, stride, pool_kernel, pool_stride, dropout_p, dropout_inplace=False):
super(model, self).__init__()
self.encoder = nn.Sequential(
BasicBlock1(input_channels, kernel_size, stride, pool_kernel, pool_stride, dropout_p),
BasicBlock(input_channels//4, kernel_size, stride, pool_kernel, pool_stride, dropout_p),
BasicBlock(input_channels//16, kernel_size, stride, pool_kernel, pool_stride, dropout_p),
BasicBlock(input_channels//16//4, kernel_size, stride, pool_kernel, pool_stride, dropout_p)
)
self.decoder = nn.Sequential(
nn.Linear(5120, 512),
nn.BatchNorm1d(512),
nn.ReLU(),
nn.Dropout(p=dropout_p, inplace=dropout_inplace),
nn.Linear(512, 512),
nn.BatchNorm1d(512),
nn.ReLU(),
nn.Dropout(p=dropout_p, inplace=dropout_inplace),
nn.Linear(512, 101),
nn.Softmax(dim=101)
)
def forward(self, x):
x = self.encoder(x)
x = x.view(x.size(0), -1) # flatten
x = self.decoder(x)
return x
def BasicBlock(input_channels, kernel_size, stride, pool_kernel, pool_stride, dropout_p, dropout_inplace=False):
return nn.Sequential(
nn.Conv1d(in_channels=input_channels, out_channels=input_channels, kernel_size=kernel_size, stride=stride,
padding=get_pad_size(input_channels, input_channels, kernel_size)),
nn.BatchNorm1d(32),
nn.ReLU(),
nn.Conv1d(in_channels=input_channels, out_channels=input_channels, kernel_size=kernel_size, stride=stride,
padding=get_pad_size(input_channels, input_channels, kernel_size)),
nn.BatchNorm1d(32),
nn.ReLU(),
nn.MaxPool1d(kernel_size=pool_kernel, stride=pool_stride,
padding=get_pad_size(input_channels, input_channels/4, kernel_size)),
nn.Dropout(p=dropout_p, inplace=dropout_inplace)
)
def BasicBlock1(input_channels, kernel_size, stride, pool_kernel, pool_stride, dropout_p, dropout_inplace=False):
return nn.Sequential(
nn.Conv1d(in_channels=1, out_channels=input_channels, kernel_size=kernel_size, stride=stride,
padding=get_pad_size(input_channels, input_channels, kernel_size)),
nn.BatchNorm1d(32),
nn.ReLU(),
nn.Conv1d(in_channels=input_channels, out_channels=input_channels, kernel_size=kernel_size, stride=stride,
padding=get_pad_size(input_channels, input_channels, kernel_size)),
nn.BatchNorm1d(32),
nn.ReLU(),
nn.MaxPool1d(kernel_size=pool_kernel, stride=pool_stride,
padding=get_pad_size(input_channels, input_channels/4, kernel_size)),
nn.Dropout(p=dropout_p, inplace=dropout_inplace)
)
def get_pad_size(input_shape, output_shape, kernel_size, stride=1, dilation=1):
"""
Gets the right padded needed to maintain same shape in the conv layers
BEWARE: works only on odd size kernel size
:param input_shape: the input shape to the conv layer
:param output_shape: the desired output shape of the conv layer
:param kernel_size: the size of the kernel window, has to be odd
:param stride: Stride of the convolution
:param dilation: Spacing between kernel elements
:return: the appropriate pad size for the needed configuration
:Author: Aneesh
"""
if kernel_size % 2 == 0:
raise ValueError(
"Kernel size has to be odd for this function to work properly. Current Value is %d." % kernel_size)
return (int((output_shape * stride - stride + kernel_size - input_shape + (kernel_size - 1) * (dilation - 1)) / 2))
最后这是我的pytorch模型创建的模型摘要
model(
(encoder): Sequential(
(0): Sequential(
(0): Conv1d(1, 5000, kernel_size=(7,), stride=(1,), padding=(3,))
(1): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
(3): Conv1d(5000, 5000, kernel_size=(7,), stride=(1,), padding=(3,))
(4): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(5): ReLU()
(6): MaxPool1d(kernel_size=8, stride=4, padding=-1872, dilation=1, ceil_mode=False)
(7): Dropout(p=0.1)
)
(1): Sequential(
(0): Conv1d(1250, 1250, kernel_size=(7,), stride=(1,), padding=(3,))
(1): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
(3): Conv1d(1250, 1250, kernel_size=(7,), stride=(1,), padding=(3,))
(4): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(5): ReLU()
(6): MaxPool1d(kernel_size=8, stride=4, padding=-465, dilation=1, ceil_mode=False)
(7): Dropout(p=0.1)
)
(2): Sequential(
(0): Conv1d(312, 312, kernel_size=(7,), stride=(1,), padding=(3,))
(1): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
(3): Conv1d(312, 312, kernel_size=(7,), stride=(1,), padding=(3,))
(4): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(5): ReLU()
(6): MaxPool1d(kernel_size=8, stride=4, padding=-114, dilation=1, ceil_mode=False)
(7): Dropout(p=0.1)
)
(3): Sequential(
(0): Conv1d(78, 78, kernel_size=(7,), stride=(1,), padding=(3,))
(1): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
(3): Conv1d(78, 78, kernel_size=(7,), stride=(1,), padding=(3,))
(4): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(5): ReLU()
(6): MaxPool1d(kernel_size=8, stride=4, padding=-26, dilation=1, ceil_mode=False)
(7): Dropout(p=0.1)
)
)
(decoder): Sequential(
(0): Linear(in_features=5120, out_features=512, bias=True)
(1): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
(3): Dropout(p=0.1)
(4): Linear(in_features=512, out_features=512, bias=True)
(5): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(6): ReLU()
(7): Dropout(p=0.1)
(8): Linear(in_features=512, out_features=101, bias=True)
(9): Softmax()
)
)
答案 0 :(得分:0)
我认为您的根本问题是将in_channels
和out_channels
与Keras形状混淆。让我们以第一个卷积层为例。在Keras中,您可以:
Conv1D(filters=32, kernel_size=8, input_shape=(5000,1), strides=1, padding='same')
等效的PyTorch应该是(像您一样将内核大小更改为7,我们稍后会再讨论):
nn.Conv1d(in_channels=1, out_channels=32, kernel_size=7, stride=1, padding=3) # different kernel size
请注意,您无需给出pytorch输入序列的形状。现在,让我们看看它与您所做的比较:
nn.Conv1d(in_channels=1, out_channels=5000, kernel_size=7, stride=1, padding=0) # note padding
您刚刚创建了一个庞大的网络。正确的实现会产生[b, 32, 5000]
的输出,其中b是批处理大小,而您的输出是[b, 5000, 5000]
。
希望此示例可帮助您纠正其余的实现。
最后,关于在pytorch中复制same
填充的一些说明。即使内核大小相同,要保留输入的大小,也需要非对称填充。我认为创建图层时可能不可用。我看到您改为将内核大小更改为7,但是实际上可以使用原始内核大小8来完成。您可以在forward()
函数中使用padding创建所需的非对称填充。
layer = nn.Conv1d(in_channels=1, out_channels=32, kernel_size=8, stride=1, padding=0) # layer without padding
x = torch.empty(1, 1, 5000).normal_() # random input
# forward run
x_padded = torch.nn.functional.pad(x, (3,4))
y = layer(x_padded).shape
print(y.shape) # torch.Size([1, 32, 5000])