GPT-LLM-Trainer:如何使用自己的数据轻松快速地微调和训练LLM

一、前言

想要轻松快速地使用您自己的数据微调和培训大型语言模型(LLM)?我们知道训练大型语言模型具有挑战性并需要耗费大量计算资源,包括收集和优化数据集、确定合适的模型及编写训练代码等。今天我们将介绍一种实验性新方法,实现特定任务高性能模型的训练。

我们的目标是最大程度地简化模型微调训练过程,使您能够在最短时间内从构思转化为高性能的完全训练的模型。以微调开源模型LLaMa 2为例,整个过程**++只需提供任务描述,系统便会为您生成数据集、解析成正确的数据格式并微调 LLaMA 2 模型++**。轻松实现快速的微调和推理过程!

二、GPT-LLM-Trainer 介绍

++GPT-LLM-Trainer++ 是一种全新、经济实惠且最简单的方法来训练大型语言模型。这个项目旨在探索一种新的训练高性能任务专用模型的流程,摆脱所有复杂的步骤,使你更容易从一个想法转变为完全训练好的模型。你只需输入任务描述,系统就会从头开始生成数据集,将其转换为你想要的任何格式,并为你进行模型微调。你可以在Google Colab上轻松的训练大型语言模型。GPT-LLM-Trainer 模型训练器利用 GPT-4 模型来简化整个过程,包括以下三个关键阶段:

  • 数据生成阶段:利用 GPT-4 模型根据提供的输入用例生成多样化的提示和响应数据。
  • 系统消息生成:通过为模型的交互设计最佳系统提示。
  • 微调模型过程:生成数据集后,系统会自动将其拆分为训练集和验证集,为您微调模型,并为推理做好准备。

GPT大型语言模型训练器的主要优势在于它可以摆脱复杂的步骤,让用户更容易地从一个想法转变为完全训练好的模型。你只需输入任务描述,系统就会从头开始生成数据集,将其转换为你想要的任何格式,并为你进行模型微调。在这种情况下,你将使用LLaMa 2进行微调。

三、如何使用自己的数据微调LLM

这里主要介绍如何在Google Colab上训练LLaMA 2大型语言模型的实现步骤。首先,我们需要收集和整理数据集,将其格式化并选择合适的模型。接下来,我们需要编写训练代码,并将所有这些整合在一起进行训练。这个过程可能会遇到很多困难和挑战,但是通过使用GPT大型语言模型训练器,我们可以大大简化这个过程。

3.1、描述你的模型

我们通过尝试一种新的方法,可以轻松地根据你输入的任务描述来构建特定任务的模型。首先,尽可能的使用GPU,可以在Google Colab中设置可用的 GPU,然后创建模型,只需要在提示中描述您想要构建的模型。 具有描述性且清晰。你可以通过更改 Hyperparameters 单元格中的 model_name 来更改要微调的模型。

3.2、数据生成步骤

在这里写下您的prompt提示。 描述性越强、越清晰越好!

然后,选择生成数据时使用的temperature(0 到 1 之间)。 较低的值非常适合精确的任务,例如编写代码,而较大的值更适合创造性的任务,例如编写故事。

最后,选择您想要生成的示例数量。 生成的数据越多,a) 花费的时间就越长,b) 数据生成的成本就越高。 但一般来说,更多的例子会产生更高质量的模型。 100 通常是最低启动值。

python 复制代码
prompt = "一个能够接收中文中类似猜灯谜的问题,并用经过深思熟虑、逐步推理的方式以中文回答的模型。"
temperature = .4
number_of_examples = 100

先安装OpenAI依赖。

bash 复制代码
!pip install openai

一旦你确定了提示,就可以执行下面的代码生成数据集。这可能需要比预期更长的时间。

python 复制代码
import os
import openai
import random

openai.api_key = "YOUR KEY HERE"

