反向转换 PyTorch 张量

Backtransforming a PyTorch Tensor

我在 CelebA dataset in PyTorch following this youtube video 上训练了一个 WGAN。由于我在 Google 云平台上执行此操作,其中 TensorBoard 不可用,因此我每个 epoch 保存一张 GAN 生成的图像图,以查看 GAN 的实际表现。

现在,保存的 pdf 文件看起来像这样:generated images。不幸的是,这并不是真正可读的,我怀疑这与我所做的预处理有关:

trafo = transforms.Compose(
                    [transforms.Resize(size = (64, 64)),
                    transforms.ToTensor(), 
                    transforms.Normalize( mean = (0.5,), std = (0.5,))]) 

有没有什么方法可以在我保存图像时撤消这种转换?

目前,我每个epoch保存图像如下:

visualization = torchvision.utils.make_grid(
                           tensor = gen(fixed_noise), 
                           nrow = 8, 
                           normalize = False)
plt.savefig("generated_WGAN_" + datetime.now().strftime("%Y%m%d-%H%M%S") + ".pdf")

另外,我应该提一下,在 Jupyter notebook 中,我收到以下警告:

“将输入数据剪裁到 imshow 的有效范围,其中 RGB 数据 ([0..1]) 用于浮点数或 [0..255] 用于整数。”

您的输出像素值似乎在 [-1, 1] 范围内(请验证)。
因此,当您保存图像时,负片部分会被剪掉(正如您收到的错误消息所暗示的那样)。

尝试:

visualization = torchvision.utils.make_grid(
                           tensor = torch.clamp(gen(fixed_noise), -1, 1) * 0.5 + 0.5,  # from [-1, 1] -> [0, 1]
                           nrow = 8, 
                           normalize = False)
plt.savefig("generated_WGAN_" + datetime.now().strftime("%Y%m%d-%H%M%S") + ".pdf")

torchvision.transform.Normalize function is usually used to standardize data (make mean(data)=0 and std(x)=1) while the normalize option on torchvision.utils.make_grid 用于对给定范围内 [0,1] 之间的数据进行归一化。所以不需要实现一个函数来解决这个问题。

If True, shift the image to the range (0, 1), by the min and max values specified by range. Default: False.

此处您希望在 01 之间进行标准化。给定张量 x:

torchvision.utils.make_grid(x, nrow=8, normalize=True, range=(x.min(), x.max()))

这里 some examples of use 由 PyTorch 的文档提供。


回到你最初的问题,我应该提到 torchvision.transform.Normalize(mean=0.5, std=0.5) 不会 转换你的数据,使其具有 mean=0.5std=0.5...它也不会将其标准化为mean=0std=1。您必须测量数据集中的均值和标准差。

torchvision.transform.Normalize 只是简单地执行了一个移位缩放操作。要撤消使用相同值的 unscale-unshift:

>>> x = torch.rand(64, 3, 100, 100)*torch.rand(64, 1, 1, 1)
>>> x.mean(), x.std()
(tensor(0.2536), tensor(0.2175))

>>> t = T.Normalize(mean, std)
>>> t_inv = lambda x: x*std + mean

>>> x_after = t(x)
>>> x_after.mean(), x_after.std()
(tensor(-0.4928), tensor(0.4350))

>>> x_before = t_inv(x_after)
>>> x_before.mean(), x_before.std()
(tensor(0.2536), tensor(0.2175))