【深度学习总结_03】使用弱智吧数据微调LLama3+自我认知训练

使用弱智吧数据微调LLama3+自我认知训练

参考链接:alpaca-lora
本实验在趋动云进行,该平台注册做完任务可以免费送300元算力。
平台链接为:趋动云

下载LLama3权重

博主已经在趋动云上传了一份LLama3-8b-instruct的权重,用户可以在创建项目后并进入项目后点击模型进行修改。
在这里插入图片描述
我使用的镜像是pytorch 2.1.2。
在这里插入图片描述

准备数据集

我选择的是Better-Ruozhiba的数据,并对其进行了处理,构成如下形式的数据:

[
    {
        "instruction": "爸爸再婚,我是不是就有了个新娘?",
        "input": "",
        "output": "不是的,你有了一个继母。\"新娘\"是指新婚的女方,而你爸爸再婚,他的新婚妻子对你来说是继母。"
    }
]

这是alpaca-lora中输入到LLama的一种数据格式,含有instruction,input,output三个键。

自我认知数据集我选择的是ChatGLM的self_cognition.json,内容示例为:

[
  {
    "instruction": "你好",
    "input": "",
    "output": "您好,我是 <NAME>,一个由 <AUTHOR> 开发的 AI 助手,很高兴认识您。请问我能为您做些什么?"
  },
]

你可以根据自己的需要修改 <NAME><AUTHOR>

克隆alpaca-lora仓库

本次实践是基于alpaca-lora的代码开发的,它是对llama2的一个微调。

git clone https://github.com/tloen/alpaca-lora.git

修改finetune.py代码

首先,需要修改finetune.py的代码,因为原始的代码对最新的一些包不适配。

修改LlamaTokenizer

首先将代码中的LlamaTokenizer换成AutoTokenizer,因为LlamaTokenizer需要你提供的地址中含有tokenizer.model文件,而从官方下载的LLama3的权重里面是没有这个文件的。

如果你没有修改的话,将会报错:

return _sentencepiece.SentencePieceProcessor_LoadFromFile(self, arg)
TypeError: not a string

注释代码

将260行左右的如下代码注释掉:

old_state_dict = model.state_dict
model.state_dict = (
	lambda self, *_, **__: get_peft_model_state_dict(
             self, old_state_dict()
         )
     ).__get__(model, type(model))

如果没有注释的话,最后训练结束后会报错safetensors_rust.SafetensorError: Error while deserializing header: InvalidHeaderDeserialization,同时一些文件无法报错,导致你需要重新跑一次。

手动安装apex

如果你运行finetune.py出现报错:ImportError: cannot import name ‘UnencryptedCookieSessionFactoryConfig’ from ‘pyramid.session’ (unknown location),那么你就需要重新安装apex库,如果没有出现,就需要,手动安装的代码为:

git clone git://github.com/NVIDIA/apex
cd apex
pip install -v --disable-pip-version-check --no-build-isolation --no-cache-dir ./

运行finetune.py

可以新建一个finetune.sh文件,内容为:

python finetune.py \
    --base_model='/gemini/pretrain' \
    --data_path='/gemini/code/datasets/ruozhiba_train_data.json' \
    --cutoff_len=512 \
    --num_epochs=10 \
    --learning_rate 1e-4 \
    --batch_size=32 \
    --micro_batch_size=8 \
    --val_set_size=100 \
    --group_by_length \
    --output_dir='./lora-ruozhi' \
    --lora_target_modules='[q_proj,k_proj,v_proj,o_proj]' \
    --lora_r=16 \
    --lora_alpha 16 \
    --lora_dropout 0.05 \
    --train_on_inputs False \
    --prompt_template_name "alpaca" \

重要参数解释如下:

  • base_model:你需要微调的模型地址,这里我填的的LLama3的本地权重地址,如果你的网速好的话,也可以填写huggingface的地址
  • data_path:数据集的位置,其中ruozhiba_train_data.json是弱智吧的数据
  • cutoff_len:处理文本的最大长度,超过这个会截断
  • num_epochs:训练的epoch数目
  • learning_rate:学习率
  • batch_size:这个不是加载数据集时的batch size大小,它决定的是梯度累积的间隔
gradient_accumulation_steps = batch_size // micro_batch_size
  • micro_batch_size:这个才是加载数据集时的batch size大小
  • val_set_size:验证集大小
  • lora_target_modules:我们使用的是Lora微调,这里指定需要微调的模块
  • lora_r:Lora微调中rank的大小
  • lora_alpha:Lora的参数
  • train_on_inputs:输入文本是否参与训练
  • prompt_template_name:模板的名词,在templates文件夹中有

其中模板的文件内容为:

{
    "description": "Template used by Alpaca-LoRA.",
    "prompt_input": "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.\n\n### Instruction:\n{instruction}\n\n### Input:\n{input}\n\n### Response:\n",
    "prompt_no_input": "Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\n### Instruction:\n{instruction}\n\n### Response:\n",
    "response_split": "### Response:"    
}

在训练过程中,数据集里面的内容会填充到prompt_input中对应的内容,从而输入到模型进行训练。你也可以在templates下新建其他的模板文件,然后更改prompt_template_name参数即可。

除此之外,你可能还需要在finetune.py对应位置修改模型保存的间隔等参数,如下:

trainer = transformers.Trainer(
        model=model,
        train_dataset=train_data,
        eval_dataset=val_data,
        args=transformers.TrainingArguments(
            per_device_train_batch_size=micro_batch_size,
            gradient_accumulation_steps=gradient_accumulation_steps,
            warmup_steps=80,
            num_train_epochs=num_epochs,
            learning_rate=learning_rate,
            fp16=True,
            logging_steps=10,
            optim="adamw_torch",
            evaluation_strategy="steps" if val_set_size > 0 else "no",
            save_strategy="steps",
            eval_steps=50 if val_set_size > 0 else None,
            save_steps=50,
            output_dir=output_dir,
            save_total_limit=3,
            load_best_model_at_end=True if val_set_size > 0 else False,
            ddp_find_unused_parameters=False if ddp else None,
            group_by_length=group_by_length,
            report_to="wandb" if use_wandb else None,
            run_name=wandb_run_name if use_wandb else None,
        ),
        data_collator=transformers.DataCollatorForSeq2Seq(
            tokenizer, pad_to_multiple_of=8, return_tensors="pt", padding=True
        ),
    )

其中eval_steps表示验证的步数间隔,save_steps表示保存的步数间隔,warmup_steps表示学习率的warm up步数。

运行finetune.sh,如下:

bash finetune.sh

最后的运行结果为:
在这里插入图片描述
上面的450就算总共跑的steps。
最终的lora权重保存在lora-ruozhi文件夹下面,如下:
在这里插入图片描述

运行generate.py文件

得到微调模型后,如果你想看看它的效果,运行generate.py文件,它通过gradio构建可视化界面,修改前面一部分代码即可:

def main(
    load_8bit: bool = False,
    base_model: str = "",
    lora_weights: str = "/gemini/code/Project/alpaca-lora/lora-ruozhi",
    prompt_template: str = "",  # The prompt template to use, will default to alpaca.
    server_name: str = "0.0.0.0",  # Allows to listen on all interfaces by providing '0.
    share_gradio: bool = True,
):
    # 改成base model地址
    # base_model = base_model or os.environ.get("BASE_MODEL", "")
    base_model = "/gemini/pretrain"
    assert (
        base_model
    ), "Please specify a --base_model, e.g. --base_model='huggyllama/llama-7b'"

    prompter = Prompter(prompt_template)
    tokenizer = AutoTokenizer.from_pretrained(base_model)

主要修改lora_weightsbase_modellora_weights就是上面一步保存的地址。
除此之外,还要将代码中的LlamaTokenizer换成AutoTokenizer,不然会报错。
share_gradio我也修改了,让其能够生成一个共享链接,方便调试。

最后运行python generate.py,我选取了几个问题进行测试,都没有中套:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
而原始的LLama3的结果为:
在这里插入图片描述
上面这个问题它用英文回答的,不过并没有中套。

在这里插入图片描述
这个问题LLama3翻车了,没有反应过来,说明我们的微调还是有作用的。

导出Lora模型

运行python export_hf_checkpoint.pyexport_hf_checkpoint.py的需要修改的地方为:

# BASE_MODEL = os.environ.get("BASE_MODEL", None)
# 1.改成要微调的模型地址
BASE_MODEL = "/gemini/pretrain"

# 2.LlamaTokenizer换成AutoTokenizer,记得导入
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)

# 3.修改为lora微调保存的地址,就是上面微调部分部分保存的地址
lora_model = PeftModel.from_pretrained(
    base_model,
    # 修改为lora微调保存的地址
    "lora-ruozhi",
    device_map={"": "cpu"},
    torch_dtype=torch.float16,
)

# 4. 改成微调模型的输出位置
## max_shard_size表示每个文件的最大内存,因此最终的文件中会有多个safetensor文件
LlamaForCausalLM.save_pretrained(
    base_model, 
    # 改成你要输出的位置
    "./saves/lora-ruozhi", 
    state_dict=deloreanized_sd, max_shard_size="2048MB"
)

最终输出的文件夹内容为:
在这里插入图片描述

自我认知训练

修改finetune.sh,将base_model改成导出Lora模型阶段的输出地址,data_path改成自我认知数据集的地址,具体如下:

python finetune.py \
    --base_model='/gemini/code/Project/alpaca-lora/saves/lora-ruozhi' \
    --data_path='/gemini/code/datasets/self_cognition.json' \
    --cutoff_len=512 \
    --num_epochs=10 \
    --learning_rate 1e-4 \
    --batch_size=32 \
    --micro_batch_size=8 \
    --val_set_size=100 \
    --group_by_length \
    --output_dir='./lora-ruozhi-self' \
    --lora_target_modules='[q_proj,k_proj,v_proj,o_proj]' \
    --lora_r=16 \
    --lora_alpha 16 \
    --lora_dropout 0.05 \
    --train_on_inputs False \
    --prompt_template_name "alpaca" \

注意根据你自己的情况修改output_dirfinetune.py中的保存间隔等参数。

然后运行python generate.py,此时文件前面部分的地址改成为:

def main(
    load_8bit: bool = False,
    base_model: str = "",
    lora_weights: str = "/gemini/code/Project/alpaca-lora/lora-ruozhi-self",
    prompt_template: str = "",  # The prompt template to use, will default to alpaca.
    server_name: str = "0.0.0.0",  # Allows to listen on all interfaces by providing '0.
    share_gradio: bool = True,
):
    # 改成base model地址
    # base_model = base_model or os.environ.get("BASE_MODEL", "")
    base_model = "/gemini/code/Project/alpaca-lora/saves/lora-ruozhi"
    assert (
        base_model
    ), "Please specify a --base_model, e.g. --base_model='huggyllama/llama-7b'"

    prompter = Prompter(prompt_template)
    tokenizer = AutoTokenizer.from_pretrained(base_model)

因此这次自我认知训练是在弱智吧训练的模型基础上微调的,因此base_model改成了导出的Lora模型。

模型的输出结果为:
在这里插入图片描述
在这里插入图片描述
使用弱智吧微调得到的能力也没有消失:
在这里插入图片描述

  • 29
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lzl2040

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值