ICLR 2023#Learning to Compose Soft Prompts for Compositional Zero-Shot Learning

组合零样本学习(CZSL)中Soft Prompt相关工作汇总(一)

ICLR 2023#Learning to Compose Soft Prompts for Compositional Zero-Shot Learning

补充:https://zhuanlan.zhihu.com/p/532153343
————提示学习soft prompt浅尝
https://zhuanlan.zhihu.com/p/493489688
————神器CLIP:连接文本和图像,打造可迁移的视觉模型

Introduction

背景:VLMs有一个灵活的文本编码器,可以将任意类表示为自然语言提示,但它们(例如CLIP)在zero-shot基准测试数据集上的性能常常低于特定于任务的体系结构→因为CLIP对从网络上抓取的数据进行的预训练没有足够的对属性的监督以及如何将它们和不同的对象进行组合。
为了提升组合零样本学习能力(即“预测unseen属性-对象组合的任务”),本文提出了一种参数高效的学习技术——CSP(Compositional Soft Promting,组合软提示)。CSP将定义类的属性和对象视为词汇表中的可学习标记。在训练过程中,词汇表被调优以识别以多种方式组成符号的类(例如,老猫和白猫);在测试时,将学习到的属性对象词汇重新组合,以识别新的类(即“组合现有的分类器来构建新的分类器”)
现有czsl方法:将属性和对象映射到预训练的词嵌入,并使用预训练的图像编码器backbone来联合对齐图像和 属性-对象文本表示,以学习组合性;
存在的问题:1.单词嵌入和图像编码器的预训练是彼此分离的,即这些方法从头开始学习对齐图像和文本表示;
2.这些特定于任务的体系结构在灵活性方面也受到限制。在让这些方法适应具有多属性和对象(如小毛猫或老白虎)的高阶组合时,就需要修改原始架构→说明超出原始长度的泛化能力是“组合性”的关键

Related work
prompt

prompt是语言和视觉领域的焦点,在大范围的任务重有助于zero-shot和few-shot学习;discrete prompt通常是手写文本输入,为大型预训练模型(如CLIP、GPT-3)等提供指导方针,无需更新模型参数进行推理(?),但是耗时严重;
提出soft prompt作为替代,可以在反向传播过程中学习部分的prompt而不用微调整个模型,在效果比手工要好的soft prompt工作中,它是单个输入连接到整个任务的所有输入;我们从多个组合中学习每个基本概念的标记,并以新的方式重新组合它们,以表示unseen的类
其他工作应用:few-shot目标分类;VQA;视频理解,但都是整个数据集只有单个prompt;
参考和22年Ge的工作类似,区别:1.我们的将类标签分解成多个部分,而不是将提示分割成与领域相关的粒度,比如与领域无关的上下文、领域特定的上下文和类标签;2.关注zero-shot学习,不能访问测试集中不可见类的标记示例,而它们在训练期间可以访问所有的测试类

Parameter-efficient learning

(补充:Parameter-efficient fine-tuning的三个特性:
1.在微调过程中预训练参数是固定的,只需微调少量额外的参数,可以达到与全量微调相当接近的性能,不同任务只需要切换任务相关的那少部分参数;
2.PEFT在训练数据量小的场景下,有时性能可以超过全量微调,预训练知识不容易遗忘,泛化能力强;
3.PEFT在方法上是模型无关的,可以广泛应用于多种模态和模型(另外的图像识别、生成任务))
https://zhuanlan.zhihu.com/p/636326003
————大模型的领域适配 —— Parameter-Efficient Fine-Tuning (PEFT)
https://zhuanlan.zhihu.com/p/620618701
————预训练大语言模型的三种微调技术总结:fine-tuning、parameter-efficient fine-tuning和prompt-tuning的介绍和对比
在这里插入图片描述图一.fine-tuning技术应用(图源上述链接)

Preliminaries

