【AI大模型应用开发】【Fine-Tuning】0. 从一个例子开始学习大模型Fine-Tuning

简介: 【AI大模型应用开发】【Fine-Tuning】0. 从一个例子开始学习大模型Fine-Tuning
  • 大家好,我是同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏

本站文章一览:


Fine-Tuning,即微调。我尝试用我的理解叙述微调的含义:在原有模型的基础上,通过补充一些数据,用这些补充的数据对原有模型进行训练,训练的过程对原有模型的部分参数进行调整,从而使模型能在某些特定的场景下表现更优。

所以,大模型微调可以提高其在特定场景下的表现,同时,会降低大模型在通用场景下的能力。

今天,我们从一个简单的例子入手,先来感受下Fine-Tune微调到底是什么。这个例子可以在笔记本电脑上跑,需要的配置不高。在开始本文的实践案例前,你可以对模型训练一窍不通,本文将带你跑通整个过程,同时解释其中一些概念。

0. 环境准备

使用模型训练利器 huggingface 来进行模型训练和微调。执行以下代码进行安装:

# pip安装
pip install transformers # 安装最新的版本
# conda安装
conda install -c huggingface transformers  # 只4.0以后的版本

huggingface简介:

  • 相当于面向 NLP 模型的 Github
  • 尤其基于 transformer 的开源模型非常全
  • 封装了模型、数据集、训练器等,使模型的下载、使用、训练都非常方便

1. 加载训练数据集

这里可以直接使用datasets库中的load_dataset函数进行在线加载,只需要指定HuggingFace中的数据集名称即可。

本文以 rotten_tomatoes 数据集为例。

这是一个对电影评论进行情感分类的数据集。

  • 输入:电影评论
  • 输出:[‘负面’,‘正面’]

save_to_disk函数用来将加载的数据集保存到本地的一个目录下。

将加载到的数据集分成 train 部分和 validation 部分。

import datasets
from datasets import load_dataset
# 数据集名称
DATASET_NAME = "rotten_tomatoes" 
# 加载数据集
raw_datasets = load_dataset(DATASET_NAME)
raw_datasets.save_to_disk(os.path.join("D:\\GitHub\\LEARN_LLM\\FineTune\\FineTune1\\data", DATASET_NAME))
# 训练集
raw_train_dataset = raw_datasets["train"]
# 验证集
raw_valid_dataset = raw_datasets["validation"]

2. 加载模型

这里直接使用transformers库中AutoModelForCausalLM的from_pretrained函数,填入预训练的模型名称,然后它就会在运行过程中自动在线加载该模型。本文使用 gpt2 模型。

from transformers import AutoModelForCausalLM
# 模型名称
MODEL_NAME = "gpt2" 
# 加载模型 
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True)

3. 加载 Tokenizer

通过HuggingFace,可以指定模型名称,运行时自动下载对应Tokenizer。直接使用transformers库中AutoTokenizer的from_pretrained函数,填入对应的模型名称。

from transformers import AutoTokenizer, AutoModel
# 加载tokenizer
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
tokenizer.add_special_tokens({'pad_token': '[PAD]'})
tokenizer.pad_token_id = 0

4. 处理训练数据集

使用datasets库中的map函数进行数据处理。map函数参数如下:

map(
    function: Optional[Callable] = None,
    with_indices: bool = False,
    with_rank: bool = False,
    input_columns: Optional[Union[str, List[str]]] = None,
    batched: bool = False,
    batch_size: Optional[int] = 1000,
    drop_last_batch: bool = False,
    remove_columns: Optional[Union[str, List[str]]] = None,
    keep_in_memory: bool = False,
    load_from_cache_file: bool = True,
    cache_file_names: Optional[Dict[str, Optional[str]]] = None,
    writer_batch_size: Optional[int] = 1000,
    features: Optional[Features] = None,
    disable_nullable: bool = False,
    fn_kwargs: Optional[dict] = None,
    num_proc: Optional[int] = None,
    desc: Optional[str] = None,
)
  • 该函数通过一个映射函数function,处理Dataset中的每一个元素。如果不指定function,则默认的函数为lambda x: x。
  • 参数batched表示是否进行批处理
  • 参数batch_size表示批处理的大小,也就是每次处理多少个元素,默认为1000。
  • 参数drop_last_batch表示当最后一批的数量小于batch_size,是否处理最后一批。
  • remove_columns表示要删除的列的名称,删除列是在数据处理结束后删除,不影响function的使用

数据处理过程代码:

# 标签集
named_labels = ['neg','pos']
# 标签转 token_id
label_ids = [
    tokenizer(named_labels[i],add_special_tokens=False)["input_ids"][0] 
    for i in range(len(named_labels))
]
MAX_LEN=32   #最大序列长度(输入+输出)
DATA_BODY_KEY = "text" # 数据集中的输入字段名
DATA_LABEL_KEY = "label" #数据集中输出字段名
# 定义数据处理函数,把原始数据转成input_ids, attention_mask, labels
def process_fn(examples):
    model_inputs = {
            "input_ids": [],
            "attention_mask": [],
            "labels": [],
        }
    for i in range(len(examples[DATA_BODY_KEY])):
        inputs = tokenizer(examples[DATA_BODY_KEY][i],add_special_tokens=False)
        label = label_ids[examples[DATA_LABEL_KEY][i]]
        input_ids = inputs["input_ids"] + [tokenizer.eos_token_id, label]
        
        raw_len = len(input_ids)
        input_len = len(inputs["input_ids"]) + 1
        if raw_len >= MAX_LEN:
            input_ids = input_ids[-MAX_LEN:]
            attention_mask = [1] * MAX_LEN
            labels = [-100]*(MAX_LEN - 1) + [label]
        else:
            input_ids = input_ids + [0] * (MAX_LEN - raw_len)
            attention_mask = [1] * raw_len + [tokenizer.pad_token_id] * (MAX_LEN - raw_len)
            labels = [-100]*input_len + [label] + [-100] * (MAX_LEN - raw_len)
        model_inputs["input_ids"].append(input_ids)
        model_inputs["attention_mask"].append(attention_mask)
        model_inputs["labels"].append(labels)
    return model_inputs
# 处理训练数据集
tokenized_train_dataset = raw_train_dataset.map(
    process_fn,
    batched=True,
    remove_columns=raw_train_dataset.column_names,
    desc="Running tokenizer on train dataset",
)
# 处理验证数据集
tokenized_valid_dataset = raw_valid_dataset.map(
    process_fn,
    batched=True,
    remove_columns=raw_valid_dataset.column_names,
    desc="Running tokenizer on validation dataset",
)

5. 定义数据规整器

训练时自动将数据拆分成 Batch

# 定义数据校准器(自动生成batch)
collater = DataCollatorWithPadding(
    tokenizer=tokenizer, return_tensors="pt",
)

6. 定义训练超参

LR=2e-5         # 学习率
BATCH_SIZE=8    # Batch大小
INTERVAL=100    # 每多少步打一次 log / 做一次 eval
# 定义训练参数
training_args = TrainingArguments(
    output_dir="./output",              # checkpoint保存路径
    evaluation_strategy="steps",        # 每N步做一次eval
    overwrite_output_dir=True,
    num_train_epochs=1,                 # 训练epoch数
    per_device_train_batch_size=BATCH_SIZE,     # 每张卡的batch大小
    gradient_accumulation_steps=1,              # 累加几个step做一次参数更新
    per_device_eval_batch_size=BATCH_SIZE,      # evaluation batch size
    logging_steps=INTERVAL,             # 每INTERVAL步log 一次
    save_steps=INTERVAL,                # 每INTERVAL步保存一个checkpoint
    learning_rate=LR,                   # 学习率
)
  • 学习率:是指导我们该如何通过损失函数的梯度调整网络权重的超参数,通过设置学习率控制参数更新的速度。以下公式,在更新参数 w 时,其中 α 就是学习率。

  • Batch Size:是指在训练时,一次提供给模型的数据的数量。在训练时,模型需要对整个训练数据集进行训练,但是数据集通常很大,如果一次把整个数据集提供给模型训练,可能导致内存不足或运算时间太长。因此,我们通常将数据集分成若干个Batch,每次提供一个Batch给模型训练。Batch Size就是指一个Batch中数据的数量。
  • 训练epoch数:在训练模型时,通常会设定训练的epoch数,这意味着模型会在训练数据集上训练多少遍。训练epoch数较多意味着模型会更加充分地学习训练数据集,但同时也会增加训练时间。
  • 检查点(CheckPoints):是指通过周期性(迭代/时间)的保存模型的完整状态,在模型训练失败时,可以从保存的检查点模型继续训练,以避免训练失败时每次都需要从头开始带来的训练时间浪费。检查点模式适用于模型训练时间长、训练需要提前结束、fine-tune等场景,也可以拓展到异常时的断点续训场景。

7. 定义训练器

# 节省显存
model.gradient_checkpointing_enable()
# 定义训练器
trainer = Trainer(
    model=model, # 待训练模型
    args=training_args, # 训练参数
    data_collator=collater, # 数据校准器
    train_dataset=tokenized_train_dataset,  # 训练集
    eval_dataset=tokenized_valid_dataset,   # 验证集
    # compute_metrics=compute_metric,         # 计算自定义评估指标
)

8. 开始训练

# 开始训练
trainer.train()

全部的依赖包如下:

import datasets
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModel
from transformers import AutoModelForCausalLM
from transformers import TrainingArguments, Seq2SeqTrainingArguments
from transformers import Trainer, Seq2SeqTrainer
import transformers
from transformers import DataCollatorWithPadding
from transformers import TextGenerationPipeline
import torch
import numpy as np
import os, re
from tqdm import tqdm
import torch.nn as nn

运行成功后的样子如下,会显示当前训练进度、预计耗时等:

训练完之后:

9. 总结

本文以Hugging face上的情感分类数据集和gpt2模型为例,展示了训练过程。同时针对Hugging face训练模型的一些接口和一些概念做了简要介绍,零基础也可以跑通该例子。

总结模型训练的过程:

(1)加载数据集

(2)数据预处理

  • 将输入输出按特定格式拼接
  • 文本转 Token IDs
  • 通过 labels 标识出哪部分是输出(只有输出的 token 参与 loss 计算)

(3)加载模型

(4)加载模型的Tokenizer

(5)定义数据规整器

(6)定义训练超参:学习率、批次大小、…

(7)定义训练器

(8)开始训练

通过这个流程,你就能跑通模型训练过程。

如果觉得本文对你有帮助,麻烦点个赞和关注呗 ~~~


  • 大家好,我是同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏

本站文章一览:

相关文章
|
16小时前
|
存储 机器学习/深度学习 人工智能
RAG:AI大模型联合向量数据库和 Llama-index,助力检索增强生成技术
RAG:AI大模型联合向量数据库和 Llama-index,助力检索增强生成技术
RAG:AI大模型联合向量数据库和 Llama-index,助力检索增强生成技术
|
1天前
|
机器学习/深度学习 人工智能 自然语言处理
对大模型和AI的认识与思考
2023年,笔者也参与了各种学习和实践,从大语言模型、多模态算法,文生图(Stable Diffusion)技术,到prompt工程实践和搭建文生图(Stable Diffusion)webui实操环境。在此对谈谈对大模型和AI的认识与思考,是为总结。5月更文挑战第3天
18 1
|
1天前
|
机器学习/深度学习 存储 人工智能
构建未来:AI在持续学习系统中的应用
【5月更文挑战第6天】 随着人工智能技术的飞速发展,AI在各个领域中的应用越来越广泛。本文将探讨AI在持续学习系统中的应用,以及如何通过这种技术提高教育质量和效率。我们将讨论AI如何帮助个性化学习,提供实时反馈,以及如何通过数据分析预测学生的学习进度。此外,我们还将探讨AI在教育中的潜在挑战和解决方案。
|
1天前
|
人工智能 文字识别 语音技术
学习资料大全​ | 一起来魔搭社区学AI吧!
魔搭社区特别推出研习社栏目,包含AI前沿技术解读、模型应用最佳实践、动手做AI应用(AIGC/Agent/RAG)等主题,持续更新,代码实战点击即运行
|
5天前
|
机器学习/深度学习 人工智能
【AI 初识】什么是迁移学习,它在人工智能中有什么用?
【5月更文挑战第2天】【AI 初识】什么是迁移学习,它在人工智能中有什么用?
|
6天前
|
机器学习/深度学习 人工智能
超越Sora极限,120秒超长AI视频模型诞生!
【5月更文挑战第1天】 StreamingT2V技术突破AI视频生成界限,实现120秒超长连贯视频,超越Sora等传统模型。采用自回归方法,结合短期记忆的条件注意模块和长期记忆的外观保持模块,保证内容连贯性和动态性。在实际应用中,展示出优秀的动态性、连贯性和图像质量,但仍有优化空间,如处理复杂场景变化和连续性问题。[链接](https://arxiv.org/abs/2403.14773)
23 3
|
7天前
|
机器学习/深度学习 人工智能 自然语言处理
构建未来:AI驱动的自适应学习系统
【4月更文挑战第30天】 随着人工智能技术的迅猛发展,教育领域正经历一场由AI驱动的变革。本文将探讨一个新兴的研究领域——自适应学习系统。这种系统通过利用机器学习算法和大数据分析,能够根据学生的学习习惯、知识水平和兴趣点提供个性化的教学方案。我们首先介绍自适应学习系统的基本概念及其在现代教育中的重要性,然后详细阐述其工作原理及关键技术,包括数据挖掘、模式识别和自然语言处理等。最后,文章将分析当前自适应学习系统面临的挑战,并提出未来的发展趋势。
|
7天前
|
机器学习/深度学习 人工智能 自然语言处理
学习AI技术
【4月更文挑战第30天】学习AI技术
20 4
|
8天前
|
机器学习/深度学习 人工智能 算法
【机器学习】探究Q-Learning通过学习最优策略来解决AI序列决策问题
【机器学习】探究Q-Learning通过学习最优策略来解决AI序列决策问题
|
8天前
|
机器学习/深度学习 人工智能 监控
构建未来:AI在个性化学习路径设计中的应用
【4月更文挑战第29天】 随着人工智能(AI)的飞速发展,教育领域正经历一场由数据驱动的变革。本文聚焦于AI技术在个性化学习路径设计中的应用,探讨其如何通过精准分析学习者的行为和表现来优化教学策略和内容。我们展示了利用机器学习模型来预测学习成果、识别学习障碍以及提供即时反馈的潜力。文章还讨论了实施个性化学习所面临的挑战,包括数据隐私保护和技术整合问题,并提出了相应的解决策略。