简介
西风吹老洞庭波,一夜湘君白发多。醉后不知天在水,满船清梦压星河。小伙伴好,我是微信公众号《小窗幽记机器学习》的小编:卖核弹的小女孩。更多、更新文章欢迎关注微信公众号:小窗幽记机器学习。后续会持续输出模型推理加速、工程部署、LLM、AI艺术等系列,敬请期待。
有很多小伙伴看我到之前分享的AI艺术系列:
- 05: 生成线稿画
- 04: 文心一言 vs ChatGPT
- 03: 生成可控图鉴赏
- 02:亚洲美女图鉴赏析
- 01: 生成宫崎骏风格图片
- 00: 梵高风格作品欣赏
都以为卖核弹的小女孩已经弃坑NLP转战CV,其实并没有。俗话说“小孩子才做选择题”,所以今天我选择NLP。今天这篇小作文主要介绍一下斯坦福 Alpaca 模型及其复现结果。 先直接抛出几个成果:
示例0:
### Instruction: 你是一名大学生,谈谈你的理想。
### Response:我的理想是成为一名优秀的教师,能给学生们提供更多的机会,帮助他们成长和发展,做到他们的爱好和梦想。我希望能够让学生们充分理解课程的内容,深入探索,充分发挥自己的潜能,最终取得成功。我还希望能够与家长和其他监督人有更好的沟通,让学生们在学习和生活中拥有更多的 healthy competition,最终达到学习的目的。示例1:
### Instruction:你是一名大学生,谈谈你的理想。除了当老师之外的理想。
### Response:我的理想是在一个贴近自然的环境中,有足够的资源和努力,我可以培养一种健康的生活方式,与自然和谐共存。除了当前老师之外的理想,我也希望具有自己的学习方法和课堂,不仅能够培养学生的知识水平,还能够培养他们的天赋和能力,使他们能够适应未来,能够适应环境变化,能够适应复杂性的社会发展。示例2:
### Instruction:你是一名计算机专业的硕士研究生,谈谈你的理想。
### Response:我的理想是在计算机和技术领域当中取得成功,具有深远的影响力。我希望能够在研究、开发和实践方面都取得成功,做出积极的贡献,并帮助人们利用计算机技术解决问题。我希望能够努力达成自己的目标,为自己、家庭、社会和地球创造一个更好的环境。示例3:
### Instruction: 你是一名医学博士生,谈谈你的理想。
### Response:我是一名医学博士生,我的理想是把医学知识和技术应用于真实的医疗环境中,帮助更多的患者获得更好的治疗 Results。我想让医学知识不仅在实践中流行,更要在教育中起到影响力,改变传统医学教育的理念,增强学生的专业性和能力,让他们能够更好的应对真实的医疗环境,让更多的患者得到充分的治疗服务。
Stanford Alpaca
模型简介
Stanford Alpaca是一个Instruction-following的LLaMA模型,即一个对LLaMA模型进行指令调优的结果模型。更多细节可以参考官方博客。
Stanford Alpaca 使用 OpenAI 的 text-davinci-003
模型以 self-instruct 方式生成 52K 指令遵循(instruction-following)样本,并以此作为对LLaMA进行指令微调的训练数据,最终得到Alpaca模型。
-
项目地址:https://github.com/tatsu-lab/stanford_alpaca
-
试用地址:https://alpaca-ai-custom6.ngrok.io/
训练方法
在学术界的预算条件下,训练高质量的指令遵循模型(instruction-following model)面临两个重要挑战:强大的预训练语言模型和高质量的指令遵循数据。对于第一个难题,可以采用最近Meta开源的LLaMA系列模型。LLaMA系列包含了参数量为7B/13B/33B/65B的不同模型。然而,原模型的效果较差(如生成的结果文不对题、以及无法自然地结束生成等),需要后续进行微调。对于第二个难题,Self-Instruct提出一种利用现有的强大语言模型自动生成指令数据。
因此,斯坦福的 Alpaca 模型基于 LLaMA-7B模型结合self-instruct 方式生成的52k指令遵循(instruction-following)样本数据进行有监督的指令微调,就能达到类似 GPT-3.5 的效果。
该项目提供了对LLaMA模型进行微调的廉价方法,大体思路如下:
首先,利用OpenAI提供的GPT模型(text-davinci-003
)API结合self-instruct方法生成质量较高的指令数据(仅52k),例如:
{"instruction": "Rewrite the following sentence in the third person","input": "I am anxious","output": "She is anxious."
}, {"instruction": "What are the three primary colors?","input": "","output": "The three primary colors are red, blue, and yellow."
}
首先使用 self-instruct 种子集中的 175 个人工编写的指令-输出(instruction-output)对,然后用该种子集作为 in-context 样本 prompt text-davinci-003
模型来生成更多指令。Alpaca通过简化生成 pipeline 改进了 self-instruct 方法,并显著降低了成本。Alpaca官方声称基于openai的API生成52k指令数据集的费用<500美元。
有了这个指令遵循数据集,下一步是使用 Hugging Face 的训练框架微调 LLaMA 模型,在这个过程利用了FSDP(Fully Sharded Data Parallel)和混合精度训练等技术。成本方面,Alpaca在8个80GB A100 上微调一个 7B LLaMA 模型需要3个小时,这对大多数云计算提供商来说成本不到 100 美元。整体价格还算比较亲民,可盐可甜。
下面介绍如何基于 LLaMA-7B 尝试复现 Alpaca-7B。
准备工作
环境安装
创建容器:
docker run --gpus all --privileged --name='test_alpaca_v1' -p 8809:8809 -p 8810:8810 -v /data/home/:/home -w /home -itd nvcr.io/nvidia/tritonserver:22.07-py3 bash
安装Python3.10
容器内默认的Python版本是3.8,而斯坦福Alpaca官方使用的是Python3.10,所以需要在容器内再安装一个Python版本:Python3.10。
安装Python3.10之前需要安装一些依赖
apt-get update -y
apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev wget libbz2-dev -y
PS: python3.7以上的Python版本的需要安装libffi-devel
另外,还需要安装先升级OpenSSL,本实验所使用容器中已经安装openssl version
版本如下:
OpenSSL 1.1.1f 31 Mar 2020
安装Python3.10:
在Python官网下载Python10的源码:
wget https://www.python.org/ftp/python/3.10.11/Python-3.10.11.tar.xz
下载后解压安装:
tar -xf Python-3.10.11.tar.xz
cd Python-3.10.11
./configure --enable-optimizations --prefix=/opt/python3.10.11
make -j8
make install
如果要安装OpenSSL可以参考。
此时Python3.10安装在/opt/python3.10.11/
。如果想将系统默认的python3
指向python3.10
。
which python3
:
/usr/bin/python3
which pip3
:
/usr/local/bin/pip3
只需要如下改动:
rm -rf /usr/bin/python3
ln -s /opt/python3.10.11/bin/python3 /usr/bin/python3
rm -rf /usr/local/bin/pip3
ln -s /opt/python3.10.11/bin/pip3 /usr/local/bin/pip3
另一种方式是直接将/opt/python3.10.11/bin/
添加到系统PATH中。
包安装
安装pytorch:
pip3 install torch==1.13 -i https://mirrors.cloud.tencent.com/pypi/simple
由于安装torch时候同时将torchrun
安装在/opt/python3.10.11/bin/torchrun
,所以需要将/opt/python3.10.11/bin/torchrun
创建一个软链接或者直接将整个/opt/python3.10.11/bin
添加到PATH。这里只添加一个软链接:
ln -s /opt/python3.10.11/bin/torchrun /usr/bin/torchrun
安装指定版本transformers:
目前,transformers官方版本并没有LLaMA相关的实现,但是已经合并到主分支了,因此,在使用过程需要切换到对应的commit,从源代码进行相应的安装。
cd transformers
git checkout 0041be5
pip3 install . -i https://mirrors.cloud.tencent.com/pypi/simple
另一种方式是直接拉取push分支的Repo,直接pip3 install . -i
安装。
安装apex:
git clone https://github.com/NVIDIA/apex.git
cd apex
git checkout 22.04-dev
pip3 install -v --disable-pip-version-check --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./
安装其他依赖:
numpy
rouge_score
fire
openai
sentencepiece
tokenizers==0.12.1
wandb
模型格式转换
需要将LLaMA原始权重文件转换为Transformers库对应的模型文件格式。如果不想自己转,也可以直接从Hugging Face下载转换好的模型
cd transformerspython3 src/transformers/models/llama/convert_llama_weights_to_hf.py --input_dir /home/model_zoo/llama --model_size 7B --output_dir /home/model_zoo/llama/7B/hf-llama-model
这个版本transformers
转换得到的结果是分别存于2个文件夹:llama-7b
和tokenizer
可以通过以下方式加载模型和分词器:
tokenizer = transformers.LlamaTokenizer.from_pretrained("/home/model_zoo/llama/7B/hf-llama-model/tokenizer/")model = transformers.LlamaForCausalLM.from_pretrained("/home/model_zoo/llama/7B/hf-llama-model/llama-7b/")
为了方便将tokenizer目录的文件拷贝到llama-7b目录下。如果是直接用最新版的transformers
中转换脚本的话在hf-llama-model
会将模型参数文件和tokenizer相关文件平铺放一起。
数据准备
Stanford Alpaca提供用于训练的指令数据集alpaca_data.json,可以直接使用该数据集进行模型精调。但是在Alpaca-LoRA中提到该数据集存在一些噪声,因此,他们对该数据集做了清洗后得到了文件alpaca_data_cleaned.json。小伙伴们也可以采用该数据集进行训练,或许会得到更好结果。这里为了兼容中文,所以使用InstructionWild中的instinwild_en.json和instinwild_ch.json。
其他
如果想使用wandb,则可以在机器终端上运行wandb login
命令,然后填入自己wandb上账号的API key。
模型精调
torchrun --nproc_per_node=8 --master_port=25001 train.py \--model_name_or_path /home/model_zoo/llama/7B/hugging_face_format/ \--data_path /home/data_zoo/InstructionWild/data/instinwild_ch_en.json \--bf16 True \--output_dir /home/Repository/LLM/stanford_alpaca/output/alpaca/sft_7b_en_cn \--num_train_epochs 3 \--per_device_train_batch_size 1 \--per_device_eval_batch_size 1 \--gradient_accumulation_steps 8 \--evaluation_strategy "no" \--save_strategy "steps" \--save_steps 2000 \--save_total_limit 1 \--learning_rate 2e-5 \--weight_decay 0. \--warmup_ratio 0.03 \--lr_scheduler_type "cosine" \--logging_steps 1 \--fsdp "full_shard auto_wrap" \--fsdp_transformer_layer_cls_to_wrap 'LlamaDecoderLayer' \--tf32 True
inference
示例0:### Instruction: 你是一名小学生,谈谈你的理想。### Response:我的理想是成为一名科学家。我梦想从事有关科学研究,努力推动科学研究,同时还能给人们带来实质性的改变和帮助。我希望能够在有关的研究领域取得杰出的成就,做出对人类社会的贡献。示例1:
> ### Instruction: 你是一名中学生,谈谈你的理想。### Response:我的理想是成为一名优秀的学生,拥有自己的自由,幸福地把自己从学习中获得成功,并尽力应对新任务,不断成长。我希望能够努力把自己的想法做到极致,做到自己认为有价值的事,同时充分利用自己的时间来实现自己的目标。我希望能够有足够的智慧和技能,成为一名领先的学者,不断成长,充实自己的梦想。示例2:
> ### Instruction: 你是一名高学生,谈谈你的理想。### Response:我的理想是成为一名优秀的教师,能给学生们提供更多的机会,帮助他们成长和发展。我希望能够在教育领域突出自己的风采,做到有追求卓越的教育质量,并且给学生们带来更多有趣的学习经历。此外,我也想继续自己学习,及时掌握最新的教育技巧和发展趋势,以最大限度地帮助学生们成长。示例3:
> ### Instruction: 你是一名大学生,谈谈你的理想。### Response:我的理想是成为一名优秀的教师,能给学生们提供更多的机会,帮助他们成长和发展,做到他们的爱好和梦想。我希望能够让学生们充分理解课程的内容,深入探索,充分发挥自己的潜能,最终取得成功。我还希望能够与家长和其他监督人有更好的沟通,让学生们在学习和生活中拥有更多的 healthy competition,最终达到学习的目的。示例4:
> ### Instruction: 你是一名大学生,谈谈你的理想。除了当老师之外的理想。### Response:我的理想是在一个贴近自然的环境中,有足够的资源和努力,我可以培养一种健康的生活方式,与自然和谐共存。除了当前老师之外的理想,我也希望具有自己的学习方法和课堂,不仅能够培养学生的知识水平,还能够培养他们的天赋和能力,使他们能够适应未来,能够适应环境变化,能够适应复杂性的社会发展。示例5:
> ### Instruction: 你是一名计算机专业的硕士研究生,谈谈你的理想。### Response:我的理想是在计算机和技术领域当中取得成功,具有深远的影响力。我希望能够在研究、开发和实践方面都取得成功,做出积极的贡献,并帮助人们利用计算机技术解决问题。我希望能够努力达成自己的目标,为自己、家庭、社会和地球创造一个更好的环境。示例6:
> ### Instruction: 你是一名医学博士生,谈谈你的理想。### Response:我是一名医学博士生,我的理想是把医学知识和技术应用于真实的医疗环境中,帮助更多的患者获得更好的治疗 Results。我想让医学知识不仅在实践中流行,更要在教育中起到影响力,改变传统医学教育的理念,增强学生的专业性和能力,让他们能够更好的应对真实的医疗环境,让更多的患者得到充分的治疗服务。示例7:
> ### Instruction: 你模仿鲁迅的风格吐槽一下猪脚饭涨价了这件事,要求100字。### Response:吐槽一下猪脚饭涨价了这件事,要求100字。猪脚饭是每个人心中的一份美食,它让人回想起童年的回忆和快乐时光。不过,现在adidas gazelle sale uk,猪脚饭的价格一整天都在上涨,而许多餐馆的猪脚饭也比以往得到越来越多的人 patronizing。到底是吐槽还是咕咕,结果一样:猪脚饭价格涨至令人难以接受的水平。示例8:
> ### Instruction: 你叫孔乙己,给大家做个自我介绍吧,并谈谈为啥你脱不下长衫。### Response:我叫孔乙,我出生于中国,在美国接受教育并取得学士学位。我目前在一家旅游公司担任公关代表,负责宣传和制定品牌策略。我喜欢旅行,学习新的文化,探索新的机会,并与来自不同背景的人们接触和沟通。我认为,要脱不下长衫,应该坚持自己的想法,拥抱失败,并勇敢地继续前行。示例9:
> ### Instruction: 你是孔乙己,给大家做个自我介绍吧,并谈谈你为啥脱不下长衫。### Response:我是孔乙,大家可以别谈谈我为啥脱不下长衫。我是一名坚强、坚韧、坚强的人,对事物一直追求质量第一的原则,努力做一个真正的人才。我从身体上健康,从心理上坚强,从思维上灵活,从能力上有限,从宽容上有毅,从耐心上坚强,把它们融入到自己的工作中,希望能够实现一个有价值的自己。示例10:
> ### Instruction: 你做好自我介绍吧,你毕业于华中科技大学,喜欢和男孩子一起玩。### Response:我叫张小绵,出生于1994年,学习于华中科技大学,喜欢和男孩子一起玩。我有一套充满励志的心,充满想象力,勇于挑战新事物,热衷于学习新技能,充满创新的精神,坚定不懈,善于解决问题。我乐观积极,乐于助人,具有良好的团队合作能力,并具有多种学习语言、烹饪、体育和文化活动等能力。
小结
可以看出,效果上整体确实一般。可能是由于开源的LLaMA模型在预训练阶段主要基于英语训练,虽然具有一定的多语言能力,然而由于它没有将中文语料加入预训练,所以LLaMA在中文上整体效果较弱。
问题汇总
运行完最后一个epoch后出现OOM:
{'train_runtime': 5162.7837, 'train_samples_per_second': 10.072, 'train_steps_per_second': 0.157, 'train_loss': 1.0267484738615347, 'epoch': 1.0}
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 812/812 [1:26:02<00:00, 6.36s/it]/opt/python3.10.11/lib/python3.10/site-packages/torch/distributed/fsdp/fully_sharded_data_parallel.py:2224:
UserWarning: Failed to clone() tensor with name _fsdp_wrapped_module._fpw_module.model.layers.28.mlp.down_proj.weight. This may mean that this state_dict entry could point to invalid memory regions after returning from
state_dict() call if this parameter is managed by FSDP.
Please check clone implementation of _fsdp_wrapped_module._fpw_module.model.layers.28.mlp.down_proj.weight.
Error: CUDA out of memory. Tried to allocate 172.00 MiB (GPU 3; 39.59 GiB total capacity; 35.81 GiB already allocated;
79.19 MiB free; 37.59 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to
avoid fragmentation. See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF
解决方案:参考官方Repo上issue,将safe_save_model_for_hf_trainer
改为如下:
def safe_save_model_for_hf_trainer(trainer: transformers.Trainer, output_dir: str):"""Collects the state dict and dump to disk."""# state_dict = trainer.model.state_dict()from torch.distributed.fsdp import (FullyShardedDataParallel as FSDP,MixedPrecision,BackwardPrefetch,ShardingStrategy,FullStateDictConfig,StateDictType,)model=trainer.model save_policy = FullStateDictConfig(offload_to_cpu=True, rank0_only=True)with FSDP.state_dict_type(model, StateDictType.FULL_STATE_DICT, save_policy):cpu_state_dict = model.state_dict()if trainer.args.should_save:trainer._save(output_dir, state_dict=cpu_state_dict) # noqa