【域适应论文汇总】未完结(2024/3/10)

DANN:Unsupervised Domain Adaptation by Backpropagation (2015)

提出DANN
在这里插入图片描述

TADA:Transferable Attention for Domain Adaptation(2019 AAAI)

提出了TADA

  • 由多个区域级 鉴别器产生的局部注意力来突出可迁移的区域
  • 由单个图像级 鉴别器产生的全局注意力来突出可迁移的图像

通过注意力机制挑选出可迁移的图像以及图像中可以重点迁移的区域。因此作者提出了两个与注意力机制结合的迁移过程:

  • Transferable Local Attention
  • Transferable Global Attention。
    在这里插入图片描述

1 局部注意力迁移:Transferable Local Attention

在这里插入图片描述
TADA与DANN的思想相同,都是通过一个特征提取器 来提取特征,之后会将提取的特征输入到域判别器 。但是TADA不同之处在于它的域判别器有多个,并且每一个域判别器是针对专门的一块区域的。在DANN中域判别器是判断输入的所有特征组合起来是属于源域还是目标域,而在TADA中每个域判别器只需要判断当前的这一块区域是属于源域还是目标域的。通过这种做法,可以将源域的图片拆开,找出最有用的区域信息,并且将不可迁移的源域信息过滤掉,减小负迁移的风险。

2 全局注意力迁移:Transferable Global Attention

在这里插入图片描述

这一步骤和DANN的操作更为相似,作者的目的是找出哪些特征映射更值得迁移,不再将特征映射划分为各个区域,而是关注它的整体。

DAN:Learning transferable features with deep adaptation networks(JMLR 2015)

代码

  • 在DAN中,所有特定于任务的层的隐藏表示都嵌入到一个可复制的内核Hilbert空间中,在这个空间中可以显式匹配不同域分布的平均嵌入。
  • 采用均值嵌入匹配的多核优化选择方法,进一步减小了domain间的差异。
  • DAN可以在有统计保证的情况下学习可转移的特性,并且可以通过核嵌入的无偏估计进行线性扩展。
    在这里插入图片描述

1 多层自适应

基本结构是AlexNet,其中三个全连接都已经和特定任务练习密切,当用于其他任务或数据集时会有较大误差,于是作者提出在最后的三个全连接层都使用MMD进行分布距离约束,从而使得模型具备更强的迁移能力。至于前边的卷积层,前三层提取到的是更为一般的特征,在预训练之后权重固定,4、5两层则要在预训练的基础上进行fine-tune(调整,以致达到最佳效果)

2 多核自适应

分布匹配主要依靠MMD作为分布距离约束来实现,而MMD的效果依赖于核函数的选择,单一核函数的表达能力是有限的,因此作者提出使用多核MMD (MK-MMD) 来作为损失

3 CNN经验误差

在这里插入图片描述- J:交叉熵损失函数

  • θ ( x i a ) θ(x_i^{a}) θ(xia) x i a x_i^{a} xia被分配到 y i a y_i^{a} yia的条件概率

4 优化目标

在这里插入图片描述

  • D s ℓ D^ℓ_s Ds:源域的第 ℓ ℓ 层隐藏表征
  • D t ℓ D^ℓ_t Dt:目标域的第 ℓ ℓ 层隐藏表征
  • d k 2 ( D s ℓ , D t ℓ ) d_k^2(D^ℓ_s, D^ℓ_t) dk2(Ds,Dt):MK-MMD评估值

5 learning Θ Θ Θ

MK-MMD计算内核功能的期望
在这里插入图片描述

6 learning β β β

多层执行MK-MMD匹配

ADDA:Adversarial discriminative domain adaptation(CVPR 2017)

在这里插入图片描述

  • 使用标记的源图像示例预训练源编码器CNN
  • 通过学习目标编码器CNN来执行对抗性适应,使得看到编码源和目标示例的鉴别器无法可靠地预测它们的域标签
  • 在测试过程中,目标图像与目标编码器一起映射到共享特征空间,并由源分类器进行分类

1 报错

  1. RuntimeError: result type Float can’t be cast to the desired output type Long
    acc /= len(data_loader.dataset)
    改成
    acc = acc / len(data_loader.dataset)

  2. 取ViT输出的池化后结果
    pred_tgt = critic(feat_tgt)
    增加 pooler_output
    pred_tgt = critic(feat_tgt.pooler_output)

  3. RuntimeError: output with shape [1, 28, 28] doesn’t match the broadcast shape [3, 28, 28]
    mnist和usps需要从灰度图片转成RGB图片,通道数从1变成3

