XnneHang

XnneHang

github
steam_profiles
douban

記錄指令微調 Qwen-7B-Chat

寫得有點隨意,老師給了四個選題:

  • YOLO 目標檢測 - 6 class
  • Unet 目標分割 - 3 class
  • 大模型微調
  • 基於 LSTM 的詩詞續寫.

前兩個啥也學不到,第四個做 tokenize 和數據集清洗太麻煩了.

於是乎就順勢選了第三個,以前沒做過,想着學點東西順便找點樂子,它要求的是一個能對話的醫生。但是,其實我更想做個賽博女朋友的 =-=.

女朋友只能等下次了.

本地能跑得動 lora 微調還是讓我挺開心的。數據集需要想法和參考.

指令微調#

通常是指用以下格式作為模型訓練集:

{
  "instruction": "現在你要扮演皇帝身邊的女人--甄嬛",
  "input": "你是誰?",
  "output": "家父是大理寺少卿甄遠道。"
}

有一個很有意思的模型,它用甄嬛的對話來微調大模型。它似乎叫做 Chat - 嬛嬛.

但是我這次要做的相對來說就沒那麼有意思了,是一個醫生,用來回答一些關於症狀和醫療的問題問答。可以的話我還是更想調一個賽博女友呀.

但我們本次還是先熟悉一遍流程,後面就可以隨心所欲地調了.

大模型把 tokenizer 什麼的都封裝好了,我們只需要把數據集放進去就可以了.

那些 embedding 啊,mask 啊,attention 啊,都不用考慮,倒是讓我這個懶人也能玩.

我做的 QA 對數據集:

鏈接: https://pan.baidu.com/s/1VX-ffLlXjShXJOUlkAZIwA?pwd=tv2y 提取碼: tv2y

Top3 預覽:

{
    "instruction": "頭痛頭昏十幾年前。吹風和曬太陽。吵鬧都會頭疼沒有檢查出來結果應該怎樣治療",
    "input": "",
    "output": ":考慮是神經性頭疼,是一種功能性的疾病,是由於緊張壓力或是精神因素引起的神經功能失調造成的頭痛,也有一定的遺傳因素,一般可考慮吃些中草藥川芎茶調散來治療。同時結合針灸按摩,效果會更好的。"
},
{
    "instruction": "眼睛疲勞,老睜不開乾澀",
    "input": "",
    "output": "一般是由於結膜炎症活乾炎症引起的,可以到醫院檢查一下。"
},
{
    "instruction": "女人的左胸下是什麼地?那裡痛是怎麼回事",
    "input": "",
    "output": "心臟在那個位置,心臟絞痛在那,也可能是胃痛導致的,胃痛位置比心臟偏下一點。"
}

有的問題會對應多個回答.

本身數據集來源是: zhangsheng93/cMedQA2

我只是做了一些簡單的處理,把數據集轉換成了 json 格式.

另外我清洗掉了長度超過 100 還是 150 的回答數據,因為我顯存不夠,哪怕輸入了也需要截斷.

而且這裡有兩種練法,一種是我在小數據集上面嘗試的,top100 練了 60 輪嘗試讓模型記住答案,另外一種則是我加大數據集,然後只練三四輪.

暫時沒決定好.

alt text

這個是我的一個訓練的 loss 情況,如果只練兩三輪三四輪,實際上模型只是淺淺地看了一下數據,對它原本的回答方式我覺得是改變不了多少的,雖然有朋友可能會說 LLM 的 loss 沒啥用.

但是我希望模型能夠改掉原本那種回答按點一個個把可能都列出來的那種方式,更希望是像我提供的數據集那樣只提出來一個可能,然後給出方案,我希望它能學習那種說話方式,那樣我才算達到了我微調的目的.

因為如果以後要練一個賽博女友,我不希望她這樣跟我對話:

你今天晚上要吃什麼,覺得這些不錯:

- 火鍋, 在冬天吃火鍋是最好的選擇
- 壽司, 壽司是一種日本料理(好像混入了什麼奇怪的東西吼,這個是copilot寫的)
- 烤鴨, 烤鴨是北京的特色菜
- 烤魚, 烤魚是一種湖南特色菜

我希望她直接這樣告訴我:

今天晚上吃火鍋吧,冬天吃火鍋最好了.

興奮!

