【一起來學AI大模型】微調技術:LoRA(Low-Rank Adaptation) 的實戰應用

?LoRA(Low-Rank Adaptation)?的實戰應用,使用 Hugging Face 的?peft?(Parameter-Efficient Fine-Tuning)?庫對大型語言模型進行高效微調。LoRA 因其顯著降低資源消耗(顯存和計算)同時保持接近全量微調性能的特點,成為當前最熱門的微調技術之一。

核心思想回顧:

LoRA 的核心假設是:模型在適應新任務時,權重的改變具有低秩特性。它不直接微調原始的大型權重矩陣?W?(維度?d x k),而是學習兩個更小的低秩矩陣?A?(維度?d x r) 和?B?(維度?r x k),其中?r << min(d, k)(秩?r?通常很小,如 8, 16, 32)。微調時,原始權重?W?被凍結(不更新),只更新?A?和?B。前向傳播變為:

h = Wx + BAx = (W + BA)x
  • Wx:凍結的原始模型計算。

  • BAx:LoRA 適配器引入的低秩更新計算。

LoRA 的優勢:

  1. 大幅降低顯存占用:?只存儲和更新?A?和?B?(r * (d + k)?個參數) 的梯度/優化器狀態,而非全量?W?(d * k?個參數) 的。顯存節省可達?90% 以上(尤其對于 Attention 的 Q/K/V/O 矩陣)。

  2. 減少計算開銷:?額外計算?BAx?相對于原始?Wx?很小。

  3. 模塊化與輕量級:?訓練后,可以將?BA?加到原始?W?中部署,也可以保持分離。保存的 LoRA 權重通常只有?幾十 MB

  4. 減少過擬合風險:?更少的可訓練參數本身就是一種正則化。

  5. 易于任務切換:?同一個基礎模型上可以訓練多個不同的 LoRA 適配器,運行時根據需要動態加載。

  6. 與量化結合(QLoRA):?可與 4-bit 量化(如 bitsandbytes)結合,實現?在消費級 GPU(如 24GB)上微調 10B+ 模型

實戰流程(使用 Hugging Face Transformers + peft + bitsandbytes (可選 QLoRA)):

環境準備:

pip install torch transformers accelerate  # 基礎環境
pip install peft                          # PEFT 核心庫
pip install bitsandbytes                  # 用于 4-bit 量化 (QLoRA)
pip install datasets                      # 加載和處理數據集
pip install trl                           # (可選) Hugging Face 的強化學習庫,包含一些訓練工具
pip install wandb                         # (可選) 實驗跟蹤

1. 導入必要的庫

import torch
from transformers import (AutoModelForCausalLM,      # 用于因果LM (如 GPT, LLaMA)AutoTokenizer,             # 分詞器TrainingArguments,         # 訓練參數配置Trainer,                   # 訓練器BitsAndBytesConfig,        # 4-bit 量化配置 (QLoRA)
)
from peft import (LoraConfig,                # LoRA 參數配置get_peft_model,            # 將基礎模型轉換為 PEFT 模型prepare_model_for_kbit_training,  # (QLoRA) 準備模型進行 k-bit 訓練
)
from datasets import load_dataset  # 加載數據集
import wandb  # 可選,用于監控