transform = transforms.Compose([
        transforms.Resize((224, 224)),  # 调整大小为 224x224
        transforms.Grayscale(num_output_channels=3),  #转化成3通道
        transforms.ToTensor(),  # 将图像转换为张量
    ])
  1. IndexError: invalid index of a 0-dim tensor. Use tensor.item() in Python or tensor.item<T>() in C++ to convert a 0-dim tensor to a number
    .data[0]
    改成
    .item()

2 代码

将lenet encoder换成vit

import torch
from transformers import ViTModel, ViTConfig
# 下载 vit-base-patch16-224-in21k 


def load_pretrained_vit_model():
    # Load pre-trained ViT-B/16 model
    model_path = "./pretrained_models/pytorch_model.bin"
    config_path = "./pretrained_models/config.json"
    config = ViTConfig.from_json_file(config_path)
    vit_model = ViTModel.from_pretrained(pretrained_model_name_or_path=None,
                                         config=config,
                                         state_dict=torch.load(model_path),
                                         ignore_mismatched_sizes=True  # 忽略大小不匹配的错误
                                         )
    return vit_model

3 判别器

"""Discriminator model for ADDA."""
from torch import nn
class Discriminator(nn.Module):
    """Discriminator model for source domain."""

    def __init__(self, input_dims, hidden_dims, output_dims):
        """Init discriminator."""
        super(Discriminator, self).__init__()
        print("Shape of input_dims:", input_dims)
        self.restored = False

        self.layer = nn.Sequential(
            nn.Linear(input_dims, hidden_dims),
            nn.ReLU(),
            nn.Linear(hidden_dims, hidden_dims),
            nn.ReLU(),
            nn.Linear(hidden_dims, output_dims)
            ,
            nn.LogSoftmax()
        )

    def forward(self, input):
        """Forward the discriminator."""
        out = self.layer(input)
        return out

4 分类器

"""LeNet model for ADDA."""
import torch
import torch.nn.functional as F
from torch import nn

class LeNetClassifier(nn.Module):
    """LeNet classifier model for ADDA."""
    def __init__(self, input_size):
        """Init LeNet encoder."""
        super(LeNetClassifier, self).__init__()
        self.input_size = input_size

        # Add linear layers to adjust the size of the input feature to fit LeNet
        # vit
        self.fc1 = nn.Linear(input_size, 500)
        # swin
        # self.fc1 = nn.Linear(49 * 1024, 500)

        self.fc2 = nn.Linear(500, 10)

    def forward(self, feat):
        """Forward the LeNet classifier."""
        # vit
        feat = feat.pooler_output

        # swin
        # feat = feat.view(feat.size(0), -1)

        # Apply the linear layers and activation function
        out = F.dropout(F.relu(self.fc1(feat)), training=self.training)
        out = self.fc2(out)
        return out

5 adapt

"""Adversarial adaptation to train target encoder."""
import os
import torch
import torch.optim as optim
from torch import nn
import params
from utils import make_variable


