1. 项目概述:从“看见”到“看清”的鲁棒性挑战

在计算机视觉领域,我们常常会遇到一个令人头疼的现象:模型在精心准备的测试集上表现优异,准确率高达99%,但一旦部署到真实世界,面对光照变化、背景干扰、轻微模糊或对抗性扰动时,其性能就可能断崖式下跌。这就像一位视力极佳但“眼神不好”的专家,在标准视力表上能看清最下面一行,但在复杂环境中却容易看错关键信息。这种脆弱性,或者说缺乏“鲁棒性”,是当前深度学习模型走向实际应用的核心瓶颈之一。

“傅里叶正则化”这个项目,正是为了解决这一痛点而生。它不是一个全新的模型架构,而是一种巧妙的训练策略,其核心思想源于信号处理领域的经典理论——傅里叶变换。简单来说,它试图引导模型在学习图像内容时,不要过度依赖那些容易被干扰的、高频的细节信息(比如物体边缘的微小锯齿、纹理的细微变化),而是更多地关注那些更稳定、更本质的低频信息(比如物体的整体形状、大致的颜色分布)。通过调控模型对不同频率成分的“敏感性”,我们能让模型在面对各种干扰时,依然保持稳定、可靠的判断力。

这个项目适合所有致力于提升模型实际部署效果的从业者,无论是研究对抗样本防御、域泛化,还是希望模型在复杂光照、天气下保持稳定的工程师。它不要求你更换强大的硬件或复杂的网络,而是在训练过程中加入一种“思想钢印”,让模型学会“抓大放小”,从而获得一种内在的鲁棒性。接下来,我将结合自己多次实验和部署的经验,为你拆解这套方法背后的原理、实现细节以及那些文档里不会写的“坑”。

2. 核心思路拆解:为什么是频率域?

2.1 图像信号的频率视角

要理解傅里叶正则化,首先得跳出像素空间,进入频率域来看图像。任何一张数字图像,都可以看作是由无数个不同频率、不同振幅的正弦波叠加而成。经过二维离散傅里叶变换(2D-DFT),图像就从我们熟悉的(高度,宽度,通道)空间,转换到了(频率高度,频率宽度,通道)的频率空间。

在这个频率空间中:

  • 低频成分 :通常位于频谱图的中心区域。它们代表了图像中变化缓慢的部分,比如大面积的天空、墙壁、物体的主体轮廓。这些信息是全局的、稳定的,对平移、轻微模糊等扰动不敏感。
  • 高频成分 :位于频谱图的边缘区域。它们代表了图像中快速变化的部分,比如锐利的边缘、细致的纹理、噪声点。这些信息是局部的、细节丰富的,但也极其脆弱,轻微的扰动(如高斯噪声、对抗性扰动)就能轻易改变高频分量的相位和振幅。

一个关键观察是:许多常见的图像干扰和对抗性攻击,其能量主要集中在高频部分。攻击者通过精心构造的高频噪声,就能“欺骗”模型。而自然扰动(如运动模糊、雾霾)则可能同时衰减高频信息。

2.2 模型“过拟合”频率的隐患

标准的深度学习模型,尤其是那些参数量巨大、容量很高的模型(如ResNet, Vision Transformer),在训练过程中会竭尽全力拟合训练数据中的所有模式,包括高频细节。这固然能提升在干净测试集上的精度,但也带来了两个问题:

  1. 对高频噪声的敏感性 :模型学会了依赖那些独特但脆弱的高频特征来进行分类。一旦这些高频特征被干扰或篡改(无论是无意的还是有意的),模型的判断依据就消失了,导致错误。
  2. 对本质特征的忽视 :模型可能没有充分学习到那些隐藏在低频中的、更鲁棒的语义特征。它走了一条“捷径”,通过记忆细节而非理解形状来解决问题。

傅里叶正则化的目标,就是打破模型对高频信息的过度依赖,鼓励甚至强制它去挖掘和利用低频信息中蕴含的鲁棒特征。

2.3 正则化的实现路径:抑制、增强与不变性