def generate_example(prompt, prev_examples, temperature=.5):
    messages=[
        {
            "role": "system",
            "content": f"您正在生成将用于训练机器学习模型的数据。\n\n您将获得我们想要训练的模型的高级描述,并由此生成数据样本,每个样本都有一个提示/ 响应对。\n\n您将按照以下格式执行此操作:\n````\nprompt\n------------\n$prompt_goes_here\n---------- -\n\nresponse\n-----------\n$response_goes_here\n------------\n```\n\n只能有一对提示/响应 每轮都会生成。\n\n对于每一轮,使示例比上一轮稍微复杂一点,同时确保多样性。\n\n确保您的样本是独特且多样化的,但高质量和复杂性足以训练一个良好的样本 执行模型。\n\n这是我们要训练的模型类型:\n`{prompt}`"
        }
    ]

    if len(prev_examples) > 0:
        if len(prev_examples) > 10:
            prev_examples = random.sample(prev_examples, 10)
        for example in prev_examples:
            messages.append({
                "role": "assistant",
                "content": example
            })

    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=messages,
        temperature=temperature,
        max_tokens=1354,
    )

    return response.choices[0].message['content']

# Generate examples
prev_examples = []
for i in range(number_of_examples):
    print(f'Generating example {i}')
    example = generate_example(prompt, prev_examples, temperature)
    prev_examples.append(example)

print(prev_examples)

生成完数据集,我们还需要生成系统消息。

python 复制代码
def generate_system_message(prompt):

    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
          {
            "role": "system",
            "content": "您将获得我们正在训练的模型的高级描述,并据此生成一个简单的系统提示以供该模型使用。 请记住,您不是生成用于数据生成的系统消息 - 您正在生成用于推理的系统消息。 一个好的格式是"给定 $INPUT_DATA,您将 $WHAT_THE_MODEL_SHOULD_DO。"。\n\n使其尽可能简洁。 在响应中只包含系统提示符。\n\n例如,切勿编写:`\"$SYSTEM_PROMPT_HERE\"`。\n\n应该类似于:`$SYSTEM_PROMPT_HERE`。"
          },
          {
              "role": "user",
              "content": prompt.strip(),
          }
        ],
        temperature=temperature,
        max_tokens=500,
    )

    return response.choices[0].message['content']

system_message = generate_system_message(prompt)

print(f'系统消息: `{system_message}`。 如果您想要更好的结果,请随意重新运行此单元格。')

接下来,我们将示例放入数据框中,并将它们转换为最终的数据集对。

python 复制代码
import pandas as pd

# 初始化列表以存储提示和响应
prompts = []
responses = []

# 从示例中解析出提示和响应
for example in prev_examples:
  try:
    split_example = example.split('-----------')
    prompts.append(split_example[1].strip())
    responses.append(split_example[3].strip())
  except:
    pass

# 创建数据框
df = pd.DataFrame({
    'prompt': prompts,
    'response': responses
})

# 删除重复项
df = df.drop_duplicates()

print('有 ' + str(len(df)) + ' 成功生成的示例。 以下是前几个:')

df.head()

将数据分为训练集和测试集。

python 复制代码
# 将数据分为训练集和测试集,其中 90% 在训练集中
train_df = df.sample(frac=0.9, random_state=42)
test_df = df.drop(train_df.index)

# 将数据帧保存到 .jsonl 文件
train_df.to_json('train.jsonl', orient='records', lines=True)
test_df.to_json('test.jsonl', orient='records', lines=True)

3.3、安装必要的库

bash 复制代码
!pip install -q accelerate==0.21.0 peft==0.4.0 bitsandbytes==0.40.2 transformers==4.31.0 trl==0.4.7
python 复制代码
import os
import torch
from datasets import load_dataset
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    BitsAndBytesConfig,
    HfArgumentParser,
    TrainingArguments,
    pipeline,
    logging,
)
from peft import LoraConfig, PeftModel
from trl import SFTTrainer

3.4、定义超参数

