VGG 损失详解:从像素损失到感知损失

在图像生成、超分辨率、风格迁移、图像修复等计算机视觉任务中,常见的损失函数有像素损失、对抗损失、感知损失等。

其中 VGG 损失通常指 VGG Perceptual Loss,也叫 VGG 感知损失

它的核心思想是:

不直接比较两张图像的像素差异,而是比较它们经过预训练 VGG 网络后,在特征空间中的差异。


1. 为什么需要 VGG 损失?

最常见的图像重建损失是像素级损失,例如 L1 或 L2 损失。

假设真实图像为:

x x x

生成图像为:

x^ \hat{x} x^

L1 损失为:

L1=∣∣x−x^∣∣1 \mathcal{L}_{1} = ||x - \hat{x}||_1 L1=∣∣xx^1

L2 损失为:

L2=∣∣x−x^∣∣22 \mathcal{L}_{2} = ||x - \hat{x}||_2^2 L2=∣∣xx^22

这类损失会逐像素比较两张图像是否一致。

但是图像任务中,“像素接近”不一定代表“视觉效果好”。例如在超分辨率任务中,使用 L2 损失往往会得到比较平滑、模糊的结果,因为模型倾向于预测多个可能结果的平均值。

因此,引入了感知损失。


2. VGG 损失的核心思想

VGG 损失使用一个在 ImageNet 上预训练好的 VGG 网络作为特征提取器。

将真实图像和生成图像分别输入 VGG 网络,取某一层或多层的中间特征,然后比较这些特征之间的距离。

设 VGG 网络第 lll 层的特征提取函数为:

ϕl(⋅) \phi_l(\cdot) ϕl()

则 VGG 感知损失可以写成:

LVGG=∣∣ϕl(x)−ϕl(x^)∣∣1 \mathcal{L}_{VGG} = ||\phi_l(x) - \phi_l(\hat{x})||_1 LVGG=∣∣ϕl(x)ϕl(x^)1

或者:

LVGG=∣∣ϕl(x)−ϕl(x^)∣∣22 \mathcal{L}_{VGG} = ||\phi_l(x) - \phi_l(\hat{x})||_2^2 LVGG=∣∣ϕl(x)ϕl(x^)22

其中:

  • xxx 表示真实图像;
  • x^\hat{x}x^表示生成图像;
  • ϕl(x)\phi_l(x)ϕl(x)表示真实图像经过 VGG 第 lll 层后的特征;
  • ϕl(x^)\phi_l(\hat{x})ϕl(x^)表示生成图像经过 VGG 第 lll 层后的特征。

3. VGG 损失和像素损失的区别

像素损失关注的是:

两张图像在每个像素位置上的数值是否接近。

VGG 损失关注的是:

两张图像在深层特征空间中的内容、结构和纹理是否相似。

举个直观例子:

两张图片的物体位置、纹理、边缘看起来很像,但像素值可能并不完全一样。像素损失会认为它们差异较大,而 VGG 损失可能认为它们在视觉语义上比较接近。

因此,VGG 损失更接近人眼感知。


4. VGG 网络为什么适合做感知损失?

VGG 网络结构简单,主要由卷积层和池化层组成。虽然它最初是为图像分类设计的,但中间层特征包含了丰富的视觉信息。

一般来说:

浅层特征更关注边缘、颜色、纹理等低级信息;

中层特征更关注局部结构和形状;

深层特征更关注高级语义内容。

因此,不同层的 VGG 特征可以用来约束不同层次的视觉信息。

例如:

  • relu12relu1_2relu12更关注颜色和纹理;
  • relu22relu2_2relu22更关注局部边缘和细节;
  • relu33relu3_3relu33更关注结构信息;
  • relu43relu4_3relu43更关注高级语义内容。

5. 多层 VGG 损失

实际使用时,往往不会只使用单层特征,而是选取多层 VGG 特征共同计算损失。

形式如下:

LVGG=∑lλl∣∣ϕl(x)−ϕl(x^)∣∣1 \mathcal{L}_{VGG} = \sum_l \lambda_l ||\phi_l(x) - \phi_l(\hat{x})||_1 LVGG=lλl∣∣ϕl(x)ϕl(x^)1

其中:

  • lll 表示选取的 VGG 层;

  • λl\lambda_lλl表示第 lll 层损失的权重。

多层特征可以同时约束低层纹理和高层语义,使生成结果更自然。


6. VGG 损失常见应用

VGG 损失常用于以下任务:

6.1 图像超分辨率

在超分辨率中,如果只用像素损失,生成结果通常比较平滑。

加入 VGG 损失后,模型更容易恢复纹理和细节,例如头发、草地、建筑边缘等。