基于上述分析,傅里叶正则化通常通过以下几种路径在训练中实现:

  1. 高频抑制(High-frequency Suppression) :在训练数据的预处理或网络前向传播过程中,主动滤除或衰减输入图像的高频成分。这相当于给模型戴上了一副“柔光镜”,让它无法看清过于细节的东西,从而被迫去学习更宏观的特征。实现方式可以是在频率域进行低通滤波,也可以在空间域进行平滑操作(如高斯模糊)。
  2. 低频增强(Low-frequency Enhancement) :与抑制高频相对,可以强调低频成分。例如,在损失函数中,为模型从低频成分中重建图像或做出正确预测给予更高的奖励。
  3. 频率不变性约束(Frequency Invariance Constraint) :这是更高级也更有效的思路。核心是要求模型对同一图像的不同频率版本(例如原图、低通滤波后的图)产生一致或相似的表示(特征)或预测。这通过在设计损失函数时,增加一个“一致性损失”项来实现。模型为了最小化这个损失,就必须学会提取那些在不同频率表达下都保持稳定的特征,这些特征天然就是鲁棒的。

在实际项目中, 频率不变性约束 因其优雅性和有效性,成为了主流方法。它不是在削弱模型的感知能力,而是在引导它形成更健康的“认知习惯”。

3. 核心实现:从理论到PyTorch代码

理论很美好,但落地是关键。下面我将以一个经典的“频率不变性特征学习”为例,详细拆解其PyTorch实现步骤。我们会构建一个可插拔的傅里叶正则化模块,方便你嵌入到现有的训练流程中。

3.1 关键组件:二维傅里叶变换与滤波

首先,我们需要实现图像在批次(Batch)维度上的快速傅里叶变换(FFT)和逆变换(IFFT),以及一个灵活的频率滤波器。

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np