python 复制代码
model_name = "NousResearch/llama-2-7b-chat-hf" # 如果您有权访问官方 LLaMA 2 模型"meta-llama/Llama-2-7b-chat-hf",请使用此选项,但请记住,您需要传递 Hugging Face 键参数
dataset_name = "/content/train.jsonl"
new_model = "llama-2-7b-custom"
lora_r = 64
lora_alpha = 16
lora_dropout = 0.1
use_4bit = True
bnb_4bit_compute_dtype = "float16"
bnb_4bit_quant_type = "nf4"
use_nested_quant = False
output_dir = "./results"
num_train_epochs = 1
fp16 = False
bf16 = False
per_device_train_batch_size = 4
per_device_eval_batch_size = 4
gradient_accumulation_steps = 1
gradient_checkpointing = True
max_grad_norm = 0.3
learning_rate = 2e-4
weight_decay = 0.001
optim = "paged_adamw_32bit"
lr_scheduler_type = "constant"
max_steps = -1
warmup_ratio = 0.03
group_by_length = True
save_steps = 25
logging_steps = 5
max_seq_length = None
packing = False
device_map = {"": 0}

3.5、加载数据集并训练

python 复制代码
# 加载数据集
train_dataset = load_dataset('json', data_files='/content/train.jsonl', split="train")
valid_dataset = load_dataset('json', data_files='/content/test.jsonl', split="train")

# 预处理数据集
train_dataset_mapped = train_dataset.map(lambda examples: {'text': [f'[INST] <<SYS>>\n{system_message.strip()}\n<</SYS>>\n\n' + prompt + ' [/INST] ' + response for prompt, response in zip(examples['prompt'], examples['response'])]}, batched=True)
valid_dataset_mapped = valid_dataset.map(lambda examples: {'text': [f'[INST] <<SYS>>\n{system_message.strip()}\n<</SYS>>\n\n' + prompt + ' [/INST] ' + response for prompt, response in zip(examples['prompt'], examples['response'])]}, batched=True)

compute_dtype = getattr(torch, bnb_4bit_compute_dtype)
bnb_config = BitsAndBytesConfig(
    load_in_4bit=use_4bit,
    bnb_4bit_quant_type=bnb_4bit_quant_type,
    bnb_4bit_compute_dtype=compute_dtype,
    bnb_4bit_use_double_quant=use_nested_quant,
)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map=device_map
)
model.config.use_cache = False
model.config.pretraining_tp = 1
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
peft_config = LoraConfig(
    lora_alpha=lora_alpha,
    lora_dropout=lora_dropout,
    r=lora_r,
    bias="none",
    task_type="CAUSAL_LM",
)
# 设置训练参数
training_arguments = TrainingArguments(
    output_dir=output_dir,
    num_train_epochs=num_train_epochs,
    per_device_train_batch_size=per_device_train_batch_size,
    gradient_accumulation_steps=gradient_accumulation_steps,
    optim=optim,
    save_steps=save_steps,
    logging_steps=logging_steps,
    learning_rate=learning_rate,
    weight_decay=weight_decay,
    fp16=fp16,
    bf16=bf16,
    max_grad_norm=max_grad_norm,
    max_steps=max_steps,
    warmup_ratio=warmup_ratio,
    group_by_length=group_by_length,
    lr_scheduler_type=lr_scheduler_type,
    report_to="all",
    evaluation_strategy="steps",
    eval_steps=5  # 每 20 步评估一次
)
# 设置监督微调参数
trainer = SFTTrainer(
    model=model,
    train_dataset=train_dataset_mapped,
    eval_dataset=valid_dataset_mapped,  # 在此处传递验证数据集
    peft_config=peft_config,
    dataset_text_field="text",
    max_seq_length=max_seq_length,
    tokenizer=tokenizer,
    args=training_arguments,
    packing=packing,
)
trainer.train()
trainer.model.save_pretrained(new_model)

# 单元 4:测试模型
logging.set_verbosity(logging.CRITICAL)
prompt = f"[INST] <<SYS>>\n{system_message}\n<</SYS>>\n\n编写一个反转字符串的函数。 [/INST]" # 将此处的命令替换为与您的任务相关的命令
pipe = pipeline(task="text-generation", model=model, tokenizer=tokenizer, max_length=200)
result = pipe(prompt)
print(result[0]['generated_text'])

3.6、运行推理

python 复制代码
from transformers import pipeline