promot 本身可以改變一些模型的回答方式,但是似乎無法根本地改變前一種回答方式,而我希望得到第二種。所以我選擇微調,所以,我選擇多練.

經過 Top 100 的半小時 60 輪微調,效果讓我相當經驗,在訓練集上是這樣的:

alt text
alt text

雖然燉狗肉這件事情我不是很認同,讓我有點疑惑.

alt text

似乎跟狗肉過不去了。但是多樣性是有了,我記得也有說吃六位地黃丸的 =-=.

這是 QA 對:

"instruction": "每天起床前都要流汗能治嗎?以前沒有用藥,但我有胃病。每天起床前都要流汗有這方面的偏方嗎?",
"input": "",
"output": "容易出汗多考慮氣虛,可以多用黃芪泡茶,多喝雞湯。可也適當服用一些補中益氣丸,參苓白術散和補中益氣湯丸。"

我再找一個訓練集外的試試.

alt text

還真別說,這個我認同度很高.

coplilot,你覺得夜跑比較好還是早晨跑比較好?

- 早晨跑步,早晨跑步有助於提高人體的新陳代謝,有助於減肥。
- 夜跑,夜跑有助於放鬆身心,有助於睡眠。
- 早晨跑步,早晨跑步有助於提高人體的新陳代謝,有助於減肥。
- 夜跑,夜跑有助於放鬆身心,有助於睡眠。

這個是 copilot 寫的.

你不知道晚上九點後跑步更睡不著嗎.

打住,我們接著往下做.

不過我倒是想到一個訓練方法,就是在先在小數據集上多輪,然後再在大數據集上訓練少輪,前者學說語氣,提高模型的表達能力.

但這個涉及到斷點續訓,不知道 llama-factory 是否需要額外的操作

微調的工具:#

datawhalechina/self-llm

這個倉庫把很多大模型的微調過程都用 jupyter notebook + markdown 寫好了,用戶基本上跑一遍就好了.

可以說已經夠懶了,但是實際上還是潛在很大問題的,就是隨著時間的推移,python 庫版本的更新,在 transformers>4.35.0 的版本中,就引入了一些破壞性的更改,讓很多模型按照原來的方式運行不起來.

即使嘗試和作者同步一樣的環境,也會碰到問題,比如碰到類似 win error 找不到文件的問題.

這個時候,就需要 docker 了.

在經過一天的折磨後,我果斷轉了 docker.

4060Ti16G 顯卡圖形化微調訓練通義千問 Qwen 模型(適合新手朋友)

這裡有個佬把 llama-factory 打包放進 docker 鏡像,然後我只需要安裝一下鏡像,然後就可以直接跑了.

唯一美中不足的一點是他後續追加包的時候沒有指定版本:

pip install einops transformers_stream_generator optimum auto-gptq -i https://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.tuna.tsinghua.edu.cn

這麼下默認是下最新的,如果和視頻間隔時間太長,估計會出新的問題,所以到時候我如果跑通了應該還得來吧這個版本指定一下.

不過本身 docker 中的好處就在於,甚至不用擔心在系統環境上的微小差異帶來的結果。起點已經很高了.

果然,這個東西有卡了我一個小時,不過好在,我顯卡能夠直接被調用。這解決了很多麻煩,我等我測試用的練完了記錄一下 version.

最後確定下來的版本是:

>>> import einops
>>> einops.__version__
'0.8.0'
>>> import transformers
>>> transformers.__version__
'4.34.1'

(llama-factroy) root@docker-desktop:/LLaMA-Factory# pip show transformers_stream_generator
Name: transformers-stream-generator
Version: 0.0.5

>>> import datasets
>>> datasets.__version__
'2.14.6'

(llama-factroy) root@docker-desktop:/LLaMA-Factory# pip show optimum
Name: optimum
Version: 1.23.3

(llama-factroy) root@docker-desktop:/LLaMA-Factory# pip show auto-gptq
Name: auto-gptq
Version: 0.6.0

如果寫成 requirements.txt:

einops==0.8.0
transformers==4.34.1
transformers-stream-generator==0.0.5
datasets==2.14.6
optimum==1.23.3
auto-gptq==0.6.0

另外除了這些包的問題,你還需要解決 --gpu all 的問題,如果是 windows 可以參考Windows 讓 Docker 支持 NVIDIA Container Toolkit.