常见损失组合为:

L=Lpixel+λLVGG \mathcal{L} = \mathcal{L}_{pixel} + \lambda \mathcal{L}_{VGG} L=Lpixel+λLVGG

6.2 图像风格迁移

风格迁移中通常有两类 VGG 损失:

内容损失:

Lcontent=∣∣ϕl(xc)−ϕl(x^)∣∣22 \mathcal{L}_{content} = ||\phi_l(x_c) - \phi_l(\hat{x})||_2^2 Lcontent=∣∣ϕl(xc)ϕl(x^)22

风格损失通常基于 Gram Matrix:

Gl=ϕl(x)ϕl(x)T G_l = \phi_l(x)\phi_l(x)^T Gl=ϕl(x)ϕl(x)T

风格损失为:

Lstyle=∣∣Gl(xs)−Gl(x^)∣∣22 \mathcal{L}_{style} = ||G_l(x_s) - G_l(\hat{x})||_2^2 Lstyle=∣∣Gl(xs)Gl(x^)22

其中:

  • xcx_cxc表示内容图;
  • xsx_sxs表示风格图;
  • x^\hat{x}x^表示生成图。

6.3 图像修复

图像修复任务中,VGG 损失可以帮助模型生成更符合上下文语义的内容,而不是仅仅让缺失区域的像素值接近真实图像。

6.4 图像生成

在 GAN 或扩散模型的一些变体中,VGG 损失也可以作为辅助损失,使生成图像在感知层面更接近目标图像。


7. VGG 损失和 FID 的区别

VGG 损失和 FID 都使用深度神经网络特征,但它们的用途不同。

VGG 损失通常是训练过程中的损失函数,用来优化模型参数。

FID 是评估指标,用来衡量一批生成图像和真实图像的整体分布差异。

标准 FID 通常使用 Inception-v3 特征,而不是 VGG 特征。

可以简单理解为:

VGG Loss→训练时使用 VGG\ Loss \rightarrow 训练时使用 VGG Loss训练时使用

FID→测试或评估时使用 FID \rightarrow 测试或评估时使用 FID测试或评估时使用

VGG 损失比较的是单张图像或成对图像之间的感知差异;FID 比较的是两组图像整体分布之间的差异。


8. VGG 损失的优点

VGG 损失的主要优点是:

第一,它比像素损失更符合人眼感知。

第二,它可以提升生成图像的纹理、边缘和结构质量。

第三,它适合与 L1、L2、GAN Loss 等其他损失联合使用。

第四,它实现简单,只需要加载预训练 VGG 网络并固定参数。


9. VGG 损失的缺点

VGG 损失也有一些局限。

首先,它依赖预训练 VGG 网络。如果任务领域和 ImageNet 差异很大,例如医学图像、遥感图像,VGG 特征可能并不完全合适。

其次,VGG 损失会增加训练计算量,因为每次都需要额外前向传播 VGG 网络。

另外,VGG 损失并不一定保证像素级准确。如果任务要求严格的数值一致性,例如医学重建、物理测量图像,仅使用 VGG 损失可能不够。


10. PyTorch 伪代码示例

下面是一个简化版 VGG 损失实现思路:

import torch
import torch.nn as nn
from torchvision.models import vgg19, VGG19_Weights

class VGGLoss(nn.Module):
    def __init__(self):
        super(VGGLoss, self).__init__()

        vgg = vgg19(weights=VGG19_Weights.IMAGENET1K_V1).features

        # 取 VGG19 的前若干层作为特征提取器
        self.feature_extractor = vgg[:36].eval()

        for param in self.feature_extractor.parameters():
            param.requires_grad = False

        self.loss = nn.L1Loss()

    def forward(self, generated, target):
        generated_features = self.feature_extractor(generated)
        target_features = self.feature_extractor(target)

        loss = self.loss(generated_features, target_features)
        return loss

实际使用时,需要注意图像输入要按照 ImageNet 的均值和方差进行归一化。


11. 总结

VGG 损失是一种典型的感知损失。它不直接比较图像像素,而是利用预训练 VGG 网络提取特征,然后比较真实图像和生成图像在特征空间中的差异。

它的核心公式是:

LVGG=∣∣ϕl(x)−ϕl(x^)∣∣ \mathcal{L}_{VGG} = ||\phi_l(x) - \phi_l(\hat{x})|| LVGG=∣∣ϕl(x)ϕl(x^)∣∣

相比像素损失,VGG 损失更关注图像的视觉质量、纹理结构和语义相似性,因此在超分辨率、风格迁移、图像修复和图像生成任务中非常常见。

一句话总结:

VGG 损失衡量的不是“像素是否一样”,而是“看起来是否像”。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