PyTorch 中的图像梯度 - 用于 WGAN 中的梯度惩罚计算
Gradient of Image in PyTorch - for Gradient Penalty calculation in WGAN
我正在关注此 Github Repo 以了解带有梯度惩罚的 WGAN 实现。
我正在尝试理解以下方法,该方法对梯度惩罚计算进行单元测试。
def test_gradient_penalty(image_shape):
bad_gradient = torch.zeros(*image_shape)
bad_gradient_penalty = gradient_penalty(bad_gradient)
assert torch.isclose(bad_gradient_penalty, torch.tensor(1.))
image_size = torch.prod(torch.Tensor(image_shape[1:]))
good_gradient = torch.ones(*image_shape) / torch.sqrt(image_size)
good_gradient_penalty = gradient_penalty(good_gradient)
assert torch.isclose(good_gradient_penalty, torch.tensor(0.))
random_gradient = test_get_gradient(image_shape)
random_gradient_penalty = gradient_penalty(random_gradient)
assert torch.abs(random_gradient_penalty - 1) < 0.1
# Now pass tuple argument for image dimenstion of
# (batch_size, channel, height, width)
test_gradient_penalty((256, 1, 28, 28))
我不明白下面这行
good_gradient = torch.ones(*image_shape) / torch.sqrt(image_size)
在上面的 torch.ones(*image_shape)
只是填充一个 4-D Tensor 填充 1 然后
torch.sqrt(image_size)
只是表示 tensor(28.)
的值
所以,我想了解为什么我需要将 4-D 张量除以 tensor(28.)
以获得 good_gradient
如果我打印 bad_gradient,它将是一个 4-D 张量,如下所示
tensor([[[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]],
---
---
如果我打印good_gradient
,输出将是
tensor([[[[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
...,
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357]]],
---
---
换行
good_gradient = torch.ones(*image_shape) / torch.sqrt(image_size)
首先,注意 WGAN 中的梯度惩罚项是 =>
(norm(gradient(interpolated)) - 1)^2
对于理想梯度(即良好梯度),该惩罚项将为 0。即良好梯度是其 gradient_penalty 尽可能接近 0 的梯度
这意味着在考虑了梯度的 L2-Norm 之后应该满足以下条件
(norm(gradient(x')) -1)^2 = 0
即norm(gradient(x')) = 1
即sqrt(Sum(gradient_i^2) ) = 1
现在如果你继续简化上面的(考虑 norm
是如何计算的,见我下面的注释)数学表达式,你最终会得到
good_gradient = torch.ones(*image_shape) / torch.sqrt(image_size)
由于您将 image_shape
作为 (256, 1, 28, 28) 传递 - 所以 torch.sqrt(image_size)
在您的情况下是张量 (28.)
有效地,上面的行将 4-D 张量的每个元素分开,如 [[[[1., 1. ... ]]]] 与缩放张量 (28.)
另外,注意 norm
是如何计算的
torch.norm
在没有额外参数的情况下执行所谓的 Frobenius 范数,它有效地将矩阵重塑为一个长向量并返回其 2 范数。
给定一个 M * N 矩阵,矩阵的 Frobenius 范数定义为矩阵元素平方和的平方根。
Input: mat[][] = [[1, 2], [3, 4]]
Output: 5.47723
sqrt(1^2 + 2^2 + 3^2 + 4^2) = sqrt(30) = 5.47723
我正在关注此 Github Repo 以了解带有梯度惩罚的 WGAN 实现。
我正在尝试理解以下方法,该方法对梯度惩罚计算进行单元测试。
def test_gradient_penalty(image_shape):
bad_gradient = torch.zeros(*image_shape)
bad_gradient_penalty = gradient_penalty(bad_gradient)
assert torch.isclose(bad_gradient_penalty, torch.tensor(1.))
image_size = torch.prod(torch.Tensor(image_shape[1:]))
good_gradient = torch.ones(*image_shape) / torch.sqrt(image_size)
good_gradient_penalty = gradient_penalty(good_gradient)
assert torch.isclose(good_gradient_penalty, torch.tensor(0.))
random_gradient = test_get_gradient(image_shape)
random_gradient_penalty = gradient_penalty(random_gradient)
assert torch.abs(random_gradient_penalty - 1) < 0.1
# Now pass tuple argument for image dimenstion of
# (batch_size, channel, height, width)
test_gradient_penalty((256, 1, 28, 28))
我不明白下面这行
good_gradient = torch.ones(*image_shape) / torch.sqrt(image_size)
在上面的 torch.ones(*image_shape)
只是填充一个 4-D Tensor 填充 1 然后
torch.sqrt(image_size)
只是表示 tensor(28.)
所以,我想了解为什么我需要将 4-D 张量除以 tensor(28.)
以获得 good_gradient
如果我打印 bad_gradient,它将是一个 4-D 张量,如下所示
tensor([[[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]],
---
---
如果我打印good_gradient
,输出将是
tensor([[[[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
...,
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357],
[0.0357, 0.0357, 0.0357, ..., 0.0357, 0.0357, 0.0357]]],
---
---
换行
good_gradient = torch.ones(*image_shape) / torch.sqrt(image_size)
首先,注意 WGAN 中的梯度惩罚项是 =>
(norm(gradient(interpolated)) - 1)^2
对于理想梯度(即良好梯度),该惩罚项将为 0。即良好梯度是其 gradient_penalty 尽可能接近 0 的梯度
这意味着在考虑了梯度的 L2-Norm 之后应该满足以下条件
(norm(gradient(x')) -1)^2 = 0
即norm(gradient(x')) = 1
即sqrt(Sum(gradient_i^2) ) = 1
现在如果你继续简化上面的(考虑 norm
是如何计算的,见我下面的注释)数学表达式,你最终会得到
good_gradient = torch.ones(*image_shape) / torch.sqrt(image_size)
由于您将 image_shape
作为 (256, 1, 28, 28) 传递 - 所以 torch.sqrt(image_size)
在您的情况下是张量 (28.)
有效地,上面的行将 4-D 张量的每个元素分开,如 [[[[1., 1. ... ]]]] 与缩放张量 (28.)
另外,注意 norm
是如何计算的
torch.norm
在没有额外参数的情况下执行所谓的 Frobenius 范数,它有效地将矩阵重塑为一个长向量并返回其 2 范数。
给定一个 M * N 矩阵,矩阵的 Frobenius 范数定义为矩阵元素平方和的平方根。
Input: mat[][] = [[1, 2], [3, 4]]
Output: 5.47723
sqrt(1^2 + 2^2 + 3^2 + 4^2) = sqrt(30) = 5.47723