2. 加載基礎模型和分詞器

  • 選擇模型:?選擇一個開源預訓練模型(如?meta-llama/Llama-2-7b-hf,?bigscience/bloom-7b1,?gpt2-xl,?tiiuae/falcon-7b)。確保你有訪問權限(如 LLaMA 2 需要申請)。

  • 加載模型:

    • 全精度/半精度 (FP16/BF16):

      model_name = "meta-llama/Llama-2-7b-hf"
      tokenizer = AutoTokenizer.from_pretrained(model_name)
      tokenizer.pad_token = tokenizer.eos_token  # 為兼容性設置 pad_token
      model = AutoModelForCausalLM.from_pretrained(model_name,torch_dtype=torch.bfloat16,  # 或 torch.float16device_map="auto",           # 多 GPU 自動分配trust_remote_code=True,      # 如果模型需要
      )

    • QLoRA (4-bit 量化):?使用?BitsAndBytesConfig?顯著降低顯存需求。

      bnb_config = BitsAndBytesConfig(load_in_4bit=True,              # 加載 4-bit 量化模型bnb_4bit_quant_type="nf4",      # 量化類型 (推薦 nf4)bnb_4bit_compute_dtype=torch.bfloat16,  # 計算時使用 bfloat16bnb_4bit_use_double_quant=True, # 嵌套量化,進一步節省顯存
      )
      model = AutoModelForCausalLM.from_pretrained(model_name,quantization_config=bnb_config,  # 應用量化配置device_map="auto",trust_remote_code=True,
      )
      model = prepare_model_for_kbit_training(model)  # 關鍵!準備模型進行 k-bit 訓練
      tokenizer = AutoTokenizer.from_pretrained(model_name)
      tokenizer.pad_token = tokenizer.eos_token

3. 配置 LoRA (核心步驟)

使用?LoraConfig?定義 LoRA 的參數:

peft_config = LoraConfig(r=8,                     # LoRA 秩 (關鍵超參數)。值越小越省資源,但能力可能越弱。常用 8, 16, 32, 64。lora_alpha=32,           # LoRA 縮放因子 (關鍵超參數)。通常設置為 `r` 的 2-4 倍。控制新學到的知識對原始知識的相對重要性。target_modules=["q_proj", "v_proj"],  # 應用 LoRA 的目標模塊名稱列表 (極其重要!)# 常見目標模塊 (取決于模型架構):#   LLaMA/GPT-like: ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "down_proj", "up_proj"]#   BLOOM: ["query_key_value", "dense", "dense_h_to_4h", "dense_4h_to_h"]#   通常只選 `query` (`q_proj`) 和 `value` (`v_proj`) 效果就不錯且省資源。lora_dropout=0.05,       # LoRA 層的 Dropout 概率,防止過擬合。bias="none",             # 是否訓練偏置。'none' (不訓練), 'all' (訓練所有), 'lora_only' (只訓練LoRA相關的偏置)。task_type="CAUSAL_LM",   # 任務類型。對于文本生成是 "CAUSAL_LM"。也可以是 "SEQ_CLS", "TOKEN_CLS" 等。
)
  • target_modules?查找技巧:

    • 查看模型的?model.print_trainable_parameters()?輸出(在下一步之后),確認目標模塊是否被正確找到和替換。

    • 查看模型架構文檔 (model.config.architectures) 或直接打印?model?的結構。

    • 常用庫如?peft?的?get_peft_model?函數有時會打印可用的模塊名。

4. 創建 PEFT 模型

將基礎模型包裝成支持 LoRA 的 PEFT 模型:

model = get_peft_model(model, peft_config)

5. (可選,但推薦) 打印可訓練參數

檢查 LoRA 是否成功應用且凍結了大部分參數:

model.print_trainable_parameters()
# 期望輸出類似:
# trainable params: 4,194,304 || all params: 6,738,415,616 || trainable%: 0.062205960660696904

6. 準備數據集

  • 加載數據集:?使用?datasets?庫加載你的任務數據集(如指令跟隨、對話、特定領域文本)。

  • 格式化和分詞:?將數據集格式化為模型期望的輸入格式(通常是包含?text?字段)。使用?tokenizer?進行分詞和填充。

  • 關鍵 - 模板化:?對于指令微調,使用清晰模板包裝輸入輸出(例如?"### Instruction:\n{instruction}\n\n### Response:\n{response}"?+?EOS?token)。

  • 示例:

def tokenize_function(examples):# 使用模板構造完整文本texts = [f"### Instruction:\n{inst}\n\n### Response:\n{resp}{tokenizer.eos_token}"for inst, resp in zip(examples['instruction'], examples['response'])]# 分詞,注意 truncation 和 paddingresult = tokenizer(texts, max_length=512, truncation=True, padding="max_length")# 創建 labels 字段 (用于計算損失)。通常將 input_ids 復制給 labels,但將 padding 和 instruction 部分的 token 設置為 -100 (被忽略)。result["labels"] = result["input_ids"].copy()return result# 加載數據集 (示例)
dataset = load_dataset("your_dataset_name_or_path")
tokenized_datasets = dataset.map(tokenize_function, batched=True)
# 劃分 train/eval
train_dataset = tokenized_datasets["train"]
eval_dataset = tokenized_datasets["validation"]  # 如果有的話

7. 配置訓練參數 (TrainingArguments)

training_args = TrainingArguments(output_dir="./lora-finetuned-model",  # 輸出目錄 (保存模型、日志等)per_device_train_batch_size=4,        # 每個 GPU/TPU 核心的訓練批次大小 (根據顯存調整,QLoRA 下可增大)per_device_eval_batch_size=4,         # 評估批次大小gradient_accumulation_steps=4,        # 梯度累積步數 (模擬更大的批次大小)learning_rate=2e-5,                   # 學習率 (LoRA 通常比全量微調大,1e-5 到 5e-5 常見)num_train_epochs=3,                   # 訓練輪數weight_decay=0.01,                    # 權重衰減optim="paged_adamw_8bit",             # 優化器 (推薦用于穩定性,尤其 QLoRA)# optim="adamw_torch",                # 常規優化器 (非 QLoRA)lr_scheduler_type="cosine",           # 學習率調度器 (cosine, linear等)warmup_ratio=0.03,                    # 預熱比例 (總步數的比例)logging_dir="./logs",                 # 日志目錄logging_steps=10,                     # 每多少步記錄一次日志save_steps=500,                       # 每多少步保存一次檢查點evaluation_strategy="steps" if eval_dataset is not None else "no",  # 評估策略eval_steps=200 if eval_dataset is not None else None,  # 評估步數report_to="wandb",                    # 報告工具 (可選: "wandb", "tensorboard")fp16=True,                            # 半精度訓練 (FP16) - 如果 GPU 支持# bf16=True,                          # 或者 BF16 (如果 Ampere+ GPU 支持)tf32=True,                            # 在 Ampere+ GPU 上啟用 TF32 數學gradient_checkpointing=True,          # 梯度檢查點 (用計算時間換顯存)
)

關鍵參數說明:

  • gradient_accumulation_steps:將多個小批次的梯度累積起來再更新參數,模擬大 batch size。

  • gradient_checkpointing:顯著減少訓練顯存(約 60-70%),但會增加約 20% 的訓練時間。強烈推薦開啟

  • fp16/bf16:半精度訓練,節省顯存加速訓練。

  • optim="paged_adamw_8bit"bitsandbytes?提供的 8-bit AdamW 優化器,在 QLoRA 訓練中非常穩定且節省顯存

8. 創建?Trainer?并開始訓練

trainer = Trainer(model=model,args=training_args,train_dataset=train_dataset,eval_dataset=eval_dataset,  # 如果沒有驗證集,設為 Nonetokenizer=tokenizer,# 可選:定義 data_collator (如 DataCollatorForLanguageModeling),但通常默認足夠
)# 開始訓練!
trainer.train()# 保存最終模型 (只保存 LoRA 權重)
trainer.model.save_pretrained(training_args.output_dir)
# 也可以保存完整模型 (基礎模型 + LoRA 權重合并)
# merged_model = model.merge_and_unload()
# merged_model.save_pretrained("merged_lora_model")

9. (訓練后) 加載和使用 LoRA 模型

  • 僅加載 LoRA 適配器 (運行時動態加載):

from peft import PeftModelbase_model = AutoModelForCausalLM.from_pretrained("base_model_name", ...)  # 加載基礎模型
peft_model = PeftModel.from_pretrained(base_model, "./lora-finetuned-model")  # 加載 LoRA 權重# 使用 peft_model 進行推理
inputs = tokenizer("### Instruction:\nWhat is AI?\n\n### Response:\n", return_tensors="pt")
outputs = peft_model.generate(**inputs, max_new_tokens=50)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
  • 加載合并后的完整模型:?如果你之前運行了?merge_and_unload()?并保存了完整模型,可以直接像普通模型一樣加載使用:

    merged_model = AutoModelForCausalLM.from_pretrained("merged_lora_model", ...)
    # ... 進行推理 ...

