首页 > 其他分享 >解锁视觉-文本双编码:CLIP类似模型的多GPU训练

解锁视觉-文本双编码:CLIP类似模型的多GPU训练

时间:2024-11-12 15:19:24浏览次数:3  
标签:768 plt features CLIP 解锁 0% GPU True image

Unlocking Vision-Text Dual-Encoding: Multi-GPU Training of a CLIP-Like Model ROCm Blogs

2024年4月24日,由Sean Song撰写。

在本博客中,我们将构建一个类似CLIP的视觉-文本双编码器模型,并在AMD GPU上使用ROCm对其进行微调,使用COCO数据集。这项工作受到CLIP原理Hugging Face 示例的启发。我们的目标是联合训练一个视觉编码器和一个文本编码器,将图像及其描述的表示投射到相同的嵌入空间中,使文本嵌入位于描述其图像的嵌入附近。在训练过程中,目标是最大化批次内图像和文本对嵌入的相似性,同时最小化错误对的嵌入相似性。该模型通过学习一个多模态嵌入空间来实现这一点。使用对称交叉熵损失优化这些相似性分数。

png

图片来源:从自然语言监督中学习可迁移的视觉模型

视觉-文本双编码器模型可以应用于广泛的下游视觉和语言任务,如图像分类、目标检测、图像描述、视觉问答等。参考我们之前的与CLIP互动博客,了解如何使用预训练的CLIP模型来计算图像和文本之间的相似性,以实现零样本图像分类。
您可以在vision-text-dual-encoding找到本博客中使用的完整代码。 

配置

本演示是在以下设置下创建的。有关全面的支持细节,请参阅 ROCm 文档.

1. 入门

安装所需的库。

!pip install datasets accelerate matplotlib -U

建议从源代码安装 Transformers。

%%bash
git clone https://github.com/huggingface/transformers
cd transformers
pip install -e .

检查系统上 GPU 的可用性。

!rocm-smi
==================== ROCm System Management Interface =========================
========================= Concise Info ===================================
    GPU  Temp (DieEdge)  AvgPwr  SCLK    MCLK     Fan  Perf  PwrCap  VRAM%  GPU%  
    0    39.0c           41.0W   800Mhz  1600Mhz  0%   auto  300.0W    0%   0%    
    1    42.0c           43.0W   800Mhz  1600Mhz  0%   auto  300.0W    0%   0%    
    2    41.0c           43.0W   800Mhz  1600Mhz  0%   auto  300.0W    0%   0%    
    3    41.0c           40.0W   800Mhz  1600Mhz  0%   auto  300.0W    0%   0%    
    4    41.0c           44.0W   800Mhz  1600Mhz  0%   auto  300.0W    0%   0%    
    5    40.0c           42.0W   800Mhz  1600Mhz  0%   auto  300.0W    0%   0%    
    6    37.0c           43.0W   800Mhz  1600Mhz  0%   auto  300.0W    0%   0%    
    7    40.0c           43.0W   800Mhz  1600Mhz  0%   auto  300.0W    0%   0%    
    ====================================================================================
=================== End of ROCm SMI Log ================================

2. 下载 COCO 数据集

以下示例使用了 COCO 数据集 (2017) 通过自定义数据集脚本,要求用户在训练前手动下载 COCO 数据集。下载时间取决于网络速度。根据我们的经验,从终端启动大约需要 7 分钟。从 Jupyter notebook 单元格下载时间会更长。

%%bash
mkdir data
cd data
wget http://images.cocodataset.org/zips/train2017.zip
wget http://images.cocodataset.org/zips/val2017.zip
wget http://images.cocodataset.org/zips/test2017.zip
wget http://images.cocodataset.org/annotations/annotations_trainval2017.zip
wget http://images.cocodataset.org/annotations/image_info_test2017.zip
cd ..

一旦您手动下载了 COCO 数据集,请使用提供的脚本加载它(ydshieh/coc_dataset_script).

import os
import datasets

