How to correctly set input image size for LPRNet model? 'RuntimeError: Sizes of tensors must match except in dimension 1..'
Trying to adapt the LPRNet model for my own dataset. The original model was set for Chinese license plate images with dimensions 24x94 pixels. My dataset consists of plates with only numbers, images come with dimensions 64x128. I got an error when I try to replace 'summary(lprnet, (3,24,94), device=&quot;cpu&quot;)' to 'summary(lprnet, (3,64,128), device=&quot;cpu&quot;)'.
The first code is working well, the second gets 'RuntimeError: Sizes of tensors must match except in dimension 1. Got 25 and 24 in dimension 3 (The offending index is 1)', this is the last line of code.
I don't see where else in the code I should change parameters. Will be thankful for any clue!
Original: https://github.com/xuexingyu24/License_Plate_Detection_Pytorch/blob/master/LPRNet/model/LPRNET.py
# LPRNET model
import torch
import torch.nn as nn
from torchsummary import summary

class small_basic_block(nn.Module):
    def __init__(self, ch_in, ch_out):
        super(small_basic_block, self).__init__()
        self.block = nn.Sequential(
            nn.Conv2d(ch_in, ch_out // 4, kernel_size=1),
            nn.ReLU(),
            nn.Conv2d(ch_out // 4, ch_out // 4, kernel_size=(3, 1), padding=(1, 0)),
            nn.ReLU(),
            nn.Conv2d(ch_out // 4, ch_out // 4, kernel_size=(1, 3), padding=(0, 1)),
            nn.ReLU(),
            nn.Conv2d(ch_out // 4, ch_out, kernel_size=1),
        )
    def forward(self, x):
        return self.block(x)

class LPRNet(nn.Module):
    def __init__(self, class_num, dropout_rate):
        super(LPRNet, self).__init__()
        self.class_num = class_num
        self.backbone = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1), # 0
            nn.BatchNorm2d(num_features=64),
            nn.ReLU(),  # 2
            nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(1, 1, 1)),
            small_basic_block(ch_in=64, ch_out=128),    # *** 4 ***
            nn.BatchNorm2d(num_features=128),
            nn.ReLU(),  # 6
            nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(2, 1, 2)),
            small_basic_block(ch_in=64, ch_out=256),   # 8
            nn.BatchNorm2d(num_features=256),
            nn.ReLU(),  # 10
            small_basic_block(ch_in=256, ch_out=256),   # *** 11 ***
            nn.BatchNorm2d(num_features=256),   # 12
            nn.ReLU(),
            nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(4, 1, 2)),  # 14
            nn.Dropout(dropout_rate),
            nn.Conv2d(in_channels=64, out_channels=256, kernel_size=(1, 4), stride=1),  # 16
            nn.BatchNorm2d(num_features=256),
            nn.ReLU(),  # 18
            nn.Dropout(dropout_rate),
            nn.Conv2d(in_channels=256, out_channels=class_num, kernel_size=(13, 1), stride=1), # 20
            nn.BatchNorm2d(num_features=class_num),
            nn.ReLU(),  # *** 22 ***
        )
        self.container = nn.Sequential(
            nn.Conv2d(in_channels=256+class_num+128+64, out_channels=self.class_num, kernel_size=(1,1), stride=(1,1)),
            # nn.BatchNorm2d(num_features=self.class_num),
            # nn.ReLU(),
            # nn.Conv2d(in_channels=self.class_num, out_channels=self.lpr_max_len+1, kernel_size=3, stride=2),
            # nn.ReLU(),
        )

    def forward(self, x):
        keep_features = list()
        for i, layer in enumerate(self.backbone.children()):
            x = layer(x)
            if i in [2, 6, 13, 22]: # [2, 4, 8, 11, 22]
                keep_features.append(x)

        global_context = list()
        for i, f in enumerate(keep_features):
            if i in [0, 1]:
                f = nn.AvgPool2d(kernel_size=5, stride=5)(f)
            if i in [2]:
                f = nn.AvgPool2d(kernel_size=(4, 10), stride=(4, 2))(f)
            f_pow = torch.pow(f, 2)
            f_mean = torch.mean(f_pow)
            f = torch.div(f, f_mean)
            global_context.append(f)

        x = torch.cat(global_context, 1)
        x = self.container(x)
        logits = torch.mean(x, dim=2)

        return logits
    
CHARS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
    
if __name__ == &quot;__main__&quot;:
     
    lprnet = LPRNet(class_num=len(CHARS), dropout_rate=0)
    print(lprnet)
    
    summary(lprnet, (3,24,94), device=&quot;cpu&quot;)
    #summary(lprnet, (3,64,128), device=&quot;cpu&quot;)


The problem with your code is that the shapes of four tensors in global_context are different for (64, 128) input size. For shape (24, 94), in LRPNet, the authors make all the tensors of (4, 18) sized with average pooling which doesn't apply to your image size. To make them same-sized, you need to change the configurations of nn.AvgPool2d while enumerating keep_features. You may update them in various ways. I updated the avgpool with the below configurations and it worked:
            if i in [0, 1]:
                f = nn.AvgPool2d(kernel_size=(11, 24), stride=(7, 4))(f)

            elif i == 2:
                f = nn.AvgPool2d(kernel_size=(9, 11), stride=(7, 2))(f)
            elif i == 3:
                f = nn.AvgPool2d(kernel_size=(7, 2), stride=(5, 1))(f)
            f_pow = torch.pow(f, 2)
            f_mean = torch.mean(f_pow)
            f = torch.div(f, f_mean)
            global_context.append(f)```

