在哪做網(wǎng)站便宜又好關(guān)鍵詞優(yōu)化步驟簡短
今天給大家?guī)砹艘黄壴敿?xì)的教程,手把手教你如何對大語言模型進(jìn)行微調(diào)(Fine Tuning)!(代碼和詳細(xì)解釋放在后文)
目錄
大語言模型進(jìn)行微調(diào)(Fine Tuning)需要哪些步驟?
大語言模型進(jìn)行微調(diào)(Fine Tuning)訓(xùn)練過程及代碼
大語言模型進(jìn)行微調(diào)(Fine Tuning)需要哪些步驟?
大語言模型進(jìn)行微調(diào)(Fine Tuning)的主要步驟🤩
-
📚 準(zhǔn)備訓(xùn)練數(shù)據(jù)集
首先你需要準(zhǔn)備一個高質(zhì)量的訓(xùn)練數(shù)據(jù)集,最好是與你的應(yīng)用場景相關(guān)的數(shù)據(jù)??梢允俏谋緮?shù)據(jù)、對話數(shù)據(jù)等,格式一般為JSON/TXT等。 -
📦 選擇合適的基礎(chǔ)模型
接下來需要選擇一個合適的基礎(chǔ)預(yù)訓(xùn)練模型,作為微調(diào)的起點(diǎn)。常見的有GPT、BERT、T5等大模型,可根據(jù)任務(wù)場景進(jìn)行選擇。 -
?? 設(shè)置訓(xùn)練超參數(shù)
然后是設(shè)置訓(xùn)練的各種超參數(shù),比如學(xué)習(xí)率、批量大小、訓(xùn)練步數(shù)等等。選擇合理的超參數(shù)對模型效果影響很大哦。 -
🧑?💻 加載模型和數(shù)據(jù)集
使用HuggingFace等庫,把選定的基礎(chǔ)模型和訓(xùn)練數(shù)據(jù)集加載進(jìn)來。記得對數(shù)據(jù)集進(jìn)行必要的前處理和劃分。 -
? 開始模型微調(diào)訓(xùn)練
有了模型、數(shù)據(jù)集和超參數(shù)后,就可以開始模型微調(diào)訓(xùn)練了!可以使用PyTorch/TensorFlow等框架進(jìn)行訓(xùn)練。 -
💾 保存微調(diào)后的模型
訓(xùn)練結(jié)束后,別忘了把微調(diào)好的模型保存下來,方便后續(xù)加載使用哦。 -
🧪 在測試集上評估模型
最后在準(zhǔn)備好的測試集上評估一下微調(diào)后模型的效果??纯磁c之前的基礎(chǔ)模型相比,是否有明顯提升?
大語言模型進(jìn)行微調(diào)(Fine Tuning)訓(xùn)練過程及代碼
那如何使用 Lamini 庫加載數(shù)據(jù)、設(shè)置模型和訓(xùn)練超參數(shù)、定義推理函數(shù)、微調(diào)基礎(chǔ)模型、評估模型效果呢?
- 首先,導(dǎo)入必要的庫
import os
import lamini
import datasets
import tempfile
import logging
import random
import config
import os
import yaml
import time
import torch
import transformers
import pandas as pd
import jsonlinesfrom utilities import *
from transformers import AutoTokenizer
from transformers import AutoModelForCausalLM
from transformers import TrainingArguments
from transformers import AutoModelForCausalLM
from llama import BasicModelRunner
這部分導(dǎo)入了一些必需的Python庫,包括Lamini、Hugging Face的Datasets、Transformers等。
- 加載Lamini文檔數(shù)據(jù)集
dataset_name = "lamini_docs.jsonl"
dataset_path = f"/content/{dataset_name}"
use_hf = False
dataset_path = "lamini/lamini_docs"
use_hf = True
這里指定了數(shù)據(jù)集的路徑,同時設(shè)置了use_hf
標(biāo)志,表示是否使用Hugging Face的Datasets庫加載數(shù)據(jù)。
- 設(shè)置模型、訓(xùn)練配置和分詞器
model_name = "EleutherAI/pythia-70m"
training_config = { ... }
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
train_dataset, test_dataset = tokenize_and_split_data(training_config, tokenizer)
這部分指定了基礎(chǔ)預(yù)訓(xùn)練模型的名稱,并設(shè)置了訓(xùn)練配置(如最大長度等)。然后,它使用AutoTokenizer
從預(yù)訓(xùn)練模型中加載分詞器,并對分詞器進(jìn)行了一些調(diào)整。最后,它調(diào)用tokenize_and_split_data
函數(shù)對數(shù)據(jù)進(jìn)行分詞和劃分訓(xùn)練/測試集。
- 加載基礎(chǔ)模型
base_model = AutoModelForCausalLM.from_pretrained(model_name)
device_count = torch.cuda.device_count()
if device_count > 0:device = torch.device("cuda")
else:device = torch.device("cpu")
base_model.to(device)
這里使用AutoModelForCausalLM
從預(yù)訓(xùn)練模型中加載基礎(chǔ)模型,并根據(jù)設(shè)備(GPU或CPU)將模型移動到相應(yīng)的設(shè)備上。
- 定義推理函數(shù)
def inference(text, model, tokenizer, max_input_tokens=1000, max_output_tokens=100):...
這個函數(shù)用于在給定輸入文本的情況下,使用模型和分詞器進(jìn)行推理并生成輸出。它包括對輸入文本進(jìn)行分詞、使用模型生成輸出以及解碼輸出等步驟。
- 嘗試使用基礎(chǔ)模型進(jìn)行推理
test_text = test_dataset[0]['question']
print("Question input (test):", test_text)
print(f"Correct answer from Lamini docs: {test_dataset[0]['answer']}")
print("Model's answer: ")
print(inference(test_text, base_model, tokenizer))
這部分使用上一步定義的inference
函數(shù),在測試數(shù)據(jù)集的第一個示例上嘗試使用基礎(chǔ)模型進(jìn)行推理。它打印了輸入問題、正確答案和模型的輸出。
- 設(shè)置訓(xùn)練參數(shù)
max_steps = 3
trained_model_name = f"lamini_docs_{max_steps}_steps"
output_dir = trained_model_name
training_args = TrainingArguments(# Learning ratelearning_rate=1.0e-5,# Number of training epochsnum_train_epochs=1,# Max steps to train for (each step is a batch of data)# Overrides num_train_epochs, if not -1max_steps=max_steps,# Batch size for trainingper_device_train_batch_size=1,# Directory to save model checkpointsoutput_dir=output_dir,# Other argumentsoverwrite_output_dir=False, # Overwrite the content of the output directorydisable_tqdm=False, # Disable progress barseval_steps=120, # Number of update steps between two evaluationssave_steps=120, # After # steps model is savedwarmup_steps=1, # Number of warmup steps for learning rate schedulerper_device_eval_batch_size=1, # Batch size for evaluationevaluation_strategy="steps",logging_strategy="steps",logging_steps=1,optim="adafactor",gradient_accumulation_steps = 4,gradient_checkpointing=False,# Parameters for early stoppingload_best_model_at_end=True,save_total_limit=1,metric_for_best_model="eval_loss",greater_is_better=False
)
這一部分設(shè)置了訓(xùn)練的一些參數(shù),包括最大訓(xùn)練步數(shù)、輸出模型目錄、學(xué)習(xí)率等超參數(shù)。
為什么要這樣設(shè)置這些訓(xùn)練超參數(shù):
learning_rate=1.0e-5
學(xué)習(xí)率控制了模型在每個訓(xùn)練步驟中從訓(xùn)練數(shù)據(jù)中學(xué)習(xí)的速度。1e-5是一個相對較小的學(xué)習(xí)率,可以有助于穩(wěn)定訓(xùn)練過程,防止出現(xiàn)divergence(發(fā)散)的情況。
num_train_epochs=1
訓(xùn)練的輪數(shù),即讓數(shù)據(jù)在模型上循環(huán)多少次。這里設(shè)置為1,是因?yàn)槲覀冎幌脒M(jìn)行輕微的微調(diào),避免過度訓(xùn)練(overfitting)。
max_steps=max_steps
最大訓(xùn)練步數(shù),會覆蓋num_train_epochs
。這樣可以更好地控制訓(xùn)練的總步數(shù)。
per_device_train_batch_size=1
每個設(shè)備(GPU/CPU)上的訓(xùn)練批量大小。批量大小越大,內(nèi)存占用越高,但訓(xùn)練過程可能更加穩(wěn)定。
output_dir=output_dir
用于保存訓(xùn)練過程中的檢查點(diǎn)(checkpoints)和最終模型的目錄。
overwrite_output_dir=False
如果目錄已存在,是否覆蓋它。設(shè)為False可以避免意外覆蓋之前的結(jié)果。
eval_steps=120, save_steps=120
每120步評估一次模型性能,并保存模型。頻繁保存可以在訓(xùn)練中斷時恢復(fù)。
warmup_steps=1
學(xué)習(xí)率warmup步數(shù),一開始使用較小的學(xué)習(xí)率有助于穩(wěn)定訓(xùn)練早期階段。
per_device_eval_batch_size=1
評估時每個設(shè)備上的批量大小。通常與訓(xùn)練時相同。
evaluation_strategy="steps", logging_strategy="steps"
以步數(shù)為間隔進(jìn)行評估和記錄日志,而不是以epoch為間隔。
optim="adafactor"
使用Adafactor優(yōu)化器,適用于大規(guī)模語言模型訓(xùn)練。
gradient_accumulation_steps=4
梯度積累步數(shù),可以模擬使用更大批量大小的效果,節(jié)省內(nèi)存。
load_best_model_at_end=True
保存驗(yàn)證集上性能最好的那個檢查點(diǎn),作為最終模型。
metric_for_best_model="eval_loss", greater_is_better=False
根據(jù)驗(yàn)證損失評估模型,損失越小越好。
model_flops = (base_model.floating_point_ops({"input_ids": torch.zeros((1, training_config["model"]["max_length"]))})* training_args.gradient_accumulation_steps
)print(base_model)
print("Memory footprint", base_model.get_memory_footprint() / 1e9, "GB")
print("Flops", model_flops / 1e9, "GFLOPs")print(base_model)
print("Memory footprint", base_model.get_memory_footprint() / 1e9, "GB")
print("Flops", model_flops / 1e9, "GFLOPs")
這里還計算并打印了模型的內(nèi)存占用和計算復(fù)雜度(FLOPs)。
最后,使用這些參數(shù)創(chuàng)建了一個Trainer
對象,用于實(shí)際進(jìn)行模型訓(xùn)練。
trainer = Trainer(model=base_model,model_flops=model_flops,total_steps=max_steps,args=training_args,train_dataset=train_dataset,eval_dataset=test_dataset,
)
- 訓(xùn)練模型幾個步驟
training_output = trainer.train()
這一行代碼啟動了模型的微調(diào)訓(xùn)練過程,并將訓(xùn)練輸出存儲在training_output
中。
- 保存微調(diào)后的模型
save_dir = f'{output_dir}/final'
trainer.save_model(save_dir)
print("Saved model to:", save_dir)
finetuned_slightly_model = AutoModelForCausalLM.from_pretrained(save_dir, local_files_only=True)
finetuned_slightly_model.to(device)
這部分將微調(diào)后的模型保存到指定的目錄中。
然后,它使用
AutoModelForCausalLM.from_pretrained
從保存的模型中重新加載該模型,并將其移動到相應(yīng)的設(shè)備上。
- 使用微調(diào)后的模型進(jìn)行推理
test_question = test_dataset[0]['question']
print("Question input (test):", test_question)
print("Finetuned slightly model's answer: ")
print(inference(test_question, finetuned_slightly_model, tokenizer))
test_answer = test_dataset[0]['answer']
print("Target answer output (test):", test_answer)
這里使用之前定義的
inference
函數(shù),在測試數(shù)據(jù)集的第一個示例上嘗試使用微調(diào)后的模型進(jìn)行推理。
打印了輸入問題、模型輸出以及正確答案。
- 加載并運(yùn)行其他預(yù)訓(xùn)練模型
finetuned_longer_model = AutoModelForCausalLM.from_pretrained("lamini/lamini_docs_finetuned")
tokenizer = AutoTokenizer.from_pretrained("lamini/lamini_docs_finetuned")
finetuned_longer_model.to(device)
print("Finetuned longer model's answer: ")
print(inference(test_question, finetuned_longer_model, tokenizer))bigger_finetuned_model = BasicModelRunner(model_name_to_id["bigger_model_name"])
bigger_finetuned_output = bigger_finetuned_model(test_question)
print("Bigger (2.8B) finetuned model (test): ", bigger_finetuned_output)
這部分加載了另一個經(jīng)過更長時間微調(diào)的模型,以及一個更大的2.8B參數(shù)的微調(diào)模型。它使用這些模型在測試數(shù)據(jù)集的第一個示例上進(jìn)行推理,并打印出結(jié)果。