def train_tgt(src_encoder, tgt_encoder, critic,
              src_data_loader, tgt_data_loader,model_type):
    """Train encoder for target domain."""
    ####################
    # 1. setup network #
    ####################

    # set train state for Dropout and BN layers
    tgt_encoder.train()
    critic.train()

    # setup criterion and optimizer
    criterion = nn.CrossEntropyLoss()
    optimizer_tgt = optim.Adam(tgt_encoder.parameters(),
                               lr=params.c_learning_rate,
                               betas=(params.beta1, params.beta2))
    optimizer_critic = optim.Adam(critic.parameters(),
                                  lr=params.d_learning_rate,
                                  betas=(params.beta1, params.beta2))
    len_data_loader = min(len(src_data_loader), len(tgt_data_loader))

    ####################
    # 2. train network #
    ####################

    for epoch in range(params.num_epochs):
        # zip source and target data pair
        data_zip = enumerate(zip(src_data_loader, tgt_data_loader))
        for step, ((images_src, _), (images_tgt, _)) in data_zip:
            ###########################
            # 2.1 train discriminator #
            ###########################
            # make images variable
            images_src = make_variable(images_src.cuda())
            images_tgt = make_variable(images_tgt.cuda())

            # zero gradients for optimizer
            optimizer_critic.zero_grad()

            # extract and concat features
            feat_src = src_encoder(images_src).pooler_output
            feat_tgt = tgt_encoder(images_tgt).pooler_output
            feat_concat = torch.cat((feat_src, feat_tgt), 0)

            # predict on discriminator
            pred_concat = critic(feat_concat.detach())

            # prepare real and fake label
            label_src = make_variable(torch.ones(feat_src.size(0)).long().cuda())
            label_tgt = make_variable(torch.zeros(feat_tgt.size(0)).long().cuda())
            label_concat = torch.cat((label_src, label_tgt), 0)

            # compute loss for critic
            loss_critic = criterion(pred_concat, label_concat)
            loss_critic.backward()

            # optimize critic
            optimizer_critic.step()

            pred_cls = torch.squeeze(pred_concat.max(1)[1])
            
            ############################
            # 2.2 train target encoder #
            ############################

            # zero gradients for optimizer
            optimizer_critic.zero_grad()
            optimizer_tgt.zero_grad()

            # extract and target features
            feat_tgt = tgt_encoder(images_tgt)

            # predict on discriminator
            pred_tgt = critic(feat_tgt.pooler_output)

            # prepare fake labels
            label_tgt = make_variable(torch.ones(feat_tgt.last_hidden_state.size(0)).long().cuda())

            # compute loss for target encoder
            loss_tgt = criterion(pred_tgt, label_tgt)
            loss_tgt.backward()

            # optimize target encoder
            optimizer_tgt.step()

            #######################
            # 2.3 print step info #
            #######################
            if (step + 1) % params.log_step == 0:
                print("Epoch [{}/{}] Step [{}/{}]:"
                      "d_loss={:.5f} g_loss={:.5f} acc={:.5f}"
                      .format(epoch + 1,
                              params.num_epochs,
                              step + 1,
                              len_data_loader,
                              loss_critic.item(),
                              loss_tgt.item(),
                              acc.item()))

        #############################
        # 2.4 save model parameters #
        #############################
    if ((epoch + 1) % params.save_step == 0):
        # 保存模型时加上特征提取器的标识符
        if model_type == "vit":
            model_name = "ADDA-target-encoder-ViT-{}.pt".format(epoch + 1)
        elif model_type == "mobilevit":
            model_name = "ADDA-target-encoder-MobileViT-{}.pt".format(epoch + 1)
        elif model_type == "swin":
            model_name = "ADDA-target-encoder-Swin-{}.pt".format(epoch + 1)

        torch.save(tgt_encoder.state_dict(), os.path.join(
            params.model_root,
            model_name))

    # 保存最终模型时也加上特征提取器的标识符
    if model_type == "vit":
        final_model_name = "ADDA-target-encoder-ViT-final.pt"
    elif model_type == "mobilevit":
        final_model_name = "ADDA-target-encoder-MobileViT-final.pt"
    elif model_type == "swin":
        final_model_name = "ADDA-target-encoder-Swin-final.pt"

    torch.save(tgt_encoder.state_dict(), os.path.join(
        params.model_root,
        final_model_name))
    return tgt_encoder

MCD:Maximum classifier discrepancy for unsupervised domain adaptation(CVPR 2018)

  • 已有的方法仅尝试去区分特征为源域/目标域
  • 没有考虑task-specific决策边界
  • 训练好的生成器G会产生近类别边界模糊特征

1 Introduction

最大分类器差异的领域自适应

  • 通过最大化分类器之间的差异来学习具有相似特征表示的源域和目标域之间的映射
  • 引入两个独立的分类器F1、F2

在这里插入图片描述

  • 两个分类器试图使目标样本上的预测结果尽可能不同
  • 特征提取器的目标是生成的特征表示尽可能地减小这种差异

2 Related Work

3 Method

在这里插入图片描述

A阶段

训练出两个不同的分类器F1、F2 、特征提取器G ,训练分类器和生成器对源样本进行正确的分类。Loss即为求source domain上的分类误差。
在这里插入图片描述

B阶段

固定特征提取器G ,训练两个不同的分类器 F1和F2 ,使得它们的差异最大。如果没有这一步,两个分类器可能会变得非常相似,就不能很好的区别靠近边界的目标样本。损失函数为 L 1 L_1 L1两个分类器概率输出之差的绝对值):
在这里插入图片描述

