在免費 google colab 跟 glow.ai 上的模型微調體驗 & 流程紀錄

note
LLM
Fine-tuning
作者

紙魚

發佈於

2026年7月8日

摘要
Fine-tuning 的極致節省版體驗。

緣起

接續上一篇文章,一開始為了寫 LLM cybersecurity 的作業又不想花 credit,於是我用免費版 google colab 來完成。1成為 credit 富翁後再來用用 glow.ai 上的設備,體驗大幅上升。這篇文章便來記錄我在免費 google colab 跟 glow.ai 上的流程跟心得。

免費 google colab 的執行流程

資料集介紹 & 目標

資料集共 18650 筆資料。我們的目標是使用微調 LoRA 技術,讓離線 LLM 可以成功分類釣魚信件。

執行步驟(Google colab 版)

記得要開 GPU

啟動 LLaMA Factory

  1. 開啟新的 google colab 裝取所需環境套件
# 1. 下載 Llama-Factory
!git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git
%cd LLaMA-Factory

# 2. 安裝依賴環境
!pip install -e ".[torch,metrics]"
!pip install --no-deps unsloth # 推薦安裝 unsloth 加速
!pip install bitsandbytes>=0.39.0 # 為了設定 Quantization bit 用
  1. 打開 google colab 的終端機輸入
llamafactory-cli webui --share 
  1. 回到 notebook 介面,新的 cell 輸入
from google.colab.output import eval_js
print("請點擊下方網址進入 Llama-Factory 介面:")
print(eval_js("google.colab.kernel.proxyPort(7860)"))

這段程式會強制 Colab 將它內部的 7860 port(也就是 Llama-Factory 跑起來的地方)映射到一個可以點擊的外部網址。

資料前處理 & 上傳到 LLaMA Factory 可以看到的地方

  1. 使用 kaggle 上的資料集下載檔後,再輸入以下
import pandas as pd
import json
import os

# 1. 讀取 Kaggle 資料集 (請確保路徑正確,此例檔名是 phishing_emails.csv)
csv_file = os.path.join(path, "Phishing_Email.csv") 
df = pd.read_csv(csv_file)

# 2. 轉換為 Llama-Factory 格式 (這裡假設欄位名稱,請根據你的 CSV 調整)
# 假設 "Email Text" 是內容,"Label" 是標籤
formatted_data = []
for _, row in df.iterrows():
    formatted_data.append({
        "instruction": "判斷這封郵件是否為釣魚郵件:",
        "input": str(row["Email Text"]),
        "output": str(row["Email Type"])
    })

# 3. 儲存到 Llama-Factory 的 data 資料夾
save_path = "/content/LLaMA-Factory/data/phishing_data.json"
with open(save_path, "w", encoding="utf-8") as f:
    json.dump(formatted_data, f, indent=2, ensure_ascii=False)

print(f"資料集已轉換並儲存至: {save_path}")

這會將資料從 .csv 轉成 .json,並且處理成 LLaMA Factory 可接受格式。

LLaMA Factory 訓練設定

  • 模型 : Qwen2.5-7B-Instruct ,因為只是辨認是否為釣魚信件(2 種可能),不必用非常大的模型應該就能處理

  • Fine-tuning method : lora

  • Quantization bit : 4,這個參數可以將模型壓縮到原來的\(\frac{1}{4}\)

  • Cutoff length: 512,主要避免內存爆掉,其次是觀察釣魚信件的特徵,關鍵通常都藏在 1-2 句話中

  • Learning rate: 5e-5

  • Epochs: 2.0 ,有足夠樣本數的情況下可以不用這麼多次

  • Batch size: 1,避免內存爆掉

  • Gradient accumulation: 32,影響 GPU 每次處理的資料

使用免費版 google colab 最需要注意內存爆掉的問題,因此設定要盡量設小,模型也要選小一點。未來如果還有需要用免費板 colab 訓練,以上設定也可以參考。2

執行結果

Loss 訓練圖

這裡 x 軸的 Step 計算方式為

\[\text{Total Steps} = \frac{\text{資料總數} \times \text{Epochs}}{\text{Total Batch Size}}\]

