Convert keras model architecture to Pytorch
I am trying to convert a keras model to pytorch for human activity recognition. The keras model could achieve up to 98% accuracy, while Pytorch model could achieve only ~60% accuracy. I couldn’t figure out the problem, first I was thinking of the padding=‘same’ of keras, but I have already adjusted the padding of pytorch already. Can you check what is wrong?
The keras code is as above
model = keras.Sequential()
model.add(layers.Input(shape=[100,12]))
model.add(layers.Conv1D(filters=32, kernel_size=3, padding=&quot;same&quot;))
model.add(layers.BatchNormalization())
model.add(layers.ReLU())
model.add(layers.Conv1D(filters=64, kernel_size=3, padding=&quot;same&quot;))
model.add(layers.BatchNormalization())
model.add(layers.ReLU())
model.add(layers.MaxPool1D(2))
model.add(layers.LSTM(64))
model.add(layers.Dense(units=128, activation='relu'))
model.add(layers.Dense(13, activation='softmax'))
model.summary()

and my pytorch model code is as below
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        seq_len = 100
        # output: [, 32, 100]
        self.conv1 = nn.Conv1d(seq_len, 32, kernel_size=3, stride=1, padding=1)
        self.bn1 = nn.BatchNorm1d(32)
        # output: [, 64, 100]
        self.conv2 = nn.Conv1d(32, 64, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm1d(64)
        # output: [, 64, 50]
        self.mp = nn.MaxPool1d(kernel_size=2, stride=2)
        # output: [, 64]
        self.lstm = nn.LSTM(6, 64, 1)
        # output: [, 128]
        self.fc1 = nn.Linear(64, 128)
        # output: [, 13]
        self.fc2 = nn.Linear(128, 13)
        
    def forward(self, x):
        x = self.conv1(x) 
        x = self.bn1(x)
        x = F.relu(x)

        x = self.conv2(x)
        x = self.bn2(x)
        x = F.relu(x)
        x = self.mp(x)
        
        out, _ = self.lstm(x)
        x = out[:, -1, :]
        
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        
        return x


Since it was too lengthy to write in the comments,I am writing it in the answer, After testing your PyTorch architecture for shape with random tensor of size which you have mentioned: torch.randn(1, 100, 12)(NCH format).
This is the outcome:
input= torch.Size([1, 100, 12])
1st Conv= torch.Size([1, 32, 12])
1st batchNorm= torch.Size([1, 32, 12])
1st relu= torch.Size([1, 32, 12])
2nd Conv= torch.Size([1, 64, 12])
2nd batchnorm= torch.Size([1, 64, 12])
2nd relu= torch.Size([1, 64, 12])
1st maxPool= torch.Size([1, 64, 6])
LSTM= torch.Size([1, 64])
1st FC= torch.Size([1, 128])
3rd relu= torch.Size([1, 128])
2nd FC= torch.Size([1, 13])

It is the 100 channels your network is receiving, and as you mentioned in comments after 1st convolution in Keras it's [batch_size, 100, 32]  but in torch it is changing to [batch_size,32,12]
Change to this:
def __init__(self):
        super(CNN, self).__init__()
        in_channels = 12
        # output: [, 32, 100]
        self.conv1 = nn.Conv1d(in_channels, 32, kernel_size=3, stride=1, padding=1)
        self.bn1 = nn.BatchNorm1d(32)
        # output: [, 64, 100]
        self.conv2 = nn.Conv1d(32, 64, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm1d(64)
        # output: [, 64, 50]
        self.mp = nn.MaxPool1d(kernel_size=2, stride=2)
        # output: [, 64]
        self.lstm = nn.LSTM(50, 64, 1)
        # output: [, 128]
        self.fc1 = nn.Linear(64, 128)
        # output: [, 13]
        self.fc2 = nn.Linear(128, 13)
        self.softmax = nn.Softmax()

The output for this will be:
input= torch.Size([1, 12, 100])
1st Conv= torch.Size([1, 32, 100])
1st batchNorm= torch.Size([1, 32, 100])
1st relu= torch.Size([1, 32, 100])
2nd Conv= torch.Size([1, 64, 100])
2nd batchnorm= torch.Size([1, 64, 100])
2nd relu= torch.Size([1, 64, 100])
1st maxPool= torch.Size([1, 64, 50])
LSTM= torch.Size([1, 64])
1st FC= torch.Size([1, 128])
3rd relu= torch.Size([1, 128])
2nd FC= torch.Size([1, 13])