C阶段

固定两个分类器F1、F2,优化特征生成器 G ,使得生成的特征对两个分类器效果尽可能一致

4 Experiment

  • 分类实验
    在这里插入图片描述

MDD:Bridging theory and algorithm for domain adaptation

CDAN:Conditional Adversarial Domain Adaptation(Neural 2018)

条件生成对抗网络,在GAN基础上做的一种改进,通过给原始的GAN的生成器和判别器添加额外的条件信息,实现条件生成模型

复现代码:https://www.cnblogs.com/BlairGrowing/p/17099742.html

提出一个条件对抗性域适应方法(CDAN),对分类器预测中所传递的判别信息建立了对抗性适应模型。条件域对抗性网络(CDAN)采用了两种新的条件调节策略:

  • 多线性条件调节,通过捕获特征表示与分类器预测之间的交叉方差来提高分类器的识别率
  • 熵条件调节,通过控制分类器预测的不确定性来保证分类器的可移植性

MCC:Moment Matching for Multi-Source Domain Adaptation(ICCV 2019)

  • ICCV 2019
  • 这篇论文介绍了一种解决多源域自适应问题的方法,称为Moment Matching for Multi-Source Domain Adaptation( M 3 S D A M^3SDA M3SDA
  • 传统的无监督域自适应UDA方法假设训练数据来自单一域,而实际情况往往是训练数据来自多个源头

主要贡献

  • 作者收集并标注了迄今为止最大的UDA数据集,称为DomainNet,包含了六个不同的域,大约有60万张图像,分布在345个类别
  • 论文提出了一种新的深度学习方法M3SDA,通过动态地对齐特征分布的矩来将多个标记源域中学到的知识转移到一个未标记的目标域
  • 论文提供了针对矩匹配方法的新的理论洞察,包括单一源域自适应和源域自适应

1 Introduction

2 Related

3 The DomainNet dataset

1 背景
  • 深度模型需要大量训练数据的事实,并且提到现有的视觉域自适应数据集要么规模较小,要么类别数量有限
  • 为了解决这一问题,作者收集了目前为止规模最大的域自适应数据集,即DomainNet
2 DomainNet
  • DomainNet包含六个不同的域,每个域都包含了345个常见物体的类别。这些域包括Clipart、Infograph、Painting、Quickdraw、Real和Sketch。
  • 每个域都有不同的特点
    • Clipart(剪贴画图像)
    • Infograph(信息图像)
    • Painting(艺术画作)
    • Quickdraw(“Quick Draw!”游戏中的玩家绘制的图像)
    • Real(真实照片和世界图像)
    • Sketch(特定物体的草图)
3 数据收集方法
  • Clipart、Infograph、Painting、Real和Sketch域的图像是通过在不同的图像搜索引擎中结合类别名称和域名称进行搜索来收集的
  • 为了清理数据集中的异常值,作者雇佣了20名注释员手动筛选异常值
  • 为了控制注释质量,每个图像分配了两名注释员,并且只有两名注释员都同意的图像才被接受
  • 筛选过程结束后,从网络爬取的120万张图像中保留了423.5k张图像
4 数据统计

数据集中各个域的平均每个类别的图像数量:

  • Clipart和Infograph约为150张
  • Painting和Sketch约为220张
  • Real约为510张
5 Quickdraw域数据收集方法
  • Quickdraw域的图像是直接从https://quickdraw.withgoogle.com/下载
  • 原始数据是一系列具有时间信息的离散点
  • 为了获得完整的绘图,作者使用了B-spline算法将每个击打中的所有点连接起来
  • 每个类别选择了500张图像,共形成Quickdraw域,总共包含了172.5k张图像

4 Moment Matching for Multi-Source DA

1 数据集

源领域的集合DS = {D1, D2, …, DN},其中每个源领域Di都是带标签的数据集。此外,还有一个未标记的目标领域DT

2 问题描述
  • 有多个带标签的源域数据
  • 一个未标记的目标域数据
  • 通过多个源领域的信息来适应目标领域的数据分布
3 Moment Distance
  • 衡量源领域集合DS和目标领域DT之间的差异
  • 通过对两个领域之间的特征分布的期望值进行比较来计算的

Moment Distance:源领域和目标领域之间的矩的平方差的总和
在这里插入图片描述

  • 第一项(关注单个领域):对于每个源领域和每个特征,计算其在源领域和目标领域上期望值的差异,并取平方。然后对所有源领域和特征进行求和,除以源领域的数量N,取平均值

  • 第二项(关注不同领域之间):

    • 1 N 2 \frac{1}{N^2} N21:表示对不同源领域组合的求和部分除以源领域的数量的平方,以取得平均
    • ∑ i = 1 N ∑ j = i + 1 N \sum_{i=1}^{N} \sum_{j=i+1}^{N} i=1Nj=i+1N:对不同的源领域组合进行求和
    • ∑ k = 1 X ( E ( X k i ) − E ( X k j ) ) 2 \sum_{k=1}^{X} (E(X_{ki}) - E(X_{kj}))^2 k=1X(E(Xki)E(Xkj))2:对于每个源领域组合和每个特征,计算其在不同源领域上期望值的差异,并取平方。然后对所有不同源领域组合和特征进行求和
4 M 3 S D A M^3SDA M3SDA

在这里插入图片描述

通过训练特征提取器G和分类器集合C,使得在源领域中的分类任务得到很好的执行,并且在共同的潜在特征空间中使源领域和目标领域之间的分布差异最小化。这个模型的设计旨在通过Moment Matching的方式实现多源领域自适应,以提高模型在目标领域上的性能,其中,包含以下组件:

  • 特征提取器G

  • Moment Matching组件

  • 分类器集合C:N个分类器,被表示为C = {C1, C2, …, CN},用于对源领域中的数据进行分类
    在这里插入图片描述

  • 目标函数=源域分类损失 + M D 2 MD^2 MD2

5 M 3 S D A − β M^3SDA-β M3SDAβ

M 3 S D A M^3SDA M3SDA的一个变种,同时对齐 p ( y ∣ x ) p(y|x) p(yx) p ( x ) p(x) p(x)

  • 训练特征提取器 G 和两个分类器(C 和 C’),分类多源领域的样本
  • 固定特征提取器 G ,对每个源领域的分类器对进行训练
  • 尽可能增大分类器C1 和 C1’在目标领域上的差异
  • 分类器输出的 L1 距离来度量两个分类器之间的差异
    在这里插入图片描述
  • 在固定分类器C 、C’,训练特征提取器 G 来最小化每一对分类器在目标领域上的差异
    在这里插入图片描述
  • 这三个训练步骤会周期性地进行,直到整个网络收敛
  • M 3 S D A − β M^3SDA-β M3SDAβ模型可以更好地对齐源领域和目标领域的特征分布以及类别条件概率分布
6 Ensemble Schema

在测试阶段,我们使用特征生成器和N个分类器对目标领域的测试数据进行处理,作者提出了两种组合分类器输出的方案。

  • 平均分类器输出:简单地对所有分类器的输出进行平均,标记为 M 3 S D A ∗ M^3SDA^* M3SDA
  • 加权平均分类器输出:每个分类器分配一个权重
    在这里插入图片描述

DAPL:Domain Adaptation via Prompt Learning(DA+prompt)(arXiv 2022)

代码:https://github.com/LeapLabTHU/DAPrompt
使用预训练的视觉语言模型,优化较少的参数,将信息嵌入到提示中,每个域中共享。
只有当图像和文本的领域和类别分别匹配的时候,他们才形成一对正例。

特征提取器优化

  • ViT
    已部署,测试中

  • Swin Transformer:基于 Transformer 结构的新型模型,计算复杂度可能更高一些(对性能要求较高)

  • MobileViT:CNN的轻量高效,transformer的自注意力机制和全局视野,在速度和内存消耗方面优秀(2021)
    文章:MobileViT: Light-Weight, General-Purpose, and Mobile-Friendly Vision Transformer

  • ConvNeXt:结合了CNN和 Transformer 的模型(2022)
    文章:A ConvNet for the 2020s
    ConvNeXt用100多行代码就能搭建完成,相比Swin Transformer拥有更简单,更快的推理速度以及更高的准确率

  • EfficientNetV2:Google 提出的一系列高效的卷积神经网络,通过使用复合缩放方法和网络深度调整策略,实现了在不同任务上的良好性能和高效计算(对移动设备友好)(2021)

  • MobileNetV3:针对移动设备的轻量级卷积神经网络,有更快的推理速度和更低的内存消耗(对移动设备友好)(2019)

PyTorch Hub 下载模型
https://huggingface.co/models

  • 11
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值