LoRA 實戰關鍵技巧與注意事項:

  1. target_modules?選擇:?這是影響效果最重要的配置之一。對于 decoder-only (GPT/LLaMA) 模型,通常優先選擇?q_proj?和?v_proj。添加?o_projdown_projup_projgate_proj?可能提升效果但會增加可訓練參數。encoder-decoder 模型 (如 T5) 需要分別指定 encoder 和 decoder 的模塊。實驗是找到最佳組合的關鍵!

  2. 秩?r?和 Alpha?lora_alpha

    • r:值越大,LoRA 表達能力越強,越接近全量微調,但參數和計算開銷也越大。常用范圍 8-64。任務越復雜/數據量越大,r?可能需要越大。

    • alpha:控制 LoRA 更新的幅度相對于原始預訓練權重的比例。經驗法則:alpha = 2 * r?或?alpha = r?是比較好的起點。實際效果?scale = alpha / r?更重要。scale?太大可能導致不穩定,太小可能導致學習不足。

  3. 數據集質量與模板:?對于指令微調,清晰、一致的提示模板 (### Instruction:,?### Response:,?EOS?token) 至關重要。數據質量直接影響最終模型效果。

  4. 學習率:?LoRA 通常可以使用比全量微調更大的學習率(如?1e-5?到?5e-5?vs?1e-6?到?5e-6)。嘗試在?1e-52e-55e-5?之間調整。

  5. 批次大小與梯度累積:?在有限顯存下,使用較小的?per_device_train_batch_size?配合較大的?gradient_accumulation_steps?來模擬大 batch size(如 16, 32),通常有助于穩定訓練和提升最終性能。

  6. 開啟梯度檢查點:?gradient_checkpointing=True?是?在消費級 GPU 上訓練大模型(即使使用 LoRA/QLoRA)的關鍵

  7. QLoRA (bitsandbytes):?對于在 24GB 或更小顯存的 GPU 上訓練 7B/13B 模型,QLoRA 幾乎是必備的。確保正確使用?BitsAndBytesConfig?和?prepare_model_for_kbit_training

  8. 評估與早停:?使用驗證集監控損失和任務特定指標(如困惑度、BLEU、ROUGE 或人工評估)。設置?evaluation_strategy?和?eval_steps,考慮在驗證指標不再提升時早停 (EarlyStoppingCallback,需額外實現)。

  9. 實驗跟蹤:?使用?wandb?或?tensorboard?記錄超參數、訓練損失、評估指標,方便分析和復現結果。

  10. 資源監控:?訓練時使用?nvidia-smi?或?gpustat?監控 GPU 顯存占用和利用率。

總結:

使用 Hugging Face?peft?庫實現 LoRA 微調是一個高效且相對直接的過程。核心步驟包括:加載(量化)模型 -> 配置?LoraConfig?(重點是?r,?alpha,?target_modules) -> 創建 PEFT 模型 -> 準備數據集(注意模板)-> 配置?TrainingArguments?(開啟梯度檢查點和梯度累積) -> 使用?Trainer?訓練 -> 保存和加載 LoRA 權重。通過合理選擇?target_modules、調整?r/alpha、利用 QLoRA 和梯度檢查點,你可以在資源有限的設備上高效地微調大型語言模型,使其適應你的特定任務。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88784.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88784.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88784.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

RedisJSON 內存占用剖析與調優

一、基礎內存模型指針包裝 所有 JSON 值&#xff08;標量、對象、數組、字符串等&#xff09;至少占用 8 字節&#xff0c;用于存儲一個帶類型標記的指針。標量與空容器 null、true、false、小整數&#xff08;靜態緩存&#xff09;、空字符串、空數組、空對象 均不分配額外內存…

【LeetCode 熱題 100】23. 合并 K 個升序鏈表——(解法一)逐一合并

Problem: 23. 合并 K 個升序鏈表 題目&#xff1a;給你一個鏈表數組&#xff0c;每個鏈表都已經按升序排列。 請你將所有鏈表合并到一個升序鏈表中&#xff0c;返回合并后的鏈表。 文章目錄整體思路完整代碼時空復雜度時間復雜度&#xff1a;O(K * N)空間復雜度&#xff1a;O(1…

垃圾收集器-Serial Old

第一章 引言1.1 JVM 中垃圾收集的簡要概述JVM&#xff08;Java Virtual Machine&#xff09;作為 Java 程序的運行時環境&#xff0c;負責將字節碼加載至內存并執行&#xff0c;同時也承擔著內存管理的重任。垃圾收集&#xff08;Garbage Collection&#xff0c;簡稱 GC&#x…

Docker(02) Docker-Compose、Dockerfile鏡像構建、Portainer

Docker-Compose 1、Docker Desktop 在Windows上安裝Docker服務&#xff0c;可以使用Docker Desktop這個應用程序。 下載并安裝這樣的一個安裝包 安裝好后&#xff1a;執行命令 docker --version 從Docker Hub提取hello-world映像并運行一個容器&#xff1a; docker run h…

大數據時代UI前端的用戶體驗設計新思維:以數據為驅動的情感化設計

hello寶子們...我們是艾斯視覺擅長ui設計和前端數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩!一、引言&#xff1a;從 “經驗設計” 到 “數據共情” 的體驗革命傳統 UI 設計常陷入 “設計師主觀經…

TypeScript 學習手冊

1.TypeScript 概念 TypeScript&#xff08;簡稱 TS&#xff0c;靜態類型&#xff09;是微軟公司開發的一種基于 JavaScript &#xff08;簡稱 JS&#xff0c;動態類型&#xff09;語言的編程語言。TypeScript 可以看成是 JavaScript 的超集&#xff08;superset&#xff09;&a…

掌握現代CSS:變量、變形函數與動態計算

CSS近年來發展迅速&#xff0c;引入了許多強大的功能&#xff0c;如變量、高級變形函數和動態計算能力。本文將深入探討如何在CSS中設置并使用變量&#xff0c;以及如何有效利用translate3d、translateY和translateX等變形方法。我們還將解析var()和calc()函數的關鍵作用。一、…

貝爾量子實驗設想漏洞

1 0 1 0 1 1 0 1 0 1 1 1 0 0 1 0 帶墨鏡如果先上下交換再左右交換&#xff0c;很可能不一樣的概率是2%&#xff0c;但是因為交換誕生了一個與之前序列相同的所以不一樣概率變成1%&#xff0c;我們在測的時候不能這么測啊&#xff0c;你得看序列完…

在 Android 庫模塊(AAR)中,BuildConfig 默認不會自動生成 VERSION_CODE 和 VERSION_NAME 字段

為什么AAR庫模塊的 BuildConfig 沒有 versionCode 和 versionName&#xff1f; aar庫模塊的 BuildConfig 默認不包含版本信息 應用模塊&#xff08;com.android.application&#xff09;會自動生成 versionCode 和 versionName 到 BuildConfig。但庫模塊&#xff08;com.androi…

強化學習 (11)隨機近似

計算均值的新方法有兩種方法。第一種方法很直接&#xff0c;即收集所有樣本后計算平均值&#xff1b;但這種方法的缺點是&#xff0c;若樣本是在一段時間內逐個收集的&#xff0c;我們必須等到所有樣本都收集完畢。第二種方法可避免此缺點&#xff0c;因為它以增量迭代的方式計…

PHP `implode` 深度解析:從基礎到高階實戰指南

文章目錄一、基礎語法與底層原理執行過程解析&#xff1a;二、性能關鍵&#xff1a;避免隱含陷阱1. 類型轉換黑盒2. 大數組內存優化3. 關聯數組處理三、高階應用場景1. SQL語句安全構建2. CSV文件生成3. 模板引擎實現四、多維數組處理方案1. 遞歸降維2. JSON轉換橋接五、性能對…

開發語言中關于面向對象和面向過程的筆記

開發語言中關于面向對象和面向過程的筆記市面主流語言分類面向過程面向對象市面主流語言分類 面向過程編程&#xff08;Procedural Programming&#xff09;&#xff1a;C語言&#xff1b;面向對象編程語言&#xff08;Object-Oriented Programming, OOP&#xff09; &#xf…

AI產品經理面試寶典第3天:技術分層、邊界與市場全景系列面試題

面試指導 面試官:請從技術實現效果的角度,解釋AI技術分層。 你的回答: AI技術分為三層。 第一層是認知層:通過圖像處理、語音識別、自然語言理解等技術,讓機器感知環境。比如攝像頭識別行人動作,麥克風捕捉用戶指令。 第二層是預測層:基于行為數據預判下一步需求。例如…

Intel英特爾ICH7R/ICH8R/ICH9R/ICH10R系列下載地址--intel_msm_8961002 下載 Version 8.9.6.1002

Intel英特爾ICH7R/ICH8R/ICH9R/ICH10R系列下載地址intel_msm_8961002 下載 Version 8.9.6.1002https://xiazai.zol.com.cn/detail/66/653449.shtml通過網盤分享的文件&#xff1a;intel_msm_8961002.zip 鏈接: https://pan.baidu.com/s/13N9ZLXWkaWaEHQ5P90Jt0g?pwd3790 提取碼…

AI(學習筆記第五課) 使用langchain進行AI開發 load documents(web)

文章目錄AI(學習筆記第五課) 使用langchain進行AI開發 load documents(web)學習內容&#xff1a;1.load documents&#xff08;web&#xff09;1.1 學習url1.2 提前安裝python的package1.2 使用WebBaseLoader進行webpage的load1.3 使用BeautifulSoup4進行webpage的部分截取1.4 …

使用macvlan實現容器的跨主機通信

使用環境&#xff1a; 兩臺運行docker的服務器 A機器網段&#xff1a;192.168.86.61 B機器網段&#xff1a;192.168.86.62 運行的容器需裝有ping指令&#xff0c; 實驗參數解釋&#xff1a; -d macvlan 指定創建網絡驅動類型 --subnet 指定子網范圍 -gateway 指定網關地址 -o p…

深度學習_全連接神經網絡

1.什么是神經網絡神經網絡中信息只向一個方向移動&#xff0c;即從輸入節點向前移動&#xff0c;通過隱藏節點&#xff0c;再向輸出節點移 動&#xff0c;網絡中沒有循環或者環。其中的基本構件是&#xff1a; 輸入層&#xff1a;即輸入x的那一層 輸出層&#xff1a;即輸出y的那…

OpenLayers使用

初學ol&#xff0c;實現了高德地圖不同圖層的切換、交互性地圖飛行以及加載本地JSON數據。說一下不同圖層切換的想法&#xff1a;1.對于標準地圖和衛星地圖&#xff1a;二者最初便掛載到map上&#xff0c;兩個圖層是疊加顯示的&#xff1b;當點擊按鈕時&#xff0c;其實是使用 …

day4--上傳圖片、視頻

1. 分布式文件系統 1.1 什么是分布式文件系統 文件系統是負責管理和存儲文件的系統軟件&#xff0c;操作系統通過文件系統提供的接口去存取文件&#xff0c;用戶通過操作系統訪問磁盤上的文件。 下圖指示了文件系統所處的位置&#xff1a; 常見的文件系統&#xff1a;FAT16/FA…

極矢量與軸矢量

物理量分為標量和矢量&#xff0c;矢量又分為極矢量和軸矢量。 矢量是既有大小又有方向并按平行四邊形法則相加的量。矢量有極矢量和軸矢量兩種&#xff0c;其間的區別是在鏡像反射變換下遵循不同的變換規律,許多物理量都是矢量,同樣,其中也有極矢量和軸矢量的區分,在力學中,例…