COCO_DIR = os.path.join(os.getcwd(), "data")
ds = datasets.load_dataset("ydshieh/coco_dataset_script", "2017", data_dir=COCO_DIR)
print(ds["train"])
    Dataset({
        features: ['image_id', 'caption_id', 'caption', 'height', 'width', 'file_name', 'coco_url', 'image_path'],
        num_rows: 591753
    })

每个数据样本由上述八个字段组成。在对比学习的背景下,当图像和字幕来自同一个样本时,它们成对作为正例;当它们不匹配并来自不同样本时,则作为负例。以下是训练数据集中的四个样本。

import matplotlib.pyplot as plt
from PIL import Image
import requests

f, axarr = plt.subplots(2,2, figsize=(8,8))
plt.subplots_adjust(hspace=-0.3, wspace=1.2)
for index in range(4):
    image = Image.open(requests.get(ds["train"][index]['coco_url'], stream=True).raw).resize((128,128)).convert("RGB")
    caption = ds["train"][index]['caption']
    axarr[index//2,index%2].imshow(image)
    axarr[index//2,index%2].title.set_text(caption)
    axarr[index//2,index%2].title.set_size(9) 
    axarr[index//2,index%2].set_xticks([])
    axarr[index//2,index%2].set_yticks([])

png

3. 创建一个类似 CLIP 的视觉-文本双编码器模型

我们使用 VisionTextDualEncoderModel 来构建类似 CLIP 模型的视觉-文本双编码器模型。这个 VisionTextDualEncoderModel 类可以用于初始化一个具有任何预训练视觉自动编码模型作为视觉编码器和预训练语言模型作为文本编码器的视觉-文本双编码器模型。在我们的案例中,我们使用 openai/clip-vit-base-patch32 和 roberta-base 分别作为视觉编码器和文本编码器。

from transformers import (
    VisionTextDualEncoderModel,
    VisionTextDualEncoderProcessor,
    AutoTokenizer,
    AutoImageProcessor
)

model = VisionTextDualEncoderModel.from_vision_text_pretrained(
    "openai/clip-vit-base-patch32", "roberta-base"
)

# 从文本和视觉编码器中获取分词器和图像处理器 
tokenizer = AutoTokenizer.from_pretrained("roberta-base")
image_processor = AutoImageProcessor.from_pretrained("openai/clip-vit-base-patch32")
processor = VisionTextDualEncoderProcessor(image_processor, tokenizer)

# 保存模型和处理器
model.save_pretrained("clip-roberta")
processor.save_pretrained("clip-roberta")
# 检查模型  
print(model)

输出:

    VisionTextDualEncoderModel(
      (vision_model): CLIPVisionModel(
        (vision_model): CLIPVisionTransformer(
          (embeddings): CLIPVisionEmbeddings(
            (patch_embedding): Conv2d(3, 768, kernel_size=(32, 32), stride=(32, 32), bias=False)
            (position_embedding): Embedding(50, 768)
          )
          (pre_layrnorm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          (encoder): CLIPEncoder(
            (layers): ModuleList(
              (0-11): 12 x CLIPEncoderLayer(
                (self_attn): CLIPAttention(
                  (k_proj): Linear(in_features=768, out_features=768, bias=True)
                  (v_proj): Linear(in_features=768, out_features=768, bias=True)
                  (q_proj): Linear(in_features=768, out_features=768, bias=True)
                  (out_proj): Linear(in_features=768, out_features=768, bias=True)
                )
                (layer_norm1): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
                (mlp): CLIPMLP(
                  (activation_fn): QuickGELUActivation()
                  (fc1): Linear(in_features=768, out_features=3072, bias=True)
                  (fc2): Linear(in_features=3072, out_features=768, bias=True)
                )
                (layer_norm2): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
              )
            )
          )
          (post_layernorm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
        )
      )
      (text_model): RobertaModel(
        (embeddings): RobertaEmbeddings(
          (word_embeddings): Embedding(50265, 768, padding_idx=1)
          (position_embeddings): Embedding(514, 768, padding_idx=1)
          (token_type_embeddings): Embedding(1, 768)
          (LayerNorm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          (dropout): Dropout(p=0.1, inplace=False)
        )
        (encoder): RobertaEncoder(
          (layer): ModuleList(
            (0-11): 12 x RobertaLayer(
              (attention): RobertaAttention(
                (self): RobertaSelfAttention(
                  (query): Linear(in_features=768, out_features=768, bias=True)
                  (key): Linear(in_features=768, out_features=768, bias=True)
                  (value): Linear(in_features=768, out_features=768, bias=True)
                  (dropout): Dropout(p=0.1, inplace=False)
                )
                (output): RobertaSelfOutput(
                  (dense): Linear(in_features=768, out_features=768, bias=True)
                  (LayerNorm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
                  (dropout): Dropout(p=0.1, inplace=False)
                )
              )
              (intermediate): RobertaIntermediate(
                (dense): Linear(in_features=768, out_features=3072, bias=True)
                (intermediate_act_fn): GELUActivation()
              )
              (output): RobertaOutput(
                (dense): Linear(in_features=3072, out_features=768, bias=True)
                (LayerNorm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
                (dropout): Dropout(p=0.1, inplace=False)
              )
            )
          )
        )
        (pooler): RobertaPooler(
          (dense): Linear(in_features=768, out_features=768, bias=True)
          (activation): Tanh()
        )
      )
      (visual_projection): Linear(in_features=768, out_features=512, bias=False)
      (text_projection): Linear(in_features=768, out_features=512, bias=False)
    )

文本编码器和视觉编码器都加载了预训练权重。由于投影层是随机初始化的,并且我们没有联合训练这两个编码器,直接使用这个模型来计算图像和文本之间的相似性不会产生令人满意的结果。为了探索这一局限性,让我们进行一个快速测试。为了方便参考,我们将这个构建的模型命名为 clip-roberta

3.1. 为clip-roberta创建测试数据

首先,准备包括六张图片和六个文字描述的测试数据。

urls = [
    "http://images.cocodataset.org/val2017/000000039769.jpg",
    "https://farm3.staticflickr.com/2674/5850229113_4fe05d5265_z.jpg",
    "http://farm6.staticflickr.com/5250/5255601114_e6bd308f74_z.jpg",
    "http://farm4.staticflickr.com/3389/3251688524_b35eaf2acd_z.jpg",
    "https://m.media-amazon.com/images/W/MEDIAX_849526-T1/images/I/51hDgswvNqL._AC_.jpg",
    "http://farm1.staticflickr.com/62/202534637_2dbb3071e5_z.jpg",
]
images = [Image.open(requests.get(url, stream=True).raw) for url in urls]

f, axarr = plt.subplots(2,3)
axarr[0,0].imshow(images[0])
axarr[0,1].imshow(images[1])
axarr[0,2].imshow(images[2])
axarr[1,0].imshow(images[3])
axarr[1,1].imshow(images[4])
axarr[1,2].imshow(images[5])

texts = ["a photo of a cat", "a photo of a dog", "a photo of an airplane", "a photo of a horse", "a photo of a tree", "a photo of a bench"]

png

3.2. 处理图像和文本并将其输入clip-roberta模型

# 推断
inputs = processor(
    text=texts, images=images, return_tensors="pt", padding=True
)
outputs = model(**inputs)
logits_per_image = outputs.logits_per_image  # this is the image-text similarity score
print(logits_per_image)
probs = logits_per_image.softmax(dim=1)  # we can take the softmax to get the label probabilities

输出:

    tensor([[ 0.4270,  0.4314,  0.4330,  0.4296,  0.4369,  0.4647],
            [ 1.2838,  1.2888,  1.2693,  1.2823,  1.2885,  1.2793],
            [ 0.9680,  0.9829,  0.9737,  0.9589,  0.9696,  0.9837],
            [ 0.4647,  0.4655,  0.4695,  0.4623,  0.4461,  0.4612],
            [-0.1244, -0.1225, -0.1151, -0.1315, -0.1097, -0.1017],
            [ 0.2710,  0.2707,  0.2837,  0.2689,  0.2669,  0.2833]],
           grad_fn=<PermuteBackward0>)

3.3. 可视化相似度分数

我们可以使用热图可视化图像和文本之间的相似度分数。分数越高,文本和图像特征越相似。

count = len(texts)
similarity = probs.detach().numpy()
plt.figure(figsize=(5, 9))
plt.imshow(similarity, vmin=0.1, vmax=0.3)
plt.yticks(range(count), texts, fontsize=10)
plt.xticks([])
for i, image in enumerate(images):
    plt.imshow(image, extent=(i - 0.5, i + 0.5, -1.6, -0.6), origin="lower")
for x in range(similarity.shape[1]):
    for y in range(similarity.shape[0]):
        plt.text(x, y, f"{similarity[y, x]:.3f}", ha="center", va="center", size=10)

for side in ["left", "top", "right", "bottom"]:
  plt.gca().spines[side].set_visible(False)

plt.xlim([-0.5, count - 0.5])
plt.ylim([count-0.5, -1.8])

plt.title("Similarity between text and image features", size=10)

png

如前所述,由于投影层是随机初始化的,并且视觉和文本编码器是分开训练的,因此模型当前无法提供准确的结果。它倾向于为每对图像和文本分配相似的分数,而不是准确地分别评估它们。这是预期的结果。下一步涉及对模型进行联合训练,然后使用相同的测试重新评估其性能。 

4. 利用COCO数据集训练模型

你可以很方便地使用 Weights & Biases. 来记录和监控训练过程。要使用Weights & Biases,先安装`wandb`包:

!pip install wandb

接着导入并登录wandb:

import wandb
wandb.login()

# 如果你不想使用wandb,用以下两行代码替代上面的代码
# import os
# os.environ["WANDB_DISABLED"] = "true"

最后,我们准备使用 run_clip.py 脚本训练我们的 clip-roberta 模型。在训练中,我们使用 Hugging Face 的 Trainer 和TrainingArguments ,它们提供了一种便捷的方法来根据需求定制训练过程。我们将模型训练5个epochs,并每500步保存一次检查点。你可以提高这个配置以减少保存所带来的开销。以下是相关的设定:

%%bash
torchrun \
    --nproc_per_node 8 ./run_clip.py \
    --output_dir ./clip-roberta-finetuned \
    --model_name_or_path ./clip-roberta \
    --data_dir $PWD/data \
    --dataset_name ydshieh/coco_dataset_script \
    --dataset_config_name=2017 \
    --image_column image_path \
    --caption_column caption \
    --remove_unused_columns=False \
    --do_train  --do_eval\
    --per_device_train_batch_size="64" \
    --per_device_eval_batch_size="64" \
    --learning_rate="5e-5" --warmup_steps="0" --weight_decay 0.1 \
    --num_train_epochs=5 \
    --overwrite_output_dir

如果你的系统配备了多个GPU,可以通过在`nproc_per_node`中指定可用GPU的数量来加速训练过程(以下训练使用8个GPU)。下表展示了使用不同数量的GPU(AMD Instinct MI210)时的训练运行时间:

Number of GPUs

1

2

4

8

Train Runtime (hours)

7.8

5.2

2.5

1.3

在训练完成后,模型 clip-roberta-finetuned 将会被保存。你可以在训练开始时找到类似的输出。点击提供的链接可以访问并追踪训练指标,例如训练损失。

wandb: ⭐️ 查看项目 https://wandb.ai/your-account/huggingface
wandb:

标签:768,plt,features,CLIP,解锁,0%,GPU,True,image
From: https://blog.csdn.net/eidolon_foot/article/details/143663335

相关文章

  • CUDA开始的GPU编程 - 第六章:thrust库
    第六章:thrust库使用CUDA官方提供的thrust::universal_vector虽然自己实现CudaAllocator很有趣,也帮助我们理解了底层原理。但是既然CUDA官方已经提供了thrust库,那就用他们的好啦。#include<cuda_runtime.h>#include<thrust/universal_vector.h>//trusth库......
  • 模态内重叠优化,简单有效的CLIP微调方法 | BMVC'24 Oral
    来源:晓飞的算法工程笔记公众号,转载请注明出处论文:CLIPAdaptationbyIntra-modalOverlapReduction论文地址:https://arxiv.org/abs/2409.11338创新点提出一种基于轻量级适配的新方法,直接在图像空间中减少CLIP中的模态内重叠(IMO)。新特征与任何利用缓存模型的无训练......
  • GPU云服务器的使用场景和功能有哪些?
    摘要:本文将全面介绍GPU云服务器的特点、优势及应用场景。并针对不同的使用需求,给出典型配置方案示例。包括:深度学习、高性能计算、3D渲染、区块链矿机、游戏直播等多种场景,旨在帮助用户深入理解GPU云服务器的功能,并快速上手应用。一、GPU云服务器简介1、GPU云服务器定义GPU......
  • 孔夫子的数字化宝库:用API解锁在售商品的秘密
    孔夫子的数字化宝库在数字化的时代,孔夫子的智慧不仅仅停留在古籍中,还延伸到了网络空间。想象一下,孔夫子戴着一副老花镜,坐在电脑前,用他那古老的智慧,通过API接口,为我们解锁在售商品的秘密。这不仅是一次技术探险,更是一次幽默的穿越之旅。1.孔夫子旧书网API接口:数字化的竹简孔......
  • 【论文系列】之 ---- CLIP
    CLIP(ContrastiveLanguage-ImagePre-Training)从名字显而易见:语言-图像,预训练,主要用于学习图像该模型的核心思想是使用大量图像和文本的配对数据进行预训练,以学习图像和文本之间的对齐关系CLIP模型有两个模态,一个是文本模态,一个是视觉模态,包括两个主要部分内容该模型的核心思......
  • CLIPFit:不绕弯子,直接微调比提示微调和适配器微调更好 | EMNLP'24
    来源:晓飞的算法工程笔记公众号,转载请注明出处论文:Vision-LanguageModelFine-TuningviaSimpleParameter-EfficientModification论文地址:https://arxiv.org/abs/2409.16718论文代码:https://github.com/minglllli/CLIPFit创新点提出了一种CLIPFit方法以高效地微......
  • ffmpeg Audio Filters adeclip
    Removeclippedsamplesfrominputaudio.Samplesdetectedasclippedarereplacedbyinterpolatedsamplesusingautoregressivemodelling.window,wSetwindowsize,inmilliseconds.Allowedrangeisfrom10to100.Defaultvalueis55milliseconds.Thisse......
  • 使用react+copy-to-clipboard封装双击复制组件
    前言:最近在公司研发后台系统,用户反馈在双击某些信息时希望可以进行复制的操作,多处使用进而封装为组件首先:安装copy-to-clipboardnpmi--savecopy-to-clipboard其次:封装组件importReact,{memo,useCallback}from'react';import{notification}from"antd";......
  • GPU OpenGL 管线
    GPUOpenGL管线主要分为以下几个阶段:顶点数据输入:数据定义与准备:开发者定义要渲染的图形的顶点数据,这些数据包含了每个顶点的位置、颜色、纹理坐标、法线向量等信息。例如,对于一个简单的三角形,需要指定三个顶点的三维坐标以及相关属性。这些数据通常存储在内存中,可以通过数组......
  • 从精准表达到成交绝技,解锁业绩飙升的钥匙
    众多人误以为,销售仅凭口才出众便能驾轻就熟,实则不然。关键在于能否精准表达,字字珠玑,直击客户心扉。销售精英实为卓越的交流大师,其衡量标尺在于能否有效说服并触动顾客。面对形形色色的顾客,我们需灵活调整语言风格,即便是同一商品,也应采用多样化的介绍方式。接下来,让我们一同探索销......