教程类:在超算互联网(SCNet)平台轻松玩转多模态大模型LLaVA的推理、预训练与微调。

   日期:2024-12-25    作者:n9imc 移动:http://oml01z.riyuangf.com/mobile/quote/12642.html

本实验在SCNet(超算互联网)平台进行。SCNet国家超算互联网可将全国众多超算中心连接起来,构建一体化的超算算力网络和服务平台。目前已有超过200家应用、数据、模型等服务商入驻国家超算互联网,并提供超过3200款商品。这些商品覆盖科学计算、工业仿真、人工智能模型训练等前沿数字化创新领域,满足经济社会发展对先进计算服务的需求。国家超算互联网正式上线将有助于缓解目前算力供需矛盾,为数字中国建设、数字经济发展等提供坚实支撑。

教程类:在超算互联网(SCNet)平台轻松玩转多模态大模型LLaVA的推理、预训练与微调。


本实验在超算互联网提供的算力上进行。

我们首先进入官网超算互联网 (scnet.cn),注册账户。

找到“计算资源”,申请资源“异构加速卡AI 显存64GB PCIE”

选择加速卡与镜像,创建Notebook

官方镜像基本上提供了所有与AI相关基本软件,如:深度学习框架Pytorch,deepspeed、Miniconda等,免去了配置环境的步骤,实现开机即用。如需使用其他AI软件,可以从光合开发者平台中下载DCU移植版的软件:cancon.hpccube.com

DCU加速卡简介

DCU(Deeplearning Computing Unit)是新一代国产AI加速卡,是基于通用GPGPU架构设计,性能可对标NVIDIA类产品,具有应用生态完善,迁移成本低的特点,基于PyTorch、TensorFlow等主流框架实现的代码无需转码,可直接使用,是构建AI算力的不二之选,具有较高性价比。

DCU的兼容性很好、生态完善,可以轻松部署运行主流的开源大模型。

LLaVA论文名:Visual Instruction Tuning 视觉指令微调

论文:*2304.08485 (arxiv.org)

代码:[haotian-liu/LLaVA: NeurIPS’23 Oral] Visual Instruction Tuning (LLaVA) built towards GPT-4V level capabilities and beyond. (github.com)

什么是指令微调?什么是视觉指令微调

首先回答什么是指令微调。所谓的指令微调就是一种特殊的有监督微调(supervised fine-tuning),不同之处在于数据集的输入输出格式上。指令微调是在(指令,输出)数据集上进行微调的,目的是让模型对于指令的输出尽可能与人类期望的输出对齐。指令微调的特殊之处在于其数据集的结构,即由人类指令和期望的输出组成的配对。这种结构使得指令微调专注于让模型理解和遵循人类指令。

什么是视觉指令微调

当指令中嵌入了图像数据时,我们就称为视觉指令微调。

LLaVA论文中的技术方案

  • 使用仅用语言的GPT-4生成了一个语言-图像指令跟随数据(instruction-following data)

模型结构