prompt = f"[INST] <<SYS>>\n{system_message}\n<</SYS>>\n\n编写一个反转字符串的函数。 [/INST]" # 将此处的命令替换为与您的任务相关的命令
num_new_tokens = 100  # 更改为您想要生成的新令牌的数量

# 计算提示中的标记数量
num_prompt_tokens = len(tokenizer(prompt)['input_ids'])

# 计算一代的最大长度
max_length = num_prompt_tokens + num_new_tokens

gen = pipeline('text-generation', model=model, tokenizer=tokenizer, max_length=max_length)
result = gen(prompt)
print(result[0]['generated_text'].replace(prompt, ''))

3.7、合并模型并存储在 Google Drive 中

python 复制代码
# 合并并保存微调后的模型
from google.colab import drive
drive.mount('/content/drive')

model_path = "/content/drive/MyDrive/llama-2-7b-custom"  # 更改为您的首选路径

# 在 FP16 中重新加载模型并将其与 LoRA 权重合并
base_model = AutoModelForCausalLM.from_pretrained(
    model_name,
    low_cpu_mem_usage=True,
    return_dict=True,
    torch_dtype=torch.float16,
    device_map=device_map,
)
model = PeftModel.from_pretrained(base_model, new_model)
model = model.merge_and_unload()

# 重新加载分词器以保存它
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"

# 保存合并后的模型
model.save_pretrained(model_path)
tokenizer.save_pretrained(model_path)

3.8、从 Drive 加载微调模型并运行推理

python 复制代码
from google.colab import drive
from transformers import AutoModelForCausalLM, AutoTokenizer

drive.mount('/content/drive')

model_path = "/content/drive/MyDrive/llama-2-7b-custom"  # 更改为保存模型的路径

model = AutoModelForCausalLM.from_pretrained(model_path)
tokenizer = AutoTokenizer.from_pretrained(model_path)

3.9、测试微调训练后的模型

python 复制代码
from transformers import pipeline

prompt = "请问,哪个字一年四季都不会凋零?"  # 更改为您想要的提示
gen = pipeline('text-generation', model=model, tokenizer=tokenizer)
result = gen(prompt)
print(result[0]['generated_text'])

四、总结

本文主要介绍了如何使用GPT大型语言模型训练器来训练你自己的大型语言模型;如何利用GPT-4的强大功能来简化训练过程,并确保你的模型能够实现最佳性能;最后介绍了如何在谷歌Colab上训练大型语言模型的实用技巧和步骤。GPT-LLM-Trainer 是一款经济实惠且易于使用的工具,用于使用您自己的数据训练大型语言模型。它简化了收集、提炼、格式化、选择和训练数据集的复杂过程,并根据您的任务描述为您微调模型。使用此工具,您可以生成各种提示、优化系统提示、拆分数据集、定义超参数以及在 Google Colab 或本地 Jupyter Notebook 上高效运行推理。

五、References

相关推荐
IT古董18 分钟前
【机器学习】机器学习的基本分类-强化学习-策略梯度(Policy Gradient,PG)
人工智能·机器学习·分类
centurysee20 分钟前
【最佳实践】Anthropic:Agentic系统实践案例
人工智能
mahuifa20 分钟前
混合开发环境---使用编程AI辅助开发Qt
人工智能·vscode·qt·qtcreator·编程ai
四口鲸鱼爱吃盐21 分钟前
Pytorch | 从零构建GoogleNet对CIFAR10进行分类
人工智能·pytorch·分类
蓝天星空35 分钟前
Python调用open ai接口
人工智能·python
睡觉狂魔er35 分钟前
自动驾驶控制与规划——Project 3: LQR车辆横向控制
人工智能·机器学习·自动驾驶
scan7241 小时前
LILAC采样算法
人工智能·算法·机器学习
leaf_leaves_leaf1 小时前
win11用一条命令给anaconda环境安装GPU版本pytorch,并检查是否为GPU版本
人工智能·pytorch·python
夜雨飘零11 小时前
基于Pytorch实现的说话人日志(说话人分离)
人工智能·pytorch·python·声纹识别·说话人分离·说话人日志
爱喝热水的呀哈喽1 小时前
《机器学习》支持向量机
人工智能·决策树·机器学习