【问题标题】:Use Pytorch SSIM loss function in my model在我的模型中使用 Pytorch SSIM 损失函数
【发布时间】:2019-05-26 04:26:01
【问题描述】:

我正在试用this repo 的这个 SSIM loss 工具来进行图像恢复。

为了参考作者GitHub上的原始示例代码,我试过了:

model.train()
for epo in range(epoch):
    for i, data in enumerate(trainloader, 0):
        inputs = data
        inputs = Variable(inputs)
        optimizer.zero_grad()
        inputs = inputs.view(bs, 1, 128, 128)
        top = model.upward(inputs)
        outputs = model.downward(top, shortcut = True)
        outputs = outputs.view(bs, 1, 128, 128)

        if i % 20 == 0:
            out = outputs[0].view(128, 128).detach().numpy() * 255
            cv2.imwrite("/home/tk/Documents/recover/SSIM/" + str(epo) + "_" + str(i) + "_re.png", out)

        loss = - criterion(inputs, outputs)
        ssim_value = - loss.data.item()
        print (ssim_value)
        loss.backward()
        optimizer.step()

但是,结果并没有像我预期的那样出来。在前 10 个 epoch 之后,打印的结果图像都是黑色的。

loss = - criterion(inputs, outputs)是作者提出的,但是对于经典的Pytorch训练代码,这将是loss = criterion(y_pred, target),因此这里应该是loss = criterion(inputs, outputs)

不过,我试过loss = criterion(inputs, outputs),结果还是一样。

谁能分享一些关于如何正确利用 SSIM 损失的想法?谢谢。

【问题讨论】:

  • 你的criterion 是什么?是可微分的吗?
  • @Shai 抱歉回复晚了。标准是我帖子中的 pytorch_ssim.SSIM() 。它是可区分的。

标签: python deep-learning pytorch image-segmentation ssim


【解决方案1】:

作者试图最大化 SSIM 值。 对 pytorch 损失函数和优化器工作的自然理解是减少损失。但是 SSIM 值是质量度量,因此越高越好。因此作者使用
loss = - criterion(inputs, outputs)

您可以改为尝试使用
loss = 1 - criterion(inputs, outputs)
paper 中所述。


使用this repo测试上述内容的修改代码(max_ssim.py)

import pytorch_ssim
import torch
from torch.autograd import Variable
from torch import optim
import cv2
import numpy as np

npImg1 = cv2.imread("einstein.png")

img1 = torch.from_numpy(np.rollaxis(npImg1, 2)).float().unsqueeze(0)/255.0
img2 = torch.rand(img1.size())

if torch.cuda.is_available():
    img1 = img1.cuda()
    img2 = img2.cuda()


img1 = Variable( img1,  requires_grad=False)
img2 = Variable( img2, requires_grad = True)

print(img1.shape)
print(img2.shape)
# Functional: pytorch_ssim.ssim(img1, img2, window_size = 11, size_average = True)
ssim_value = 1-pytorch_ssim.ssim(img1, img2).item()
print("Initial ssim:", ssim_value)

# Module: pytorch_ssim.SSIM(window_size = 11, size_average = True)
ssim_loss = pytorch_ssim.SSIM()

optimizer = optim.Adam([img2], lr=0.01)

while ssim_value > 0.05:
    optimizer.zero_grad()
    ssim_out = 1-ssim_loss(img1, img2)
    ssim_value = ssim_out.item()
    print(ssim_value)
    ssim_out.backward()
    optimizer.step()
    cv2.imshow('op',np.transpose(img2.cpu().detach().numpy()[0],(1,2,0)))
    cv2.waitKey()

【讨论】:

    【解决方案2】:

    将相似度(越高越好)转换为损失的常用方法是计算1 - similarity(x, y)

    要创建这种损失,您可以创建一个新的“函数”。

    def ssim_loss(x, y):
        return 1. - ssim(x, y)
    

    或者,如果相似性是一个类 (nn.Module),您可以重载它来创建一个新类。

    class SSIMLoss(SSIM):
        def forward(self, x, y):
            return 1. - super().forward(x, y)
    

    此外,SSIM 有比这个 repo 更好的实现。例如,piqa Python 包之一的速度更快。 该软件包可以安装

    pip install piqa
    

    针对你的问题

    from piqa import SSIM
    
    class SSIMLoss(SSIM):
        def forward(self, x, y):
            return 1. - super().forward(x, y)
    
    criterion = SSIMLoss() # .cuda() if you need GPU support
    
    ...
    loss = criterion(x, y)
    ...
    

    应该很好用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-29
      • 2018-07-22
      • 1970-01-01
      • 2019-08-31
      • 2021-02-20
      • 2022-01-15
      • 2021-02-20
      • 2021-03-06
      相关资源
      最近更新 更多