属性集A、对象集O,样本标签Y=A×O;
训练阶段:已知Sseen={(x1,y1),…,(xn,yn)}来学习有区分性的模型f:X → Yseen;
推理阶段:想要模型可以预测测试集中seen+unseen的组合,f:X → Ytest 1).封闭世界中,Ytest = Yseen ∪ Yunseen;2).开放世界中,考虑属性、对象的所有组合:Ytest = Y,Yunseen = Y - Yseen

CSP训练设置
CSP的训练设置:带有属性和对象词汇的prompts(A photo of [ATTRIBUTE][OBJECT])通过文本编码器来获得文本的表征(representation),图像通过图像编码器获得图像表征;之后计算所有prompts和图像之间的余弦相似度后计算交叉损失熵;最后重传损失并更新属性-对象词汇权重(weights)

Compositional Soft Prompting

Motivation:改进vlm(如CLIP)在组合概化方面的表现,因为它们似乎不如当前最先进的方法。这可能是因为CLIP对从网络爬来的数据进行的预训练没有提供足够的属性监督以及它们如何与不同对象结合→目标是教vlm(如CLIP)如何更好地组合原始概念
把它看做一个词汇学习问题,因为它是参数有效(parameter-efficient)的,并提供了一种自然的方法来组成新类
Prompt construction
CSP把用来定义类的属性和对象视为可学习的词汇表标记,并根据多个prompt组合对它们进行调优;我们把每个原语概念都表示成VLM词汇表中一个新的、辅助性的token,每表示一类就用"a photo of [attribute][object]"
Training:直接贴汇报用的ppt图了
在这里插入图片描述
Inference
在推理过程中,在提示中重新组合经过调整的属性和对象词汇表;
以在训练过程中相同的方式将经过调整的θ与(属性、对象)对组合在候选提示中‘’在封闭世界和开放世界设置中,我们只使用提示符中经过调整的参数替换属性和对象。最后,计算最可能的属性和对象对:
在这里插入图片描述
后续实验部分分析了csp在开放世界和封闭世界中的效果,在不同衡量标准下的效果,还有baseline和benchmark结果的对比等等,本文是组合零样本学习czsl中soft prompt相关工作的基础工作,提出的创新点主要是将提高下游任务效果的方向转移到文本端来,因此提出了对clip的prompt工程进行改进而提出了soft-prompt,故在实验效果不做赘述。之后的几篇文章讲解都以csp为基础进行后续的工作,见专栏文章…
**因为博主(hdu研一在读)也刚开始接触多模态学习领域的工作不久,因此有相关科研领域和方向的读者大大有兴趣可以和我相互交流学习(菜鸡互啄),qq:1297995979

  • 15
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Few-shot learning是一种机器学习技术,用于在数据集较小的情况下进行分类任务。它可以通过在训练过程中使用少量的样本来学习新的类别,而不是需要大量的数据来训练模型。以下是Few-shot learning的代码详解: 1. 数据集准备 Few-shot learning的数据集通常包含许多小的类别,每个类别只有几个样本。因此,我们需要将数据集分成训练集和测试集,并将每个类别的样本分成训练样本和测试样本。在这里,我们使用Omniglot数据集作为示例。 ```python from torch.utils.data import Dataset, DataLoader from torchvision import transforms from PIL import Image import os class OmniglotDataset(Dataset): def __init__(self, data_dir, transform=None): self.data_dir = data_dir self.transform = transform self.samples = [] self.class_to_idx = {} self.idx_to_class = {} for alphabet in os.listdir(data_dir): alphabet_path = os.path.join(data_dir, alphabet) if not os.path.isdir(alphabet_path): continue class_idx = len(self.class_to_idx) self.class_to_idx[alphabet] = class_idx self.idx_to_class[class_idx] = alphabet for character in os.listdir(alphabet_path): character_path = os.path.join(alphabet_path, character) if not os.path.isdir(character_path): continue for sample in os.listdir(character_path): sample_path = os.path.join(character_path, sample) if not os.path.isfile(sample_path): continue self.samples.append((sample_path, class_idx)) def __len__(self): return len(self.samples) def __getitem__(self, idx): sample_path, class_idx = self.samples[idx] image = Image.open(sample_path).convert('L') if self.transform is not None: image = self.transform(image) return image, class_idx train_transform = transforms.Compose([ transforms.RandomAffine(degrees=15, translate=(.1, .1), scale=(.8, 1.2)), transforms.ToTensor(), transforms.Normalize(mean=[.5], std=[.5]) ]) test_transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean=[.5], std=[.5]) ]) train_dataset = OmniglotDataset('omniglot/images_background', transform=train_transform) test_dataset = OmniglotDataset('omniglot/images_evaluation', transform=test_transform) train_dataloader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4) test_dataloader = DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=4) ``` 2. 模型定义 Few-shot learning的模型通常由两部分组成:特征提取器和分类器。特征提取器用于从输入图像中提取特征,而分类器用于将这些特征映射到类别空间。在这里,我们使用一个简单的卷积神经网络作为特征提取器,并使用一个全连接层作为分类器。 ```python import torch.nn as nn class ConvNet(nn.Module): def __init__(self): super(ConvNet, self).__init__() self.conv_layers = nn.Sequential( nn.Conv2d(1, 64, kernel_size=3, padding=1), nn.BatchNorm2d(64), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2), nn.Conv2d(64, 128, kernel_size=3, padding=1), nn.BatchNorm2d(128), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2), nn.Conv2d(128, 256, kernel_size=3, padding=1), nn.BatchNorm2d(256), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2), nn.Conv2d(256, 512, kernel_size=3, padding=1), nn.BatchNorm2d(512), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2), ) self.fc_layers = nn.Sequential( nn.Linear(512, 256), nn.BatchNorm1d(256), nn.ReLU(inplace=True), nn.Linear(256, 128), nn.BatchNorm1d(128), nn.ReLU(inplace=True), nn.Linear(128, 64), nn.BatchNorm1d(64), nn.ReLU(inplace=True), nn.Linear(64, 5) ) def forward(self, x): x = self.conv_layers(x) x = x.view(x.size(), -1) x = self.fc_layers(x) return x ``` 3. 训练模型 在训练过程中,我们使用一些训练样本来学习新的类别,并使用另一些样本来评估模型的性能。在每个训练步骤中,我们从训练集中随机选择一些类别和样本,并使用它们来训练模型。然后,我们使用测试集中的样本来评估模型的性能。 ```python import torch.optim as optim import torch.nn.functional as F device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') model = ConvNet().to(device) optimizer = optim.Adam(model.parameters(), lr=1e-3) def train_step(model, optimizer, x, y): model.train() optimizer.zero_grad() x = x.to(device) y = y.to(device) logits = model(x) loss = F.cross_entropy(logits, y) loss.backward() optimizer.step() return loss.item() def test_step(model, x, y): model.eval() x = x.to(device) y = y.to(device) with torch.no_grad(): logits = model(x) preds = logits.argmax(dim=1) acc = (preds == y).float().mean().item() return acc for epoch in range(10): train_loss = . train_acc = . for i, (x, y) in enumerate(train_dataloader): loss = train_step(model, optimizer, x, y) train_loss += loss train_acc += test_step(model, x, y) train_loss /= len(train_dataloader) train_acc /= len(train_dataloader) test_acc = . for i, (x, y) in enumerate(test_dataloader): test_acc += test_step(model, x, y) test_acc /= len(test_dataloader) print(f'Epoch {epoch+1}: Train Loss={train_loss:.4f}, Train Acc={train_acc:.4f}, Test Acc={test_acc:.4f}') ``` 在训练过程中,我们可以看到模型的训练损失和准确率以及测试准确率。在这个例子中,我们使用了5-way 1-shot的任务,即每个任务有5个类别,每个类别只有1个样本。在10个epoch的训练后,我们得到了约80%的测试准确率,这表明模型可以在少量的样本上进行分类任务。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值