当前位置: 首页 > 科技观察

Imageclassificationwithfew-shotlearningusingPyTorch

时间:2023-03-13 23:59:40 科技观察

近年来,基于深度学习的模型在目标检测和图像识别等任务中表现良好。具有挑战性的图像分类数据集,如ImageNet,包含1000种不同的对象分类,现在有一些模型的性能超过了人类水平。但是这些模型依赖于监督训练过程,它们在很大程度上受到标记训练数据可用性的影响,并且模型可以检测的类别仅限于它们接受训练的类别。由于在训练期间没有足够的标记图像用于所有类别,因此这些模型在现实世界中可能不太有用。我们希望模型能够识别它在训练期间没有见过的类,因为几乎不可能训练所有潜在物体的图像。我们将从几个样本中学习的问题称为Few-Shot学习。什么是小样本学习?小样本学习是机器学习的一个子领域。它涉及仅使用少量训练样本和监督数据对新数据进行分类。只需少量的训练样本,我们创建的模型就可以表现得相当不错。考虑以下场景:在医学领域,对于一些不常见的疾病,可能没有足够的X射线图像来进行训练。对于这样的场景,构建一个few-shot学习分类器是完美的解决方案。一般来说,研究人员确定了四种类型:N-ShotLearning(NSL)Few-ShotLearning(FSL)One-ShotLearning(OSL)Zero-ShotLearning(ZSL)当我们谈论FSL时,我们通常指的是N-way-K-Shot分类。N代表类数,K代表每个类要训练的样本数。因此,N-ShotLearning被视为比所有其他概念更广泛的概念。Few-Shot、One-Shot和Zero-Shot可以说是NSL的子领域。而零样本学习旨在在没有任何训练示例的情况下对看不见的类进行分类。在One-ShotLearning中,每个班级只有一个样本。Few-Shot每个类有2到5个样本,这意味着Few-Shot是One-ShotLearning的更灵活版本。FewShotLearningMethods一般而言,在解决FewShotLearning问题时应考虑两种方法:Data-LevelApproach(DLA)这种策略非常简单,如果没有足够的数据来创建实体模型并防止欠拟合和过拟合,然后只需添加更多数据。正因为如此,许多FSL问题可以通过利用来自更大底层数据集的更多数据来解决。基础数据集的一个显着特征是它缺少构成我们对Few-Shot挑战的支持集的类。例如,如果我们要对某只鸟进行分类,底层数据集可能包含许多其他鸟的图片。Parameter-LevelApproach(PLA)从参数级别的角度来看,Few-ShotLearning样本相对容易过拟合,因为它们通常具有较大的高维空间。限制参数空间、使用正则化和使用适当的损失函数将对此有所帮助。模型会泛化少量训练样本。可以通过将模型引导到宽参数空间来提高性能。由于缺乏训练数据,正常的优化方法可能无法产生准确的结果。由于上述原因,训练我们的模型以找到通过参数空间的最佳路径会产生最佳预测。这种方法称为元学习。小样本学习图像分类算法常见的小样本学习方法有四种:Model-independentmeta-learningModel-AgnosticMeta-Learning基于梯度的元学习(GBML)原理是MAML的基础。在GBML中,元学习器通过基础模型训练获得先验经验,并学习所有任务表示的共享特征。每次有新任务要学习时,元学习器都会使用其现有经验和新任务提供的最少数量的新训练数据进行微调。一般来说,如果我们随机初始化参数并多次更新算法,算法将不会收敛到良好的性能。MAML试图解决这个问题。MAML仅需几个梯度步骤就可以可靠地初始化元参数学习器,并保证不会出现过拟合,因此它可以针对新任务进行最佳且快速的学习。步骤如下:元学习器在每一集开始时创建自己的副本C,C在这一集上训练(在基础模型的帮助下),C对查询集进行预测,并从这些predictions计算出的损失用于更新C,它一直持续到所有多样性集的训练完成。这种技术的最大优点是它被认为独立于元学习算法的选择。因此,MAML方法被广泛应用于许多需要快速自适应的机器学习算法,尤其是深度神经网络。MatchingNetworks第一个由MatchingNetworks创建的用于解决FSL问题的度量学习方法是MatchingNetwork(MN)。当使用匹配网络方法解决Few-ShotLearning问题时,需要一个大的基础数据集。.将此数据集拆分为子集后,对于每个子集,匹配网络如下进行:来自支持集和查询集的每个图像被馈送到CNN,该CNN输出查询图像的特征嵌入使用支持集训练的模型获得余弦嵌入特征的距离,分类结果的交叉熵损失通过softmax分类,特征嵌入通过CNN反向传播更新。匹配网络可以学习以这种方式构建图像嵌入。MNs能够在没有任何特殊类别先验知识的情况下使用这种方法对照片进行分类。他只是比较类的几个实例。由于类别因集合而异,匹配网络计算对类别区分很重要的图像属性(特征)。而在使用标准分类时,该算法会选择每个类别独有的特征。PrototypicalNetworksPrototypicalNetworks类似于匹配网络的是原型网络(PN)。它通过一些小的改动提高了算法的性能。PN取得了比MN更好的结果,但它们的训练过程本质上是相同的,只是比较来自支持集的一些查询图像嵌入,但原型网络提供了不同的策略。我们需要在PN中创建类的原型:通过对类中图像的嵌入进行平均来创建类的嵌入。然后只有这些类原型用于比较查询图像嵌入。当用于一次性学习问题时,它与匹配网络相当。RelationalNetworkRelationalNetwork可以说继承了上述所有方法的研究成果。RN基于PN的思想但包含重大的算法改进。该方法使用的距离函数是可学习的,而不是像以前的研究那样预先定义它。关系模块位于嵌入模块之上,嵌入模块是根据输入图像计算嵌入和类原型的部分。可训练的关系模块(距离函数)将查询图像的嵌入和每个类的原型作为输入,并输出每个类匹配的关系分数。关系分数通过Softmax得到预测。使用Open-AIClip进行零样本学习CLIP(对比语言-图像预训练)是一种在各种(图像、文本)对上训练的神经网络。它预测给定图像的最相关文本片段,而无需针对任务直接优化(类似于GPT-2和3的零样本功能)。CLIP可以在ImageNet“零样本”上达到原始ResNet50的性能,并且不需要使用任何带标签的例子。它克服了计算机视觉中的几个主要挑战。下面我们使用Pytorch来实现一个简单的分类模型。导入包!pip安装ftfy正则表达式tqdm!pipinstallgit+https://github.com/openai/CLIP.gitimportnumpyasnpimporttorchfrompkg_resourcesimportpackagingprint("Torchversion:",torch.__version__)loadmodelimportclipclip.available_models()#它将列出可用CLIP模型的名称模型,预处理=clip.load("ViT-B/32")model.cuda().eval()context_lengthvocab_size=model.vocab_sizeprint("模型参数:",f"{np.sum([int(np.prod(p.shape))forpinmodel.parameters()]):,}")print("Inputresolution:",input_resolution)print("Contextlength:",context_length)print("Vocabsize:",vocab_size)图像预处理我们将8张样本图像及其文本描述输入到模型中,比较相应的特征相似度之间。分词器不区分大小写,我们可以自由提供任何合适的文本描述。importosimportskimageimportIPython.displayimportmatplotlib.pyplotaspltfromPILimportImageimportnumpyasnpfromcollectionsimportOrderedDictimporttorch%matplotlibinline%configInlineBackend.figure_format='retina'#skimage中要使用的图像及其文本描述descriptions={"page":"一页关于分割的文字","chelsea":"一张虎斑猫的面部照片","astronaut":"一张拿着美国国旗的宇航员的肖像","rocket":“站在发射台上的火箭”,“motorcycle_right”:“站在车库里的红色摩托车”,“camera”:“一个人在三脚架上看着相机”,“horse”:“黑白照片”马的轮廓”,“咖啡”:“碟子上的一杯咖啡”}original_images=[]images=[]texts=[]plt.figure(figsize=(16,5))forfilenamein[filenameforos.listdir(skimage.data_dir)中的文件名iffilename.endswith(".png")orfilename.endswith(".jpg")]:name=os.path.splitext(filename)[0]如果名称不在描述中:继续image=Image.open(os.path.join(skimage.data_dir,filename)).convert("RGB")plt.subplot(2,4,len(图像)+1)plt.imshow(图像)plt.title(f"{文件名}\n{描述[名称]}")plt.xticks([])plt.yticks([])original_images.append(image)images.append(preprocess(image))texts.append(descriptions[name])plt.tight_layout()结果可视化如下:我们规范化图像,标记化每个文本输入,并运行模型图像和文本特征的前向传播image_input=torch.tensor(np.stack(images)).cuda()text_tokens=clip.tokenize(["Thisis"+descfordescintexts]).cuda()withtorch.no_grad():我们将展示归一化,并计算每对的点积,进行余弦相似度计算image_features/=image_features.norm(dim=-1,keepdim=True)text_features/=text_features.norm(dim=-1,keepdim=True)similarity=text_features.cpu().numpy()@image_features.cpu().numpy().Tcount=len(descriptions)plt.figure(figsize=(20,14))plt.imshow(similarity,vmin=0.1,vmax=0.3)#plt.colorbar()plt.yticks(range(count),texts,fontsize=18)plt.xticks([])fori,imageinenumerate(original_images):plt.imshow(image,extent=(i-0.5,i+0.5,-1.6,-0.6),origin="lower")forxinrange(similarity.shape[1]):foryinrange(similarity.shape[0]):plt.text(x,y,f"{similarity[y,x]:.2f}",ha="center",va="center",size=12)forsidein["left","top","right","底部"]:plt.gca().spines[side].set_visible(False)plt.xlim([-0.5,计数-0.5])plt.ylim([count+0.5,-2])plt.title("文本和图像特征之间的余弦相似度",size=20)零样的图像分类fromtorchvision.datasetsimportCIFAR100cifar100=CIFAR100(os.path.expanduser("~/.cache"),transform=preprocess,download=True)text_descriptions=[f"这是一张{label}的照片"forlabelincifar100.classes]text_tokens=clip.tokenize(text_descriptions).cuda()与torch.no_grad():text_features=model.encode_text(text_tokens).float()text_features/=text_features.norm(dim=-1,keepdim=True)text_probs=(100.0*image_features@text_features.T).softmax(dim=-1)top_probs,top_labels=text_probs.cpu().topk(5,dim=-1)plt.figure(figsize=(16,16))fori,枚举中的图像(original_images):plt.subplot(4,4,2*i+1)plt.imshow(image)plt.axis("off")plt.subplot(4,4,2*i+2)y=np.arange(top_probs.shape[-1])plt.grid()plt.barh(y,top_probs[i])plt.gca().invert_yaxis()plt.gca().set_axisbelow(True)plt.yticks(y,[cifar100.classes[index]forindexintop_labels[i].numpy()])plt.xlabel("probability")plt.subplots_adjust(wspace=0.5)plt.show()可以看出分类的效果还是很好的