class FourierFilter2D(nn.Module):
    """
    一个灵活的二维频率域滤波器。
    支持低通、高通、带通滤波,以及自定义滤波掩码。
    """
    def __init__(self, filter_type='lowpass', cutoff_ratio=0.5, bandwidth_ratio=0.1):
        super(FourierFilter2D, self).__init__()
        self.filter_type = filter_type
        self.cutoff_ratio = cutoff_ratio  # 截止频率比例 (0~1)
        self.bandwidth_ratio = bandwidth_ratio  # 用于带通滤波的带宽

    def _create_filter_mask(self, height, width, device):
        """创建频率滤波掩码。"""
        # 生成频率网格,中心为0频率
        h, w = height, width
        y = torch.arange(-h//2, h//2, device=device).float()
        x = torch.arange(-w//2, w//2, device=device).float()
        Y, X = torch.meshgrid(y, x, indexing='ij')
        D = torch.sqrt(X**2 + Y**2)  # 每个点到中心(0频率)的距离
        D = D / (torch.max(D) + 1e-8)  # 归一化到[0, 1]

        mask = torch.ones((h, w), device=device)

        if self.filter_type == 'lowpass':
            # 低通滤波:距离小于截止频率的区域为1,其余为0(理想滤波器)
            # 实践中常用高斯或巴特沃斯滤波器以获得平滑过渡
            mask = torch.exp(- (D / self.cutoff_ratio)**4)  # 近似高斯低通,过渡更平滑
        elif self.filter_type == 'highpass':
            mask = 1.0 - torch.exp(- (D / self.cutoff_ratio)**4)
        elif self.filter_type == 'bandpass':
            # 带通:保留特定频率范围内的成分
            low_cut = max(0, self.cutoff_ratio - self.bandwidth_ratio/2)
            high_cut = min(1, self.cutoff_ratio + self.bandwidth_ratio/2)
            mask = torch.exp(- (D / high_cut)**4) - torch.exp(- (D / low_cut)**4)
            mask = torch.clamp(mask, 0, 1)
        # 可以扩展更多滤波器类型...
        return mask

    def forward(self, x_freq):
        """
        对频率域信号x_freq进行滤波。
        x_freq: 形状为 (B, C, H, W) 的复数张量,表示傅里叶系数。
        返回滤波后的频率域信号。
        """
        B, C, H, W = x_freq.shape
        # 为每个通道创建相同的滤波掩码(也可以设计通道相关的)
        filter_mask = self._create_filter_mask(H, W, x_freq.device)
        # 扩展维度以匹配批次和通道数
        filter_mask = filter_mask.view(1, 1, H, W).expand(B, C, H, W)
        # 应用滤波掩码
        x_freq_filtered = x_freq * filter_mask
        return x_freq_filtered

def batch_fft2(x):
    """对批次图像进行2D FFT,并做频谱中心化。"""
    # x: (B, C, H, W)
    x_fft = torch.fft.fft2(x, norm='ortho')
    # 将零频率分量移到频谱中心
    x_fft_shifted = torch.fft.fftshift(x_fft, dim=(-2, -1))
    return x_fft_shifted

def batch_ifft2(x_freq_shifted):
    """对中心化的频率信号进行2D逆FFT,返回空间域图像。"""
    # 将零频率移回角落
    x_freq = torch.fft.ifftshift(x_freq_shifted, dim=(-2, -1))
    x = torch.fft.ifft2(x_freq, norm='ortho').real  # 取实部,理论上应为原始图像(可能有微小误差)
    return x

注意 :这里使用了 norm='ortho' 来保证变换是归一化的,使得 ifft2(fft2(x)) 能几乎完美还原 x (忽略浮点误差)。同时,我们使用了平滑的高斯型滤波器而非理想的矩形窗,这是为了避免在空间域引入振铃效应。

3.2 构建频率不变性正则化损失

接下来,我们实现核心的频率不变性正则化模块。它的作用是计算原始图像特征和其低频版本特征之间的距离,并将其作为额外的损失项。

class FrequencyInvarianceRegularizer(nn.Module):
    """
    频率不变性正则化器。
    计算模型对原始图像和其低频版本图像的特征之间的差异。
    """
    def __init__(self, feature_layer, loss_type='cosine', cutoff_ratio=0.3, strength=1.0):
        """
        Args:
            feature_layer: 一个函数或nn.Module,用于从模型中提取特征。
                           例如:lambda model, x: model.features(x)
            loss_type: 特征差异的度量方式,'cosine'(余弦相似度)或 'mse'(均方误差)。
            cutoff_ratio: 低通滤波器的截止频率比例。
            strength: 正则化项的强度系数(lambda)。
        """
        super(FrequencyInvarianceRegularizer, self).__init__()
        self.feature_extractor = feature_layer
        self.loss_type = loss_type
        self.filter = FourierFilter2D(filter_type='lowpass', cutoff_ratio=cutoff_ratio)
        self.strength = strength

    def forward(self, model, x, y):
        """
        Args:
            model: 主模型。
            x: 输入图像,形状 (B, C, H, W)。
            y: 标签(在本正则项中可能不直接使用,但保留接口)。
        Returns:
            total_loss: 主分类损失 + 正则化损失。
            classification_loss: 主分类损失。
            reg_loss: 频率不变性正则化损失。
        """
        # 1. 正常前向传播,计算主损失
        preds = model(x)
        classification_loss = F.cross_entropy(preds, y)

        # 2. 生成输入图像的低频版本
        with torch.no_grad(): # 低频图像生成过程不需要梯度
            x_freq = batch_fft2(x)
            x_freq_low = self.filter(x_freq)
            x_low = batch_ifft2(x_freq_low)
            # 可选:对x_low进行裁剪,确保值在合理范围内(如[0,1])
            x_low = torch.clamp(x_low, 0, 1)

        # 3. 提取特征
        # 注意:这里需要确保model在训练模式下,但特征提取部分应能处理梯度。
        feat_original = self.feature_extractor(model, x)
        feat_low = self.feature_extractor(model, x_low)

        # 4. 计算特征一致性损失
        if self.loss_type == 'cosine':
            # 使用余弦相似度,鼓励特征方向一致
            feat_original_flat = feat_original.view(feat_original.size(0), -1)
            feat_low_flat = feat_low.view(feat_low.size(0), -1)
            cos_sim = F.cosine_similarity(feat_original_flat, feat_low_flat, dim=1)
            reg_loss = 1.0 - cos_sim.mean() # 余弦相似度越接近1,损失越接近0
        elif self.loss_type == 'mse':
            reg_loss = F.mse_loss(feat_original, feat_low)
        else:
            raise ValueError(f"Unsupported loss type: {self.loss_type}")

        # 5. 组合损失
        total_loss = classification_loss + self.strength * reg_loss

        return total_loss, classification_loss, reg_loss

3.3 集成到训练循环中

现在,我们将这个正则化器集成到标准的训练循环里。假设我们有一个经典的ResNet-18模型。

import torch.optim as optim
from torchvision import models, datasets, transforms

# 1. 准备数据、模型、优化器
train_loader = ... # 你的数据加载器
model = models.resnet18(pretrained=False, num_classes=10)
optimizer = optim.Adam(model.parameters(), lr=1e-3)

# 2. 定义特征提取函数
# 对于ResNet,我们可以提取全局平均池化前的特征图,或者最后一个卷积层的输出。
def resnet_feature_extractor(model, x):
    # 这里以提取最后一个卷积层(layer4)的输出为例
    # 注意:这是一个简化的hook方式,实际使用可能需要更严谨的hook或修改forward
    x = model.conv1(x)
    x = model.bn1(x)
    x = model.relu(x)
    x = model.maxpool(x)
    x = model.layer1(x)
    x = model.layer2(x)
    x = model.layer3(x)
    x = model.layer4(x) # 形状: (B, 512, H/32, W/32)
    return x

# 3. 实例化正则化器
fir = FrequencyInvarianceRegularizer(
    feature_layer=resnet_feature_extractor,
    loss_type='cosine',
    cutoff_ratio=0.4, # 这是一个关键超参数,需要调优
    strength=0.5 # 正则化强度,另一个关键超参
)

# 4. 修改训练循环
model.train()
for epoch in range(num_epochs):
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.cuda(), target.cuda()
        optimizer.zero_grad()

        # 使用正则化器计算损失
        total_loss, cls_loss, reg_loss = fir(model, data, target)

        total_loss.backward()
        optimizer.step()

        if batch_idx % 100 == 0:
            print(f'Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)}] '
                  f'Cls Loss: {cls_loss.item():.4f} Reg Loss: {reg_loss.item():.4f} '
                  f'Total Loss: {total_loss.item():.4f}')

4. 超参数调优与实操心得

傅里叶正则化的效果很大程度上取决于几个关键超参数的选择。这里分享一些我通过大量实验总结出的经验。

4.1 关键超参数解析

  1. 截止频率比例 ( cutoff_ratio )

    • 作用 :决定低通滤波器保留多少低频信息。值越小,过滤掉的高频越多,图像越模糊。
    • 调优范围 :通常在 0.2 0.6 之间。对于CIFAR-10/CIFAR-100这类32x32的小图像,建议从 0.3 开始尝试;对于ImageNet等大图像,可以尝试 0.1 0.3
    • 心得 :这不是越大越好。过大的 cutoff_ratio (如>0.6)意味着保留了太多高频信息,正则化效果微弱;过小(如<0.1)则可能过度模糊图像,损害模型对必要细节的分辨能力,导致基础精度下降。 一个实用的技巧是可视化低频图像 ,确保它虽然模糊,但主要物体的轮廓和类别信息依然可辨。
  2. 正则化强度 ( strength )

    • 作用 :平衡主分类损失和一致性损失。
    • 调优范围 0.1 2.0 。这是一个需要精细调节的参数。
    • 心得 :开始时可以设一个较小的值(如0.1),观察训练日志。如果 reg_loss 远小于 cls_loss (例如1/10以下),说明正则化作用太弱,可以逐步增大 strength 。目标是让 reg_loss 在训练中后期与 cls_loss 处于同一数量级,或略小。 过强的正则化会迫使模型过度忽略细节,同样损害精度。
  3. 特征提取层 ( feature_layer )

    • 作用 :决定从网络的哪一层提取特征来计算一致性。
    • 选择 越靠近输出的层,特征语义信息越强,但空间信息越抽象。 对于分类任务,常用最后几个卷积层或全局池化前的特征。对于密集预测任务(如分割),可能需要在多个尺度上提取特征。
    • 心得 :从中间层(如ResNet的 layer3 )开始尝试通常是个安全的选择。它既包含了一定的语义信息,又保留了一些空间结构。你可以进行消融实验,比较从不同层提取特征的效果。
  4. 损失类型 ( loss_type )

    • cosine vs mse cosine 损失关注特征向量的方向一致性,对特征的幅度变化不敏感,通常更稳定,是我首选的选项。 mse 损失要求特征值严格接近,在特征幅度动态范围较大时可能过于严苛,导致训练不稳定。

4.2 训练动态观察与调试

在训练过程中,你需要密切关注以下指标:

  • 训练集精度 :引入傅里叶正则化后,训练集精度可能会比基线模型 略有下降 (例如下降0.5%-2%),这是正常的,因为模型的学习任务变难了(它不能只靠记高频细节了)。
  • 验证集精度 :这是我们的主要观察点。理想情况下,在干净验证集上,精度应与基线持平或 轻微下降 ,但下降幅度应小于训练集。这表示模型泛化能力没有受损。
  • 鲁棒性测试集精度 :在加了噪声、模糊或对抗样本的测试集上,精度应有 显著提升 。这是衡量正则化成功与否的黄金标准。
  • 损失曲线 :观察 cls_loss reg_loss 的下降曲线。 reg_loss 应该随着训练稳步下降,最终收敛到一个较小的正值(因为完全一致很难达到)。如果 reg_loss 始终很高或剧烈震荡,可能需要降低 strength 或调整 cutoff_ratio

一个重要的实操技巧:渐进式正则化 。不要在训练一开始就施加很强的频率不变性约束。可以在前几个epoch使用较小的 strength (甚至为0),让模型先学习一些基础特征,然后再逐步增大 strength 。这类似于“课程学习”,让模型先易后难。

5. 效果评估与对比实验设计

为了令人信服地证明傅里叶正则化的有效性,你需要设计严谨的对比实验。以下是一个标准的评估框架。

5.1 基准模型与评估指标

  1. 基线模型 (Baseline) :使用完全相同的架构、数据增强、优化器设置,但不加任何傅里叶正则化进行训练。
  2. 傅里叶正则化模型 (Ours) :在基线基础上,加入我们实现的 FrequencyInvarianceRegularizer
  3. 对比方法 :可以选择其他提升鲁棒性的经典方法作为对比,例如:
    • 数据增强 :如CutMix, MixUp, AutoAugment。
    • 对抗训练 :如PGD对抗训练(计算成本高)。
    • 其他正则化 :如Dropout, Label Smoothing。

评估指标

  • 干净准确率 (Clean Accuracy) :在原始、无干扰的测试集上的Top-1准确率。
  • 鲁棒准确率 (Robust Accuracy)
    • 噪声鲁棒性 :在添加了高斯噪声、椒盐噪声的测试集上的准确率。
    • 模糊鲁棒性 :在经过高斯模糊、运动模糊处理的测试集上的准确率。
    • 对抗鲁棒性 :在白盒攻击(如FGSM, PGD)下生成的对抗样本上的准确率。 注意:评估对抗鲁棒性计算量很大,可根据项目重点选择。
  • 平均鲁棒增益 :计算模型在所有鲁棒性测试集上相对于基线的平均准确率提升。

5.2 实验结果呈现与分析

将实验结果整理成表格,清晰直观。

模型 干净准确率 (%) 高斯噪声 (σ=0.1) 运动模糊 (kernel=15) PGD攻击 (ε=8/255) 平均鲁棒增益
Baseline (ResNet-18) 95.2 65.3 70.1 12.5 -
+ CutMix 94.8 68.7 (+3.4) 72.5 (+2.4) 15.1 (+2.6) +2.8
+ Label Smoothing 94.9 67.1 (+1.8) 71.8 (+1.7) 13.8 (+1.3) +1.6
+ 傅里叶正则化 (Ours) 94.5 (-0.7) 72.4 (+7.1) 76.2 (+6.1) 18.9 (+6.4) +6.5

(注:以上为模拟数据,实际效果因数据集和超参而异)

结果分析要点

  1. 精度-鲁棒性权衡 :我们的方法在干净准确率上有微不足道的下降(0.7%),但换来了在所有鲁棒性指标上大幅度的提升(平均增益+6.5%),这个权衡是非常值得的。
  2. 对比优势 :相较于CutMix和Label Smoothing,傅里叶正则化在鲁棒性提升上表现更全面、更显著,尤其是在对抗攻击防御上。
  3. 结论 :傅里叶正则化通过引导模型关注低频的鲁棒特征,有效提升了模型对多种常见干扰的抵御能力,且实现简单,计算开销相对较小(主要增加一次FFT/IFFT和一次前向传播)。

6. 常见问题与排查技巧实录

在实际操作中,你肯定会遇到各种问题。下面是我踩过的一些坑和解决方案。

6.1 训练不稳定或发散

  • 症状 reg_loss 异常大或为NaN,总损失震荡剧烈,模型无法收敛。
  • 可能原因与排查
    1. strength 过大 :这是最常见的原因。立即检查训练日志开头几个batch的 reg_loss 值。如果它一开始就比 cls_loss 大一个数量级,说明正则化太强了。 解决方案 :将 strength 降低一个数量级(例如从1.0降到0.1)重新开始训练。
    2. 特征幅度差异大 :如果使用 mse 损失,且提取的特征层数值范围很大或不稳定,会导致梯度爆炸。 解决方案 :优先使用 cosine 损失。如果必须用 mse ,考虑在特征提取后加入一个层归一化(LayerNorm)或批量归一化(BatchNorm)来稳定特征尺度。
    3. 低频图像数值溢出 :逆FFT后, x_low 的数值可能略微超出原始图像的范围(如[0,1])。虽然 torch.clamp 可以解决,但剧烈的裁剪可能引入信息损失。 解决方案 :在滤波时使用更平滑的滤波器(如我们代码中的高斯型),并确保 cutoff_ratio 不是极端小。也可以在滤波后,对频谱进行轻微的缩放,使其能量与原始图像接近。

6.2 鲁棒性没有提升甚至下降

  • 症状 :在鲁棒性测试集上,准确率与基线相比没有改善,或者干净准确率下降太多。
  • 可能原因与排查
    1. cutoff_ratio 设置不当 :这是核心超参数。 排查 :可视化生成的低频图像 x_low 。如果图像已经模糊到连物体类别都无法区分(比如猫和狗看起来都一样),那么模型从中学不到任何有用的不变性。需要调高 cutoff_ratio 。反之,如果 x_low 看起来和原图几乎没区别,说明滤波太弱,需要调低 cutoff_ratio
    2. 特征层选择不当 :如果从过于浅的层(如第一个卷积层后)提取特征,特征包含的语义信息太少,模型很容易满足一致性(因为都是低级边缘),但这对提升高层语义的鲁棒性帮助有限。 解决方案 :尝试更深的层。
    3. 数据集本身过于简单 :如果数据集(如MNIST)本身特征就很低频,那么高频抑制可能作用不大。 解决方案 :对于这类数据,可以尝试更激进的滤波,或者转向研究如何防御低频攻击。

6.3 计算效率与内存问题

  • 症状 :训练速度明显变慢,GPU内存使用增加。
  • 分析 :傅里叶变换/逆变换是计算密集型操作,且我们为了计算 reg_loss 需要额外做一次前向传播(对 x_low )。
  • 优化技巧
    1. 梯度检查点 :如果内存是瓶颈,可以对处理 x_low 的那部分前向传播使用 torch.utils.checkpoint ,以时间换空间。
    2. 降低频率 :不必每个训练step都计算正则化损失。可以每隔2个或4个step计算一次。这能显著降低计算开销,且对最终效果影响很小。
    3. 在输入层应用 :一种更轻量级的变体是,直接将低频图像 x_low 作为另一个输入,与原始图像 x 一起输入网络,然后要求网络中间层的特征或最终输出保持一致。这样只需要一次前向传播,但需要修改模型输入部分。

6.4 与其他技术结合

傅里叶正则化可以很好地与现有技术结合,产生叠加效果:

  • 与数据增强结合 :在应用CutMix或MixUp时,可以对混合后的图像同样进行频率一致性约束,效果更佳。
  • 与对抗训练结合 :在生成对抗样本时,可以考虑在频率域施加约束,生成更“自然”的扰动,再与频率不变性损失结合,能进一步提升对抗鲁棒性。但这会进一步增加计算成本。

最后,我想分享一点个人体会:傅里叶正则化最吸引我的地方,在于它提供了一种 原理驱动 的、 可解释性较强 的鲁棒性提升思路。它不像对抗训练那样依赖于具体的攻击算法,也不像某些数据增强那样略显随意。它直指模型脆弱性的一个潜在根源——对高频细节的过度敏感,并通过经典的信号处理工具来施加约束。这种将不同领域经典思想交叉应用来解决深度学习问题的方式,往往能带来意想不到的简洁与有效。当你下次为模型的脆弱性头疼时,不妨试试给它加上这个“频率视角”的约束,或许会有惊喜。

更多推荐