LLaVA的模型结构很简单,由CLIP视觉编码器ViT-L/14、Vicuna大语言模型和一个Projection层组成。

  • CLIP视觉编码器:负责将输入图像Xv转换视觉特征向量Zv。视觉编码器参数在整个模型训练过程中都保持冻结。

  • Projection层:负责将视觉特征向量Zv通过一个简单的线性变换矩阵W(LLaVA 1.5版本使用MLP层实现,把视觉特征空间转换到语义特征空间,与LLM的语言embedding tokens对齐。

  • 大语言模型Vicuna:把由图像转换而来的embedding tokens与指令tokens拼接在一起作为输入,生成模型回复Xa。

  • 关于参数冻结的理解

    在Pytorch中,使用一行代码实现参数冻结

    被冻结的参数依然参与反向传播计算,因为误差反向传播是按照链式法则逐层向后进行的。但是梯度不再更新,同时不再为梯度保留空间,不占用显存。

模型训练

LLaVA模型的预训练分为两个阶段。

  • Stage 1:第一阶段冻结视觉编码器与LLM参数,仅训练Projection层,将图像特征Hv与大模型的word embedding 对齐。
  • Stage 2:第二阶段仅冻结视觉编码器,同时更新LLM参数和projection层参数进行端到端微调。

安装LLaVA代码库

  1. 下载LLaVA代码

    git clone https://github.com/haotian-liu/LLaVA.git
    cd LLaVA
  2. 安装

    pip install --upgrade pip  # enable PEP 660 support
    pip install -e .
  3. 安装训练需要的包

    pip install -e ".[train]"
    pip install flash-attn --no-build-isolation # 注意DCU版flash-attn请从光合开发者平台下载移植版https://www.hpccube.com/sso/login?service=https://developer.hpccube.com/tool/

模型推理

我们运行基于Gradio Web UI的网页版Demo进行推理演示。首次运行Demo会自动下载模型权重,亲测下载速度很快。

基于LLaVA独特的前后端架构,我们依次执行以下命令启动网页版demo

1. 启动controller

任意打开一个终端,执行命令

python -m llava.serve.controller --host 0.0.0.0 --port 10000

启动成功会看到

2.启动gradio web server

任意打开一个终端,执行命令

python -m llava.serve.gradio_web_server --controller http://localhost:10000 --model-list-mode reload

启动成功会输出一个URL: ,记下端口号7860,这即是我们要访问的网页Demo的端口号。

3.加载模型

任意打开一个终端,执行命令

python -m llava.serve.model_worker --host 0.0.0.0 --controller http://localhost:10000 --port 40000 --worker http://localhost:40000 --model-path liuhaotian/llava-v1.5-13b

首次启动会自动从hf上下载模型权重,默认保存在目录下。

模型启动成功

4.访问7860端口

如何使用本地浏览器访问远程服务器的URL呢?请参考网络博客通过ssh在本地打开远程服务器的网页_怎么终端在远程服务器打开的网站在本地操作-CSDN博客

这里我们着重看一下SCNet平台的访问方法。SCNet平台专门提供了“访问自定义服务”的功能,只需要输入服务端口号7860即可从本地访问服务器URL。

启动后会自动弹出网页。

到此为止,我们成功在DCU服务器上部署LLaVA模型。

可能遇到的报错与解决办法

报错:TypeError: LlavaLlamaForCausalLM.forward() got an unexpected keyword argument 'cache_position'
​
解决办法:降低Transformers库的版本installed transformers==4.37.2 and it worked.
报错:libgomp: Thread creation failed: Resource temporarily unavailable
原因:OpenMP系统线程数过大,系统资源不够
解决办法:减少OpenMP线程数 
export OMP_NUM_THREADS=1
减少模型并发线程数

推理效果

可以看到LLaVA的多模态能力十分强大,可以很好地捕捉到图像中的细节。

推理显存分析

llava-1.5-13B(24.3GB bf16权重),实际推理显存占用(默认半精度):28.8GB

8bit量化后显存占用:13.9968GB

4bit量化后显存占用:8.2944GB

flash_attn不影响显存


实验平台与软硬件环境

LLaVA预训练阶段的实验平台与软硬件环境与推理阶段相同,我们在SCNet超算互联网申请一台64GB大显存的DCU进行预训练。

硬件配置如下

加速卡异构加速卡AI(DCU) * 1卡显存64GB处理器15核心 2*7490 64C内存110GB

软件环境

  • jupyterlab

  • pytorch:2.1.0

  • ubuntu20.04

  • dtk24.04.1

  • py3.10

预备阶段:准备预训练数据集

根据LlaVA论文的介绍,模型预训练是在558K subset of the LAION-CC-SBU 数据集上进行的,我们先下载数据集:liuhaotian/LLaVA-Pretrain · Datasets at Hugging Face

数据细节

从数据样例可以看出,该数据集由image、图片索引(id)、对话文本(human与gpt的问答组成一对数据,gpt的回答可以作为训练的label)组成。

数据集结构
  • blip_laion_cc_sbu_558k.json 包含了从图像-标题对生成的多模态合成对话,通过添加随机选择的指令,如“描述这张图片”。它用于 LLaVA 的预训练。使用原始的 CC-3M 标题作为默认答案。

  • blip_laion_cc_sbu_558k_meta.json 包含了图像文件名、图像 URL 和合成 BLIP 标题的元数据。

  • images.zip 包含了从 LAION/CC/SBU 过滤子集中的所有原始图像。

我们将下载好的数据解压后存放在一个文件夹中,按如下方式组织数据,例如在文件夹:/root/private_data/LLaVA/dataset中

 

启动预训练脚本

我们直接启动LLaVA提供的预训练脚本,脚本文件在目录下,如果我们没有事先下载权重,首次启动脚本会自动下大语言模型权重与CLIP视觉编码器权重,比较方便,亲测下载速度很快。自动下载的模型权重默认保存在系统的.cache目录下,例如。我们可以先以默认方式下载,然后再把模型权重移动到自己喜欢的位置。

脚本文件内容如下:llava使用deepspeed框架进行预训练,便于结合zero优化器实现显存优化与分布式训练。由于本次实验只在单卡上进行,deepspeed是针对分布式训练(多卡)的优化,所以deepspeed的作用在此约等于无。

 

在此我对上述预训练脚本的参数进行一些注释,方便大家按需修改,使用时注意把注释删掉

 

比较重要的超参数

预训练阶段关键超参数如下

HyperparametersValuebf16Truenum_train_epochs1per_device_train_batch_size32learning_rate1e-3weight_decay0warmup_ratio0.03lr_scheduler_type"cosine"model_max_length2048base optimizerAdamWgradient_checkpointingTruedataloader_num_workers4lazy_preprocessTrue

可能遇到的问题

启动预训练脚本很可能遇到一些很常见的问题,大家按照报错提示解决即可,在这里列出一些我遇到的特殊问题

报错1:OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 64 current, 64 max
​
解决办法:export OPENBLAS_NUM_THREADS=1
​
pycharm服务器远程报错:not find libgalaxyhip.so.5
解决办法:添加环境变量 LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/dtk-24.04.1/lib
​
wandb连接问题:将参数脚本参数 report_to 设为none即可
​
报错2:MIOpen(HIP): Warning [SearchGcnAssembler] No rocm path set while finding /llvm/bin/clang. Recommended to set ROCM_PATH env 
​
报错3:ValueError: --tf32 requires Ampere or a newer GPU arch, cuda>=11 and torch>=1.
解决办法:DCU不支持tf32,在预训练脚本中,把tf32一项删去即可。
​
远程调试代码库打断点技巧:在debug配置中设置对应文件的映射即可打上断点。
F:/LLaVA-main/scripts/v1_5/llava/train/train_mem.py /tmp/pycharm_project_229/scripts/v1_5/llava/train/train_mem.py
第二,不能越级打断点,比如用deepspeed模组启动train_mem.py文件,必需在train_mem.py文件中打断点,如果在train.py打则打不上。虽然说train_mem.py最终会跳转到train.py中执行
​

训练实况

  • 显存占用:25.9584GB 到 46.9184GB 到 60.896GB 到 47.36GB 到 52.06GB。。。不断地跳变,这是为什么呢?答,显存变化与梯度检查点gradient_checkpointing )的优化策略有关。梯度检查点会在计算过程中动态地丢弃一些中间计算结果(激活值)以节约显存开销。

  • 梯度检查点gradient_checkpointing )核心思想是在模型的前向传播过程中选择性地存储中间结果。通常,反向传播阶段需要保存所有层的激活值以计算梯度。但此方法会占用大量内存,特别是在处理长序列或大模型时。相反,Gradient Checkpointing 在关键点(称为“检查点”)记录中间状态,在其他地方则丢弃这些信息。当需要回溯计算梯度时,只需重新执行从上一个检查点到当前位置的前向传播部分。详见探索高效深度学习:Gradient Checkpointing 技术详解与应用-CSDN博客

  • 从hf官方下载的vicuna-13b-v1.5权重实际上是半精度的(bf16),加载到显存大约需要24.343GB空间(仅16bits权重

  • vision_towerclip-vit-large-patch14-336) 大约需要0.768GB显存 clip-vit-large-patch14-336(bf16)(视觉骨架约384M参数)

  • 单卡64GB显存进行LLaVA-13b-v1.5预训练,使用稍微小一些的batch_size=32 + bf16 + 梯度检查点技术,显存刚好够用

  • 关于第一阶段预训练参数冻结的关键代码实现:关键参数tune_mm_mlp_adapter=True,会首先冻结全部模型参数包括:LLM参数、vision_tower参数、projector层参数,然后再单独解冻projector层的参数,来达到仅训练projector层的目的,关键代码如下

