关于 pytorch 中.eval () 的问题

技术讨论 Silencewang ⋅ 于 1个月前 ⋅ 最后回复由 NCTU_noob 1个月前 ⋅ 134 阅读

from future import print_function
import torch
from PIL import Image
import numpy as np
from models.u_net import UNet
from torch.autograd import Variable
from torchvision.models.segmentation import deeplabv3_resnet50

from models.resnet import resnet34
from torchvision.transforms import ToPILImage

---------------------------------------------------------------

val_path = './cloud/test/'
predict_path = 'cloud/pred-Unet-deconv-newdata-pooling-nn.conv-2bs/'
number_photo = 1352
model = UNet(3,1).cuda()

model_path = 'checkpoint/Unet-deconv-newdata-pooling-nn.conv-2bs/model/netG_178.pth'

model.load_state_dict(torch.load(model_path))
##model=model.eval()

---------------------------------------------------------------

transform1 = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
]
)
for i in range(1,number_photo+1):

test_image = Image.open(val_path+ str(i) + '.png').convert('RGB')

test_image = Image.open(val_path + str(i) + '.png')

img = transform1(test_image)
img = img.unsqueeze(0)
img = img.cuda()
img = Variable(img)

label_image = model(img)

label_image = label_image.squeeze(0)

label_image[label_image >= 0.5] = 1
label_image[label_image < 0.5] = 0
label_image = label_image.cpu()
a = transforms.ToPILImage()(label_image)
a.save(predict_path+ str(i) + '.png')
print('转换第%d张图' % (i))
i = i + 1
请问一下在我的测试代码中加上model.eval()和去除model.eval()结果差别非常大,没有加的话,在不同模型上都能测试出结果,而且结果也会有差别,加上之后效果非常差。请问一下这是什么原因造成的?

有人说是我的网络结构问题,下采样不i能将self.relu(self.bn())这么嵌套

 c1 = self.relu(self.bn64(self.in_conv1(input)))
    c2 = self.relu(self.bn64(self.in_conv2(c1)))

    e1_ = self.relu(self.bn128(self.conv1_1(self.pooling1(c2))))
    e1 = self.relu(self.bn128(self.conv1_2(e1_)))

    e2_ = self.relu(self.bn256(self.conv2_1(self.pooling1(e1))))
    e2 = self.relu(self.bn256(self.conv2_2(e2_)))

    e3_ = self.relu(self.bn512(self.conv3_1(self.pooling1(e2))))
    e3 = self.relu(self.bn512(self.conv3_2(e3_)))

    e4_ = self.relu(self.bn1024(self.conv4_1(self.pooling1(e3))))
    e4 = self.relu(self.bn1024(self.conv4_2(e4_)))

    d1_1 = self.upsampling1(e4)
    d1_2 = torch.cat([d1_1, e3], dim=1)
    d1_ = self.relu(self.bn512(self.conv5_1(d1_2)))
    d1 = self.relu(self.bn512(self.conv5_2(d1_)))

    d2_1 = self.upsampling2(d1)
    d2_2 = torch.cat([d2_1, e2], dim=1)
    d2_ = self.relu(self.bn256(self.conv6_1(d2_2)))
    d2 = self.relu(self.bn256(self.conv6_2(d2_)))

    d3_1 = self.upsampling3(d2)
    d3_2 = torch.cat([d3_1, e1], dim=1)
    d3_ = self.relu(self.bn128(self.conv7_1(d3_2)))
    d3 = self.relu(self.bn128(self.conv7_2(d3_)))

    d4_1 = self.upsampling4(d3)
    d4_2 = torch.cat([d4_1,c2], dim=1)
    d4_ = self.relu(self.bn64(self.conv8_1(d4_2)))
    d4 = self.relu(self.bn64(self.conv8_2(d4_)))

    output = self.sigmoid(self.out_conv(d4))

    return output

    麻烦各位大神给出指点