做這些事情當然還是 linux 最方便,奈何我的電腦放在家裡只有 windows 可以連.

步驟:#

1. 下載數據集,放到 data 文件夾下.#

你需要一個dataset_info.json. 參考我數據集的那個網盤了鏈接.

注意點是裡面那個 sha1 的 key 不能刪,我記得這個應該是用來校驗的,但是即使我用之前遺留的也是可以的.

但是如果你刪除掉了,在 llama-factory 中,就會一直報錯 dataset_info.json cannot be found. 人

2. 下載 docker 鏡像:#

docker pull bucess/llama-factory:1

我用的並不是官網的鏡像.

它的下載可能有一點久,並且有時候有一些 layer 似乎還會卡住,但是不用擔心,找一個相對穩定的網絡環境,接上你的適配器,搭上你的梯子,然後等待即可.

有鏡像的話,每次啟動就相當快了。甚至容器都配完後,下次直接start -i 就可以了.

3. 啟動容器:#

docker run -it --name llama-factory --gpus all --network host --shm-size 4g -v D:\senmen\data:/LLaMA-Factory/data bucess/llama-factory:1 /bin/bash

你需要改得只有D:\senmen\data, 改成你數據集的位置,當然如果你夠自信的話,把模型也放進來也可以。當然不小心誤刪了就撲街了.

最好的嘗試是用docker cp進行模型的拷貝.

4. 追加 Python 包,啟動 llama-factory#

pip install einops==0.8.0 transformers==4.34.1 transformers-stream-generator==0.0.5 datasets==2.14.6 optimum==1.23.3 auto-gptq==0.6.0 -i https://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.tuna.tsinghua.edu.cn

-i https://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.tuna.tsinghua.edu.cn

這個參數還挺好使的,因為容器內似乎默認是沒有代理的,用這個的話就不用特地再設置一下臨時的http_proxy了.

修改 src/train_web.py:(可選)

在我啟動 gradio 應用後,我無法通過 ip+port 的形式在本地訪問到面板,所以我用了 gradio 的 share 參數.

(llama-factroy) root@docker-desktop:/LLaMA-Factory# cat src/train_web.py
from llmtuner import create_ui


def main():
    demo = create_ui()
    demo.queue()
    demo.launch(share=True, inbrowser=True)


if __name__ == "__main__":
    main()

值得注意的是,你需要下載一個這個:

https://cdn-media.huggingface.co/frpc-gradio-0.2/frpc_linux_amd64

它總是被 windows 報毒然後自動刪除.

你需要把它放到合適的地方,並且改名,運行 share=True 但是沒有這個文件的時候就會自動拋出,這裡不追述了。你也可以參考:

https://github.com/gradio-app/gradio/issues/8186

這裡有報錯的細節.

5. 啟動 llama-factory#

python src/train_web.py

如果執行了 4 那麼這樣它會生成一個臨時的網址,你可以在任何計算機上調用它.

類似這樣:https://d6cdc0f5cda64dd72b.gradio.live/

因為我的電腦放在家裡,而我需要在學校訓練,調用和演示,這個就很方便了.

6. 載入我們的 top100 數據集並訓練#

在這之後都是 webui 操作了,我一個寫博客的就不寫了.

你需要把 dataset_info.json 中的"name"後面改成"qa_top100.json".

具體操作可以參考: 4060Ti16G 顯卡圖形化微調訓練通義千問 Qwen 模型(適合新手朋友)

有意思的是他用到了一種做法,就是用 int4 量化模型進行訓練,最後偷天換日導出成 float32 的,不僅降低的訓練門檻,而且導出非量化模型後,推理速度變得非常快.

直接解決我最大的问题,就是我先前嘗試直接訓練非量化模型,哪怕用了 lora,batch_size 設置為 1, 依然還是爆顯存,而且還不穩定,遠程桌面黑屏,閃爍.

而經過這麼一番操作,我的 batch_size 設置成 8, 顯存佔用在 13G 左右,佔用率一直拉滿,但是不影響我遠程桌面,這就很好了.

7. 斷點續訓 (還沒做)#

這個是我最後要做的,因為我想要在小數據集上多輪,然後在大數據集上少輪,這樣模型就能夠既學會說話方式,又能夠在大數據集上學到更多的知識.

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。