准备数据集

请下载数据集注释文件https://huggingface.co/datasets/liuhaotian/LLaVA-Instruct-150K/blob/main/llava_v1_5_mix665k.json

并且下载images文件

  • COCO: train2017

  • GQA: images

  • OCR-VQA: download script, we save all files as (建议从kaggle上面下载OCR-VQA-200K-dataset-zip (kaggle.com)

  • TextVQA: train_val_images

  • VisualGenome: part1, part2

将下载好的数据集解压,并按照如下方式组织数据文件,例如在目录https://blog.csdn.net/m0_62480812/article/details/dataset下

├── coco
│   └── train2017
├── gqa
│   └── images
├── ocr_vqa
│   └── images
├── textvqa
│   └── train_images
└── vg
    ├── VG_100K
    └── VG_100K_2

下载projector权重

为了便于微调,我们可以直接下载官方预训练好的projector权重LLaVA/docs/MODEL_ZOO.md at main · haotian-liu/LLaVA (github.com)

找到匹配的模型与版本号

在服务器上新建一个文件夹专门放置下载好的projector权重

记好地址,后面启动脚本时需要用到

启动微调脚本

微调脚本的路径是

在启动微调脚本之前,我们需要对一些参数进行个性化修改,比如模型路径、数据集路径等。

 

从启动脚本上看,微调脚本与预训练脚本几乎没有差别,都是启动train_mem.py进行训练。一个最重要的参数区别是预训练把参数tune_mm_mlp_adapter=True,而微调则没有设置该参数。

直接尝试全参数微调

直接启动微调脚本会出现显存不够用的情况,因为LLM模型也参与了微调,而且不包括数据batch与激活值。而我们的单卡DCU最大显存只有64GB直接微调行不通。

LoRA微调

LoRA(Low-Rank Adaptation of LLMs),即LLMs的低秩适应,是参数高效微调最常用的方法。

LoRA的本质就是用更少的训练参数来近似LLM全参数微调所得的增量参数,从而达到使用更少显存占用的高效微调。

LoRA的核心思想是,在冻结预训练模型权重后,将可训练的低秩分解矩阵注入到的Transformer架构的每一层中,从而大大减少了在下游任务上的可训练参数量。

微调脚本

特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。


举报收藏 0评论 0
0相关评论
相关最新动态
推荐最新动态
点击排行
{
网站首页  |  关于我们  |  联系方式  |  使用协议  |  隐私政策  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号