From 7a1e0d0621f8e5a63510400c8e8526189f869c77 Mon Sep 17 00:00:00 2001 From: qiankun ye <42082658+yeyeyeyeeeee@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:37:54 +0800 Subject: [PATCH] update qwen2.5-coder-7b lora --- .../Qwen2.5-Coder-7B-Instruct Lora 微调.md | 217 +++++ .../Qwen2.5-Coder-7B-instruct lora微调.ipynb | 861 ++++++++++++++++++ 2 files changed, 1078 insertions(+) create mode 100644 models/Qwen2.5-Coder/Qwen2.5-Coder-7B-Instruct Lora 微调.md create mode 100644 models/Qwen2.5-Coder/Qwen2.5-Coder-7B-instruct lora微调.ipynb diff --git a/models/Qwen2.5-Coder/Qwen2.5-Coder-7B-Instruct Lora 微调.md b/models/Qwen2.5-Coder/Qwen2.5-Coder-7B-Instruct Lora 微调.md new file mode 100644 index 0000000..845c781 --- /dev/null +++ b/models/Qwen2.5-Coder/Qwen2.5-Coder-7B-Instruct Lora 微调.md @@ -0,0 +1,217 @@ +# Qwen2.5-Coder-7B-Instruct Lora 微调 + +本节我们简要介绍如何基于 transformers、peft 等框架,对Qwen2.5-Coder-7B-Instruct 模型进行 Lora 微调。Lora 是一种高效微调方法,深入了解其原理可参见博客:[知乎|深入浅出Lora](https://zhuanlan.zhihu.com/p/650197598)。 + + +这个教程会在同目录下给大家提供一个 [nodebook](./05-Qwen2-7B-Instruct%20Lora.ipynb) 文件,来让大家更好的学习。 + +## 模型下载 + +使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径。 + +在 /root/autodl-tmp 路径下新建 model_download.py 文件并在其中输入以下内容,粘贴代码后请及时保存文件,如下图所示。并运行 `python /root/autodl-tmp/model_download.py` 执行下载,模型大小为 14.18GB,下载模型大概需要 5 分钟。 + +```python +import torch +from modelscope import snapshot_download +import os +model_dir = snapshot_download('Qwen/Qwen2.5-Coder-7B-Instruct', cache_dir='/root/autodl-tmp', revision='master') +``` + +## 环境配置 + +在完成基本环境配置和本地模型部署的情况下,你还需要安装一些第三方库,可以使用以下命令: + +```bash +python -m pip install --upgrade pip + +pip install modelscope==1.20.0 +pip install transformers==4.46.2 +pip install sentencepiece==0.2.0 +pip install accelerate==1.1.1 +pip install datasets==3.1.0 +pip install peft==0.13.2 + +``` + +> 考虑到部分同学配置环境可能会遇到一些问题,我们在AutoDL平台准备了Qwen2.5-Coder-7B-Instruct的环境镜像。点击下方链接并直接创建Autodl示例即可。 +> ***https://www.codewithgpu.com/i/datawhalechina/self-llm/Qwen2.5-Coder-7B-Instruct*** + +在本节教程里,我们将微调数据集放置在根目录 [/dataset](../dataset/huanhuan.json)。 + +## 指令集构建 + +LLM 的微调一般指指令微调过程。所谓指令微调,是说我们使用的微调数据形如: + +```json +{ + "instruction":"回答以下用户问题,仅输出答案。", + "input":"1+1等于几?", + "output":"2" +} +``` + +其中,`instruction` 是用户指令,告知模型其需要完成的任务;`input` 是用户输入,是完成用户指令所必须的输入内容;`output` 是模型应该给出的输出。 + +即我们的核心训练目标是让模型具有理解并遵循用户指令的能力。因此,在指令集构建时,我们应针对我们的目标任务,针对性构建任务指令集。例如,在本节我们使用由笔者合作开源的 [Chat-甄嬛](https://github.com/KMnO4-zx/huanhuan-chat) 项目作为示例,我们的目标是构建一个能够模拟甄嬛对话风格的个性化 LLM,因此我们构造的指令形如: + +```json +{ + "instruction": "你是谁?", + "input":"", + "output":"家父是大理寺少卿甄远道。" +} +``` + +我们所构造的全部指令数据集在根目录下。 + + +## 数据格式化 + +`Lora` 训练的数据是需要经过格式化、编码之后再输入给模型进行训练的,如果是熟悉 `Pytorch` 模型训练流程的同学会知道,我们一般需要将输入文本编码为 input_ids,将输出文本编码为 `labels`,编码之后的结果都是多维的向量。我们首先定义一个预处理函数,这个函数用于对每一个样本,编码其输入、输出文本并返回一个编码后的字典: + +```python +def process_func(example): + MAX_LENGTH = 384 # Llama分词器会将一个中文字切分为多个token,因此需要放开一些最大长度,保证数据的完整性 + input_ids, attention_mask, labels = [], [], [] + instruction = tokenizer(f"<|im_start|>system\n现在你要扮演皇帝身边的女人--甄嬛<|im_end|>\n<|im_start|>user\n{example['instruction'] + example['input']}<|im_end|>\n<|im_start|>assistant\n", add_special_tokens=False) # add_special_tokens 不在开头加 special_tokens + response = tokenizer(f"{example['output']}", add_special_tokens=False) + input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id] + attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1] # 因为eos token咱们也是要关注的所以 补充为1 + labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id] + if len(input_ids) > MAX_LENGTH: # 做一个截断 + input_ids = input_ids[:MAX_LENGTH] + attention_mask = attention_mask[:MAX_LENGTH] + labels = labels[:MAX_LENGTH] + return { + "input_ids": input_ids, + "attention_mask": attention_mask, + "labels": labels + } +``` + +`Qwen2.5-Coder` 采用的`Prompt Template`格式如下: + +```text +<|im_start|>system +You are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|> +<|im_start|>user +{user_prompt}<|im_end|> +<|im_start|>assistant +{assistant_response}<|im_end|> + +``` + +## 加载tokenizer和半精度模型 + +模型以半精度形式加载,如果你的显卡比较新的话,可以用`torch.bfolat`形式加载。对于自定义的模型一定要指定`trust_remote_code`参数为`True`。 + +```python +tokenizer = AutoTokenizer.from_pretrained('/root/autodl-tmp/qwen/Qwen2-7B-Instruct/', use_fast=False, trust_remote_code=True) + +model = AutoModelForCausalLM.from_pretrained('/root/autodl-tmp/qwen/Qwen2-7B-Instruct/', device_map="auto",torch_dtype=torch.bfloat16) +``` + +## 定义LoraConfig + +`LoraConfig`这个类中可以设置很多参数,但主要的参数没多少,简单讲一讲,感兴趣的同学可以直接看源码。 + +- `task_type`:模型类型 +- `target_modules`:需要训练的模型层的名字,主要就是`attention`部分的层,不同的模型对应的层的名字不同,可以传入数组,也可以字符串,也可以正则表达式。 +- `r`:`lora`的秩,具体可以看`Lora`原理 +- `lora_alpha`:`Lora alaph`,具体作用参见 `Lora` 原理 + +`Lora`的缩放是啥嘞?当然不是`r`(秩),这个缩放就是`lora_alpha/r`, 在这个`LoraConfig`中缩放就是4倍。 + +```python +config = LoraConfig( + task_type=TaskType.CAUSAL_LM, + target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], + inference_mode=False, # 训练模式 + r=8, # Lora 秩 + lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理 + lora_dropout=0.1# Dropout 比例 +) +``` + +## 自定义 TrainingArguments 参数 + +`TrainingArguments`这个类的源码也介绍了每个参数的具体作用,当然大家可以来自行探索,这里就简单说几个常用的。 + +- `output_dir`:模型的输出路径 +- `per_device_train_batch_size`:顾名思义 `batch_size` +- `gradient_accumulation_steps`: 梯度累加,如果你的显存比较小,那可以把 `batch_size` 设置小一点,梯度累加增大一些。 +- `logging_steps`:多少步,输出一次`log` +- `num_train_epochs`:顾名思义 `epoch` +- `gradient_checkpointing`:梯度检查,这个一旦开启,模型就必须执行`model.enable_input_require_grads()`,这个原理大家可以自行探索,这里就不细说了。 + +```python +args = TrainingArguments( + output_dir="./output/Qwen2_instruct_lora", + per_device_train_batch_size=4, + gradient_accumulation_steps=4, + logging_steps=10, + num_train_epochs=3, + save_steps=100, + learning_rate=1e-4, + save_on_each_node=True, + gradient_checkpointing=True +) +``` + +## 使用 Trainer 训练 + +```python +trainer = Trainer( + model=model, + args=args, + train_dataset=tokenized_id, + data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True), +) +trainer.train() +``` + +## 加载 lora 权重推理 + +训练好了之后可以使用如下方式加载`lora`权重进行推理: + +```python +from transformers import AutoModelForCausalLM, AutoTokenizer +import torch +from peft import PeftModel + +model_path = 'Qwen/Qwen2.5-Coder-7B-Instruct' +lora_path = 'lora_path' + +# 加载tokenizer +tokenizer = AutoTokenizer.from_pretrained(model_path) + +# 加载模型 +model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto",torch_dtype=torch.bfloat16) + +# 加载lora权重 +model = PeftModel.from_pretrained(model, model_id=lora_path, config=config) + +prompt = "你是谁?" +messages = [ + {"role": "system", "content": "现在你要扮演皇帝身边的女人--甄嬛"}, + {"role": "user", "content": prompt} +] + +text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) + +model_inputs = tokenizer([text], return_tensors="pt").to('cuda') + +generated_ids = model.generate( + model_inputs.input_ids, + max_new_tokens=512 +) +generated_ids = [ + output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) +] + +response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] + +print(response) +``` + diff --git a/models/Qwen2.5-Coder/Qwen2.5-Coder-7B-instruct lora微调.ipynb b/models/Qwen2.5-Coder/Qwen2.5-Coder-7B-instruct lora微调.ipynb new file mode 100644 index 0000000..e808f0e --- /dev/null +++ b/models/Qwen2.5-Coder/Qwen2.5-Coder-7B-instruct lora微调.ipynb @@ -0,0 +1,861 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "968b3659-a0f4-4dd9-866e-936cd3b3512c", + "metadata": {}, + "outputs": [], + "source": [ + "from datasets import Dataset\n", + "import pandas as pd\n", + "from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForSeq2Seq, TrainingArguments, Trainer, GenerationConfig" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3e4b2293-3762-4b5c-939b-2dab7a0955ae", + "metadata": {}, + "outputs": [], + "source": [ + "# 将JSON文件转换为CSV文件\n", + "df = pd.read_json('/root/self-llm-master/dataset/huanhuan.json')\n", + "ds = Dataset.from_pandas(df)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "2400d0f1-162c-477c-a650-f5ce1a3a72d0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'instruction': ['小姐,别的秀女都在求中选,唯有咱们小姐想被撂牌子,菩萨一定记得真真儿的——',\n", + " '这个温太医啊,也是古怪,谁不知太医不得皇命不能为皇族以外的人请脉诊病,他倒好,十天半月便往咱们府里跑。',\n", + " '嬛妹妹,刚刚我去府上请脉,听甄伯母说你来这里进香了。'],\n", + " 'input': ['', '', ''],\n", + " 'output': ['嘘——都说许愿说破是不灵的。', '你们俩话太多了,我该和温太医要一剂药,好好治治你们。', '出来走走,也是散心。']}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ds[:3]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "56aa4253-a3b1-441d-b24f-88a78d1732d1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Qwen2Tokenizer(name_or_path='/root/autodl-tmp/Qwen/Qwen2.5-Coder-7B-Instruct', vocab_size=151643, model_max_length=131072, is_fast=False, padding_side='right', truncation_side='right', special_tokens={'eos_token': '<|im_end|>', 'pad_token': '<|endoftext|>', 'additional_special_tokens': ['<|im_start|>', '<|im_end|>', '<|object_ref_start|>', '<|object_ref_end|>', '<|box_start|>', '<|box_end|>', '<|quad_start|>', '<|quad_end|>', '<|vision_start|>', '<|vision_end|>', '<|vision_pad|>', '<|image_pad|>', '<|video_pad|>']}, clean_up_tokenization_spaces=False), added_tokens_decoder={\n", + "\t151643: AddedToken(\"<|endoftext|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151644: AddedToken(\"<|im_start|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151645: AddedToken(\"<|im_end|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151646: AddedToken(\"<|object_ref_start|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151647: AddedToken(\"<|object_ref_end|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151648: AddedToken(\"<|box_start|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151649: AddedToken(\"<|box_end|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151650: AddedToken(\"<|quad_start|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151651: AddedToken(\"<|quad_end|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151652: AddedToken(\"<|vision_start|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151653: AddedToken(\"<|vision_end|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151654: AddedToken(\"<|vision_pad|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151655: AddedToken(\"<|image_pad|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151656: AddedToken(\"<|video_pad|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),\n", + "\t151657: AddedToken(\"\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=False),\n", + "\t151658: AddedToken(\"\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=False),\n", + "\t151659: AddedToken(\"<|fim_prefix|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=False),\n", + "\t151660: AddedToken(\"<|fim_middle|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=False),\n", + "\t151661: AddedToken(\"<|fim_suffix|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=False),\n", + "\t151662: AddedToken(\"<|fim_pad|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=False),\n", + "\t151663: AddedToken(\"<|repo_name|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=False),\n", + "\t151664: AddedToken(\"<|file_sep|>\", rstrip=False, lstrip=False, single_word=False, normalized=False, special=False),\n", + "}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tokenizer = AutoTokenizer.from_pretrained('/root/autodl-tmp/Qwen/Qwen2.5-Coder-7B-Instruct', use_fast=False, trust_remote_code=True)\n", + "tokenizer" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "12df8a44-3ab8-4a19-8b39-967cb76d0709", + "metadata": {}, + "outputs": [], + "source": [ + "def process_func(example):\n", + " MAX_LENGTH = 384 # Llama分词器会将一个中文字切分为多个token,因此需要放开一些最大长度,保证数据的完整性\n", + " input_ids, attention_mask, labels = [], [], []\n", + " instruction = tokenizer(f\"<|im_start|>system\\n现在你要扮演皇帝身边的女人--甄嬛<|im_end|>\\n<|im_start|>user\\n{example['instruction'] + example['input']}<|im_end|>\\n<|im_start|>assistant\\n\", add_special_tokens=False) # add_special_tokens 不在开头加 special_tokens\n", + " response = tokenizer(f\"{example['output']}\", add_special_tokens=False)\n", + " input_ids = instruction[\"input_ids\"] + response[\"input_ids\"] + [tokenizer.pad_token_id]\n", + " attention_mask = instruction[\"attention_mask\"] + response[\"attention_mask\"] + [1] # 因为eos token咱们也是要关注的所以 补充为1\n", + " labels = [-100] * len(instruction[\"input_ids\"]) + response[\"input_ids\"] + [tokenizer.pad_token_id] \n", + " if len(input_ids) > MAX_LENGTH: # 做一个截断\n", + " input_ids = input_ids[:MAX_LENGTH]\n", + " attention_mask = attention_mask[:MAX_LENGTH]\n", + " labels = labels[:MAX_LENGTH]\n", + " return {\n", + " \"input_ids\": input_ids,\n", + " \"attention_mask\": attention_mask,\n", + " \"labels\": labels\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "7319b6c4-e5d0-47da-9dea-4f28f82e01dc", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3531234a30734470b291a9c9a56ebb78", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Map: 0%| | 0/3729 [00:00system\\n现在你要扮演皇帝身边的女人--甄嬛<|im_end|>\\n<|im_start|>user\\n小姐,别的秀女都在求中选,唯有咱们小姐想被撂牌子,菩萨一定记得真真儿的——<|im_end|>\\n<|im_start|>assistant\\n嘘——都说许愿说破是不灵的。<|endoftext|>'" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tokenizer.decode(tokenized_id[0]['input_ids'])" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "5bc95adb-6b98-4378-bf90-863c5e367491", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'你们俩话太多了,我该和温太医要一剂药,好好治治你们。<|endoftext|>'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tokenizer.decode(list(filter(lambda x: x != -100, tokenized_id[1][\"labels\"])))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "daac681e-015b-4412-8c9f-9da8361d28de", + "metadata": {}, + "outputs": [], + "source": [ + "import torch" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "7b5d6464-acc0-4a94-ad43-3bfdd23e6f4c", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fa76e5d2475b42e398189d119da8ec8c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Loading checkpoint shards: 0%| | 0/4 [00:00, auto_mapping=None, base_model_name_or_path=None, revision=None, task_type=, inference_mode=False, r=8, target_modules={'gate_proj', 'v_proj', 'down_proj', 'o_proj', 'up_proj', 'k_proj', 'q_proj'}, lora_alpha=32, lora_dropout=0.1, fan_in_fan_out=False, bias='none', use_rslora=False, modules_to_save=None, init_lora_weights=True, layers_to_transform=None, layers_pattern=None, rank_pattern={}, alpha_pattern={}, megatron_config=None, megatron_core='megatron.core', loftq_config={}, use_dora=False, layer_replication=None, runtime_config=LoraRuntimeConfig(ephemeral_gpu_offload=False))" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from peft import LoraConfig, TaskType, get_peft_model\n", + "\n", + "config = LoraConfig(\n", + " task_type=TaskType.CAUSAL_LM, \n", + " target_modules=[\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\", \"gate_proj\", \"up_proj\", \"down_proj\"],\n", + " inference_mode=False, # 训练模式\n", + " r=8, # Lora 秩\n", + " lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理\n", + " lora_dropout=0.1# Dropout 比例\n", + ")\n", + "config" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "73403447-e6f8-436d-a6ae-9a3e62d697dd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "LoraConfig(peft_type=, auto_mapping=None, base_model_name_or_path='/root/autodl-tmp/Qwen/Qwen2.5-Coder-7B-Instruct/', revision=None, task_type=, inference_mode=False, r=8, target_modules={'gate_proj', 'v_proj', 'down_proj', 'o_proj', 'up_proj', 'k_proj', 'q_proj'}, lora_alpha=32, lora_dropout=0.1, fan_in_fan_out=False, bias='none', use_rslora=False, modules_to_save=None, init_lora_weights=True, layers_to_transform=None, layers_pattern=None, rank_pattern={}, alpha_pattern={}, megatron_config=None, megatron_core='megatron.core', loftq_config={}, use_dora=False, layer_replication=None, runtime_config=LoraRuntimeConfig(ephemeral_gpu_offload=False))" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model = get_peft_model(model, config)\n", + "config" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "bdadeda7-40c7-4d13-bb10-2342f2589b59", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "trainable params: 20,185,088 || all params: 7,635,801,600 || trainable%: 0.2643\n" + ] + } + ], + "source": [ + "model.print_trainable_parameters()" + ] + }, + { + "cell_type": "markdown", + "id": "f1bcf2d8-27ba-46e7-afc3-0af4564f0bcd", + "metadata": {}, + "source": [ + "# 配置训练参数" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "f2ebb791-793f-43c4-95a1-25b5d5e0b070", + "metadata": {}, + "outputs": [], + "source": [ + "args = TrainingArguments(\n", + " output_dir=\"./output/Qwen2.5-Coder-7B-Instruct\",\n", + " per_device_train_batch_size=4,\n", + " gradient_accumulation_steps=4,\n", + " logging_steps=10,\n", + " num_train_epochs=3,\n", + " save_steps=10, # 为了快速演示,这里设置10,建议你设置成100\n", + " learning_rate=1e-4,\n", + " save_on_each_node=True,\n", + " gradient_checkpointing=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "9daa30c2-752c-49db-888a-af48baaa434e", + "metadata": {}, + "outputs": [], + "source": [ + "trainer = Trainer(\n", + " model=model,\n", + " args=args,\n", + " train_dataset=tokenized_id,\n", + " data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "d051dc78-00a8-4d89-aa36-7ed70b5bf71b", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`...\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "
\n", + " \n", + " \n", + " [699/699 23:35, Epoch 2/3]\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
StepTraining Loss
103.968300
203.456000
303.343800
403.229300
503.239300
603.198400
703.202300
803.261800
903.303900
1003.208000
1103.207700
1203.209000
1303.126500
1403.127100
1503.195700
1603.172500
1703.143400
1803.092800
1903.088900
2003.083900
2103.070200
2203.062300
2303.113700
2403.393000
2502.783600
2602.682300
2702.778900
2802.802900
2902.798200
3002.679400
3102.679900
3202.698100
3302.751100
3402.765400
3502.768200
3602.715900
3702.709400
3802.795400
3902.670100
4002.608800
4102.795300
4202.679900
4302.775000
4402.684300
4502.634800
4602.697600
4702.634500
4802.363200
4902.281900
5002.294300
5102.185200
5202.302200
5302.258700
5402.351600
5502.430900
5602.360900
5702.356000
5802.145100
5902.343300
6002.179200
6102.300300
6202.259300
6302.329900
6402.309000
6502.242900
6602.310000
6702.378500
6802.170900
6902.234300

" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "TrainOutput(global_step=699, training_loss=2.7544531378793784, metrics={'train_runtime': 1418.2557, 'train_samples_per_second': 7.888, 'train_steps_per_second': 0.493, 'total_flos': 4.575963998146867e+16, 'train_loss': 2.7544531378793784, 'epoch': 2.996784565916399})" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "trainer.train()" + ] + }, + { + "cell_type": "markdown", + "id": "0814a560-1e42-4ced-99e6-de9648f8bfd8", + "metadata": {}, + "source": [ + "# 合并加载模型" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "7219bb51-66fa-4dae-bf5a-997382c220df", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b8588305bba14213ada7ca70dac68f5f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Loading checkpoint shards: 0%| | 0/4 [00:00