主要變化

  1. 11.54 (Epoch 0.01,186 筆)

  2. 7.24 (Epoch 0.02,371 筆)

  3. 3.60 (Epoch 0.03,457 筆)

  4. 2.29(Epoch 0.04,752 筆)

  5. 1.6 (Epoch 0.05,927 筆)

最後怕觸發免費 colab 的使用限制而提早停止,最終訓練到的資料共 927 筆,耗時約 2 小時,好久:(。

信件測試:

到 Chat 區載入 checkpoint path(相當於執行結果模型),進行測試

安全信件測試

釣魚信件測試

以 chat 區的結果來說全對,但當時沒用數據看結果,可惜了TT 但如果看訓練圖,會發現其實還有不小的改進空間。

在 Glows.ai 上的執行流程

這次使用的機器是 NVIDIA GeForce RTX 4090,可以用 HTTP 連線了!

資料集介紹 & 目標

  • 資料集:Kaggle 上的 Finance News Sentiments 資料集,裡面也是有兩個欄位。

  • News Text: 金融新聞內容(包含標題與一段內文)

  • Sentiment Label: 三種類別(Positive / Negative / Neutral),用於表示新聞對市場情緒的影響

共 32,569 筆,一樣使用微調 LoRA 技術,讓離線 LLM 可以成功分類新聞情緒。

執行步驟(Glows.ai 版)

  1. 開啟 HTTP port 連線

  2. 導入資料集、對資料做前處理

這一步與 google colab 類似,快速快過

!pip install kagglehub[pandas-datasets]
import kagglehub

path = kagglehub.dataset_download(
    "antobenedetti/finance-news-sentiments"
)

print(path)

import os
print(os.listdir(path))

確定檔名後測試能不能導入

import pandas as pd

csv_path = path + "/dataset.csv"

df = pd.read_csv(csv_path)

df.head()

確定 OK 後調整資料集成 LLaMA Factory 可接受格式

import pandas as pd
import json
import os

# 1. 讀取 Kaggle 資料集 (請確保路徑正確)
csv_file = os.path.join(path, "dataset.csv")
df = pd.read_csv(csv_file)

# 2. 轉換為 Llama-Factory 格式 (這裡假設欄位名稱,請根據你的 CSV 調整)
formatted_data = []
for _, row in df.iterrows():
    formatted_data.append({
        "instruction": "判斷這則財經新聞的情緒:",
        "input": str(row["text"]),
        "output": str(row["sentiment"])
    })

# 3. 儲存到 Llama-Factory 的 data 資料夾
save_path = "/LLaMA-Factory/data/news_data.json"
with open(save_path, "w", encoding="utf-8") as f:
    json.dump(formatted_data, f, indent=2, ensure_ascii=False)

print(f"資料集已轉換並儲存至: {save_path}")
  1. 調整 LLaMA-Factory\data 裡的 dataset_infon.json
{
  "news_data": {
    "file_name": "news_data.json",
    "formatting": "alpaca",
    "columns": {
      "prompt": "instruction",
      "query": "input",
      "response": "output"
    }
  },

在 LLaMA Factory 訓練

打開 LLaMA Factory 的 HTTP Port,輸入剛剛建立好的 dataset 後即可開始訓練,最終訓練設定如下:

  • Model: Qwen2.5-7B-Instruct

  • learning rate: 2e-4

  • Epochs: 1

  • Maximum gradient norm: 1

  • Max samples: 100000

  • Compute type: fp16 (重要,選錯可能會跑不動)

  • cutoff length: 256

  • batch: 16

  • Gradient accumulation: 4

速度: 2$$4=8

  • val_size: 0.2

  • LR scheduler: cosine

因為現在資源比較多,設定可以奢侈一點~這個設定只花沒幾分鐘就練好了,讚。

訓練結果

看起來不錯,至少比在 Colab 上的情況要好很多。

再來看看 perdition

setting

  • cutoff: 256

  • Max samples: 100000

  • Batch size: 16

  • Maximum new tokens: 8

  • Top-p: 0.7

  • Temperature: 0.95

評估 result:

{ “predict_bleu-4”: 0.6883751680324095, “predict_model_preparation_time”: 0.0022, “predict_rouge-1”: 0.7306242519105055, “predict_rouge-2”: 0.0, “predict_rouge-l”: 0.7260624436055612, “predict_runtime”: 266.5178, “predict_samples_per_second”: 122.255, “predict_steps_per_second”: 7.643 }

AI 附的快速簡單看法

指標 本質
BLEU-4 1~4-gram precision + brevity penalty
ROUGE-1 unigram recall
ROUGE-2 bigram recall
ROUGE-L LCS-based F1
  • BLEU:偏「寫得像不像原句(precision)」,越高越好。
  • ROUGE:偏「有沒有講到重點(recall)」,越高越好。
  • ROUGE-L:更偏「句子結構是否一致」

BLEU-4(predict_bleu-4)

BLEU 是 precision-based n-gram overlap 與 brevity penalty的結合,基本公式

\[BLEU = BP \cdot \exp\left(\sum_{n=1}^{4} w_n \log p_n\right)\]

  • \(p_n\):n-gram precision
  • \(w_n\):權重(通常 \(w_n = 1/4\)
  • BP:brevity penalty(避免生成太短的懲罰項)

其中

n-gram precision (\(p_n\)) 為

\[p_n = \frac{\sum \text{clip(count of n-gram)}}{\sum \text{count of n-gram in candidate}}\]

Brevity Penalty (BP) 為

\[ BP = \begin{cases} 1 & c > r \\ e^{(1 - r/c)} & c \le r \end{cases} \]

  • \(c\):生成句長度
  • \(r\):參考句長度

ROUGE-N(ROUGE-1 / ROUGE-2)

ROUGE 是 recall-oriented overlap的意思,公式

  1. ROUGE-N recall(核心公式)

\[ROUGE\text{-}N = \frac{\sum \text{overlap n-grams}}{\sum \text{n-grams in reference}}\]

  1. ROUGE-N precision

\[ P = \frac{\text{overlap n-grams}}{\text{n-grams in candidate}} \]

  1. ROUGE-N F1(最常用)

\[F1 = \frac{2PR}{P + R}\]

特例

ROUGE-1

  • n=1(unigram)

ROUGE-2

  • n=2(bigram)

ROUGE-L(最長共同子序列 LCS)

  1. LCS 定義

\[ LCS = \text{longest common subsequence} \]


  1. Recall

\[R_{LCS} = \frac{LCS(ref, cand)}{|ref|}\]

  1. Precision

\[P_{LCS} = \frac{LCS(ref, cand)}{|cand|}\]

  1. ROUGE-L F1

\[ROUGE\text{-}L = \frac{(1 + \beta^2) P R}{R + \beta^2 P}\]

  • 通常 \(\beta = 1\)

所以簡化版:

\[ROUGE\text{-}L = \frac{2PR}{P + R}\]

ROUGE-W(加權 LCS)

(有些 toolkit 會用)

\[ ROUGE\text{-}W = \frac{(1 + \beta^2) W_{LCS}}{...} \]

  • 強化「連續匹配片段」

ROUGE-S(skip-bigram)

就是允許跳詞的 bigram:

\[ ROUGE\text{-}S = \frac{\text{skip bigram overlap}}{\text{reference skip bigrams}} \]

ROUGE-SU(skip-bigram + unigram)

\[ ROUGE\text{-}SU = ROUGE\text{-}S + ROUGE\text{-}1 \]

整體看起來是還可以的結果。

總結

微調有個缺點是耗時較長,需求配備也較高,用免費版的 Colab 幾乎很難做出有用的結果TT,相較之下有花$$的 glow.ai 就好多了!

原理部分,LoRA 微調的原理跟從頭訓練機器學習模型的過程頗為類似,只是除了跑的時候要注意訓練情況、跟數值結果外,實際跑一次也滿重要的。

無符合的項目

腳註

  1. 但也是因為課堂給的作業目標比較簡單,不需要訓練很多筆資料就能有一定的效果,不然目標複雜一點就不行了:(。↩︎

  2. 不過應該很少人想做這件事…。↩︎