对神经网络使用model.eval()时,每次输入非常不同,结果都是相同的输出

2024-05-14 10:29:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我用pytorch实现了一个简单的网络

class network:

    def __init__(self):

        self.device = device
        #these are the 3 convolutional synapses; Same convolution;
        self.layer     = sequential(
                                conv2d(3, 3, (23), padding=11),
                                batch_norm_2d(3),
                                Swish(),
        
                                conv2d(3, 3, (11), padding=5),
                                batch_norm_2d(3),
                                Swish(),
        
                                conv2d(3, 3, (5), padding=2),
                                batch_norm_2d(3),
                                Swish(),

                                conv2d(3, 4, (3), padding=15, stride=2),
                                batch_norm_2d(4),
                                Swish(),
        
                                conv2d(4, 8, (3), padding=15, stride=2),
                                batch_norm_2d(8),
                                Swish(),
        
                                conv2d(8, 4, (1)),
                                batch_norm_2d(4),
                                Swish(),
        
                                conv2d(4, 8, (3), padding=15, stride=2),
                                batch_norm_2d(8),
                                Swish(),
                        
                                conv2d(8, 16, (3), padding=15, stride=2),
                                batch_norm_2d(16),
                                Swish(),
        
                                conv2d(16, 8, (1)),
                                batch_norm_2d(8),
                                Swish(),
        
                                conv2d(8, 16, (3), padding=15, stride=2),
                                batch_norm_2d(16),
                                Swish(),
                        
                                conv2d(16, 32, (3), padding=15, stride=2),
                                batch_norm_2d(32),
                                Swish(),
        
                                conv2d(32, 16, (1)),
                                batch_norm_2d(16),
                                Swish(),
        
                                conv2d(16, 32, (3), padding=15, stride=2),
                                batch_norm_2d(32),
                                Swish(),
                        
                                conv2d(32, 64, (3), padding=15, stride=2),
                                batch_norm_2d(64),
                                Swish(),
        
                                conv2d(64, 32, (1)),
                                batch_norm_2d(32),
                                Swish(),
        
                                conv2d(32, 64, (3), padding=15, stride=2),
                                batch_norm_2d(64),
                                Swish(),
                        
                                conv2d(64, 128, (3), padding=15, stride=2),
                                batch_norm_2d(128),
                                Swish(),
        
                                conv2d(128, 64, (1)),
                                batch_norm_2d(64),
                                Swish(),
        
                                conv2d(64, 128, (3), padding=15, stride=2),
                                batch_norm_2d(128),
                                Swish(),
                        
                                conv2d(128, 256, (3), padding=15, stride=2),
                                batch_norm_2d(256),
                                Swish(),
        
                                conv2d(256, 128, (1)),
                                batch_norm_2d(128),
                                Swish(),
                                
                                flatten(1, -1),
        
                                linear(128*29*29, 8*8*2*5),
                                batch_norm_1d(8*8*2*5),
                                Swish()
            )
    
    
        #loss and optimizer functions for ethirun
        self.Loss_1 = IoU_Loss() #the loss function for bounding box.
        self.Loss_2 = tor.nn.SmoothL1Loss(reduction='mean')
    
        #the optimizer
        self.Optimizer =     tor.optim.AdamW(self.parameters())#tor.optim.SGD(self.parameters(), lr=1e-2, momentum=0.9, weight_decay=1e-5, nesterov=True)
        self.Scheduler = tor.optim.lr_scheduler.StepLR(self.Optimizer, 288, gamma=0.5)
        self.sizes = tor.tensor(range(0, 5), dtype=tor.int64, device=self.device)

    def forward(self, input):
         return self.layer(input)

    def backprop(self, preds, lbls, val_or_trn):
    #takes predictions and labels and calculates error and backpropagates        
         mask = tor.index_select(lbls, -1, self.sizes[0])
         preds.register_hook(lambda grad: grad * mask.float())
         error = self.Loss_2(preds, lbls)
        
         if val_or_trn == 1:
             #backpropagation
             error.backward()
             self.Optimizer.step()
             self.Scheduler.step()
        
             #zeroing the gradients.
             self.Optimizer.zero_grad()
    

        return error.detach()

model = network()

其中输入、输出和通道是任意的。然后假设我创建了一些像这样的随机输入张量

input_data = torch.randn(1, 3, 256, 256)

然后我在这些数据中预测了一些结果

model(input_data)

假设我还通过在保持模型不变的情况下启动torch.randn命令一系列不同的时间来更改input_data变量。这不是重新启动model=network()命令

我得到这个错误

在培训时,每个通道的预期值超过1,获得输入大小。大小([1,某些值])

因此,我尝试在评估模式下运行它,使用model.eval()函数,如下所示

model.eval()

with tor.no_grad()
   pred = model(input_data)

model.train()

这是没有错误的。然而,无论我如何更改输入数据变量,我总是在pred中得到相同的值。然而,如果我重新启动模型的参数,我会得到一个新的pred,它再次不会随着不同的输入而改变。除非我再次使用model=network()重新启动模型。我做错了什么

编辑:为了提供更多关于我的问题的信息,我正在尝试从头创建一个类似于yolo的网络。这是我正在使用的数据集https://www.kaggle.com/devdgohil/the-oxfordiiit-pet-dataset


Tags: andtheselfnorminputmodeldevicebatch
2条回答

基本上这就是Batchnorm所做的。使用Batchnorm可以减少训练过度的倾向,但不要在评估中使用Batchnorm,这样你就可以得到正确的结果,就像辍学一样

每一个带有批量标准化和/或退出的CNN模型都做同样的事情。列车和评估期间,相同输入的输出将不同

这正是Pytork拥有model.eval()的原因。在推理过程中关闭这些层以获得正确的输出

编辑

问题在于输出端的激活和批处理规范化

只使用能使结果与基本事实相似的东西。当您希望输出在0-1范围内时,可以使用sigmoid;对于-1到1,可以使用tanh;对于轴上的概率,可以使用softmax

想象一下relu函数(它基本上是swishsoftplus的简单版本)。它会将0以下的所有内容都转换为0。你可能需要一些输出低于0,这样你的模型就不会收敛

你定义了一个神经网络,但你没有训练它

为了让您的模型在对数据进行多次迭代后预测来自同一输入的不同输出,您的模型需要能够调整其权重和偏差

为此,您需要一个损失函数和优化器,从中可以通过梯度下降反向传播预测误差以调整模型参数

我邀请您关注这个链接,其中介绍了在PyTorch中培训模特的每一步:QuickStart PyTorch

相关问题 更多 >

    热门问题