pytorchinferencebatchnorm

Pytorch model with multi batchnorm1d layers get errors during inference - "expected 2D or 3D input (got 1D input)"


My model in pytorch with batchnorm1D is like this:

class Discriminator(nn.Module):
def __init__(self, sequenceLength):
    super(Discriminator,self).__init__()
    self.batchnorm1 = nn.BatchNorm1d(sequenceLength)
    self.batchnorm2 = nn.BatchNorm1d(2*sequenceLength)
    self.linear1 = nn.Linear(sequenceLength, 2*sequenceLength)
    self.conv2 = nn.Conv1d(1, 1,kernel_size=3, stride=1, padding=1)
    self.conv3 = nn.Conv1d(1, 1,kernel_size=3, stride=1, padding=1)
    self.linear4 = nn.Linear(2*sequenceLength, 1)
    self.relu = nn.ReLU(0.01)
    self.sigmoid = nn.Sigmoid()

def forward(self, x):
    out = self.batchnorm1(x)
    out = self.linear1(out)
    out = self.relu(out)
    out = self.batchnorm2(out)
    out = out.unsqueeze(1)
    out = self.conv2(out)
    out = self.sigmoid(out)
    out = self.conv3(out)
    out = self.relu(out)
    out = out.squeeze()
    out = self.batchnorm2(out)
    out = self.linear4(out)
    out = self.sigmoid(out)
    return out

My inference code is like this:

Discriminator = torch.load('disc.pth', map_location=torch.device('cpu'))
Discriminator.eval()
embededSeq = Embedding.EmbedOne('sample data')
embededSeq = torch.tensor(embededSeq).float()
embededSeq = embededSeq.unsqueeze(0)
score = PosDiscriminator(embededSeq).detach().numpy()[0]

And I got the error message: "expected 2D or 3D input (got 1D input)" at the out = self.batchnorm2(out) line in the model. I wonder if is it caused by my previous line out = out.squeeze() or not? However, the training code worked fine, only happen during the inference.

Could you please have a look and show me what's wrong?

Thank you in advance,


Solution

  • Yes, this issue is caused by out.squeeze. In general you should avoid out.squeeze() without any dimension arguments because this removes all dimensions with a size of 1, resulting in a tensor with an indeterminate number of dimensions. Within a model the number of dimensions expected by each layer is pretty much always fixed so this is likely to cause problems.

    Let your input be of shape [batch_size,length]. (As a side note some of these layers (e.g. conv1D) expect a channel dimension and all of these layers are compatible with a channel dimension, so you may want to add a channel dimension before input to the model rather than altering the number of dimensions within the model.). Here I use length as an arbitrary, changing length, not a fixed value.

    FIX:

    You can fix this by specifying the dimension to squeeze: out = out.squeeze(1), which will always result in a tensor of shape [batch_size,length].