成为第一个点赞的人吧 :bowtie:
回复数量: 6
  • self.relu(self.bn()),这样是没问题的。
    主要是model.eval(),会把 batch normalization layer 的参数锁起来,不会更新。

    1个月前 2
  • 那请问一下出现这个问题应该怎么处理,或者不用model.eval()做出来的结果可以用吗。。。

    1个月前
  • 测试时,逻辑上是要用 .eval() 的,当然不用也是跑的动啦。
    说回代码,我看了一下是目前是看到 BN 层,有复用的问题,每个 BN 层都有自己的参数,一般不用在其他地方。
    不过把 .eval() 拿掉,结果比较好是挺不正常的,我的直觉是觉得是因为其他的问题。

    1个月前
  • class DoubleConv(nn.Module):
    def init(self, in_ch, out_ch):
    super(DoubleConv, self).init()
    self.conv = nn.Sequential(
    nn.Conv2d(in_ch, out_ch, 3, padding=1),
    nn.BatchNorm2d(out_ch),
    nn.ReLU(inplace=True),
    nn.Conv2d(out_ch, out_ch, 3, padding=1),
    nn.BatchNorm2d(out_ch),
    nn.ReLU(inplace=True)
    )

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

    class UNet(nn.Module):
    def init(self,in_ch,out_ch):
    super(UNet, self).init()

        self.conv1 = DoubleConv(in_ch, 64)
        self.down1 = nn.MaxPool2d(2)
        self.conv2 = DoubleConv(64, 128)
        self.down2 = nn.MaxPool2d(2)
        self.conv3 = DoubleConv(128, 256)
        self.down3 = nn.MaxPool2d(2)
        self.conv4 = DoubleConv(256, 512)
        self.down4 = nn.MaxPool2d(2)
        self.conv5 = DoubleConv(512, 1024)
        self.up6 = nn.ConvTranspose2d(1024, 512, 2, stride=2)
        self.conv6 = DoubleConv(1024, 512)
        self.up7 = nn.ConvTranspose2d(512, 256, 2, stride=2)
        self.conv7 = DoubleConv(512, 256)
        self.up8 = nn.ConvTranspose2d(256, 128, 2, stride=2)
        self.conv8 = DoubleConv(256, 128)
        self.up9 = nn.ConvTranspose2d(128, 64, 2, stride=2)
        self.conv9 = DoubleConv(128, 64)
        self.conv10 = nn.Conv2d(64,out_ch, 1)
        self.sigmoid = nn.Sigmoid()
    
    def forward(self,x):
        c1=self.conv1(x)
    
        p1=self.down1(c1)
        c2=self.conv2(p1)
        p2=self.down2(c2)
        c3=self.conv3(p2)
        p3=self.down3(c3)
        c4=self.conv4(p3)
        p4=self.down4(c4)
        c5=self.conv5(p4)
        up_6= self.up6(c5)
        merge6 = torch.cat([up_6, c4], dim=1)
        c6=self.conv6(merge6)
        up_7=self.up7(c6)
        merge7 = torch.cat([up_7, c3], dim=1)
        c7=self.conv7(merge7)
        up_8=self.up8(c7)
        merge8 = torch.cat([up_8, c2], dim=1)
        c8=self.conv8(merge8)
        up_9=self.up9(c8)
        merge9=torch.cat([up_9,c1],dim=1)
        c9=self.conv9(merge9)
        c10=self.conv10(c9)
        out = self.sigmoid(c10)
        return out

    我又重新写了这样的,可以用.eval(),但是跑出来结果会比不用的差了大概十个点,这就有点懵逼了,而且我测试代码二分类。居然会有测出灰色的,我也是醉了。。。

    1个月前
    • @Silencewang torchvision.transforms.ToTensor 是会顺便帮你将 [0, 255] 的值转成 [0, 1]的,但 torchvision.transforms.ToPILImage 不会顺便帮你转回去,要把 tensor *= 255 一下。

      1个月前
您需要登陆以后才能留下评论!