Safetensors
Chinese
kuixing
custom_code
jslin09 commited on
Commit
d3ee595
·
verified ·
1 Parent(s): 8285908

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +197 -34
README.md CHANGED
@@ -9,7 +9,15 @@ base_model:
9
  - jslin09/KuiXing
10
  ---
11
 
12
- # 魁星 (KuiXing) — 繁體中文預訓練語言模型
 
 
 
 
 
 
 
 
13
 
14
  **魁星(KuiXing)** 是一個從零開始、以繁體中文語料預訓練的 Decoder-Only 大型語言模型。取名自中國傳統文化中掌管文章與科舉的神祇「魁星」,象徵對中文語言理解能力的追求。本專案包含完整的訓練程式碼,可在 Apple Silicon(MLX)或 NVIDIA GPU(CUDA)上執行,並輸出與 HuggingFace `transformers` 相容的模型格式。
15
 
@@ -27,6 +35,8 @@ base_model:
27
  - [訓練程式用法](#訓練程式用法)
28
  - [CLI 參數說明](#cli-參數說明)
29
  - [輸出格式與載入方式](#輸出格式與載入方式)
 
 
30
  - [程式限制](#程式限制)
31
  - [目錄結構](#目錄結構)
32
  - [授權事項](#授權事項)
@@ -73,9 +83,9 @@ Token Embedding(vocab_size × d_model)
73
  │ └── Output Projection(無 bias)
74
  ├── Residual + Dropout
75
  ├── RMSNorm
76
- ├── Feed-Forward Network(GELU
77
  │ ├── Linear: d_model → d_ff(無 bias)
78
- │ ├── GELU Activation
79
  │ ├── Dropout
80
  │ └── Linear: d_ff → d_model(無 bias)
81
  └── Residual + Dropout
@@ -122,7 +132,7 @@ Embedding dropout、Attention dropout 及殘差連接處均加入 dropout(預
122
  | `max_seq_len` | 2,048 | 最大序列長度 |
123
  | `vocab_size` | 99,384 | BPE 詞彙量 |
124
  | `dropout` | 0.1 | Dropout 比率 |
125
- | `activation` | GELU | FFN 激活函數 |
126
  | `norm` | RMSNorm | 正規化層類型 |
127
  | `pos_encoding` | Learned | 可學習的位置嵌入 |
128
 
@@ -136,7 +146,7 @@ Embedding dropout、Attention dropout 及殘差連接處均加入 dropout(預
136
  | Position Embedding | 4,915,200(4.9M) |
137
  | Attention(×12 層) | 276,480,000(276.5M) |
138
  | Feed-Forward(×12 層) | 552,960,000(553.0M) |
139
- | RMSNorm(×25 個) | 62,400 |
140
  | LM Head | 0(與 Token Embedding 共享) |
141
  | **合計** | **1,072,936,800(≈ 1.07B)** |
142
 
@@ -169,13 +179,13 @@ Embedding dropout、Attention dropout 及殘差連接處均加入 dropout(預
169
  | 有效 Batch Size | 128 | `batch_size × accum_steps` |
170
  | `learning_rate` | 3×10⁻⁴ | AdamW 峰值學習率 |
171
  | LR Schedule | Linear Warmup + Cosine Decay | |
172
- | `warmup_steps` | 250 | 線性暖身步數 |
173
  | `weight_decay` | 0.1 | AdamW L2 正則化係數 |
174
  | `betas` | (0.9, 0.95) | AdamW 動量係數 |
175
  | `eps` | 1×10⁻⁶ | AdamW 數值穩定項 |
176
  | `grad_clip` | 1.0 | 全局梯度裁剪閾值(L2 norm) |
177
  | `epochs` | 3 | 訓練回合數 |
178
- | `steps` | 30,000 | 每 epoch 最大步數 |
179
  | 混合精度 | bfloat16(CUDA)/float32(MPS)/bfloat16(MLX) | |
180
 
181
  **Weight Decay 策略:** 僅對 `dim ≥ 2` 的權重矩陣施加 weight decay;bias、RMSNorm 參數不衰減。
@@ -199,7 +209,7 @@ Embedding dropout、Attention dropout 及殘差連接處均加入 dropout(預
199
  > **需求說明:**
200
  > - float32 模型權重 ≈ 4.3 GB;加上梯度與 AdamW 狀態(各一份,共 3× 權重大小),訓練峰值顯存約 **90 GB 以上**。
201
  > - Apple Silicon 的統一記憶體由 CPU 與 GPU 共用,128 GB 為能在 MLX bfloat16 模式下穩定訓練的最低配置。
202
- > - 主機記憶體(系統 RAM)需 ≥ 64 GB,以容納分詞器訓練資料、資料集 tokenize、chunk 建構及 PyTorch 的系統側暫存空間。
203
 
204
  ### Python 套件
205
 
@@ -221,7 +231,7 @@ tqdm >= 4.65.0
221
 
222
  ```bash
223
  # 1. 複製專案
224
- git clone https://github.com/your-username/kuixing.git
225
  cd kuixing
226
 
227
  # 2. 建立虛擬環境(建議)
@@ -237,7 +247,7 @@ pip install torch
237
  # 4. 安裝 MLX(Apple Silicon 專用,建議安裝以獲得最佳性能)
238
  pip install mlx
239
 
240
- # 5. 安裝其餘套件
241
  pip install sentencepiece datasets transformers safetensors numpy matplotlib tqdm
242
  ```
243
 
@@ -248,7 +258,7 @@ pip install sentencepiece datasets transformers safetensors numpy matplotlib tqd
248
  ### 互動模式(無參數,推薦���次使用)
249
 
250
  ```bash
251
- python KuiXing_Trainer_MLT.py
252
  ```
253
 
254
  程式會自動偵測硬體環境,若有既有模型則詢問是否接續訓練及使用哪個資料集;若無既有模型則從頭開始訓練。
@@ -257,22 +267,22 @@ python KuiXing_Trainer_MLT.py
257
 
258
  ```bash
259
  # 從頭訓練(強制忽略已存在的模型)
260
- python KuiXing_Trainer_MLT.py --from-scratch
261
 
262
  # 直接接續訓練(不互動詢問,使用 config 預設資料集)
263
- python KuiXing_Trainer_MLT.py --resume
264
 
265
  # 接續訓練並切換到新資料集
266
- python KuiXing_Trainer_MLT.py --resume --dataset jslin09/other_dataset --column text
267
 
268
  # 以新資料集從頭訓練
269
- python KuiXing_Trainer_MLT.py --from-scratch --dataset your_org/dataset_name --column article
270
 
271
  # 獨立繪圖模式(讀取訓練記錄後生成曲線圖,不啟動訓練)
272
- python KuiXing_Trainer_MLT.py --plot
273
 
274
  # 訓練摘要模式(顯示 loss / perplexity 統計後結束,不啟動訓練)
275
- python KuiXing_Trainer_MLT.py --summary
276
  ```
277
 
278
  ---
@@ -297,19 +307,19 @@ python KuiXing_Trainer_MLT.py --summary
297
  ============================================================
298
  🏁 KuiXing 訓練完成摘要
299
  ============================================================
300
- 總記錄步數 : 2,811 步(optimizer update)
301
  訓練 Epoch : 3
302
- 學習率範圍 : 0.00e+00 → 3.00e-04
303
- 梯度被裁剪次數 : 51 次(佔 1.8%)
304
  ============================================================
305
- 最終 Loss : 2.741243
306
- 最終 Perplexity : 15.5062
307
  ============================================================
308
- 最佳 Loss : 2.639037 (第 81,311 步)
309
- 最佳 Perplexity : 13.9997
310
  ============================================================
311
- 末 100 步平均 Loss : 2.784486
312
- 末 100 步平均 PPL : 16.1915
313
  ============================================================
314
  ```
315
 
@@ -373,6 +383,152 @@ model = AutoModelForCausalLM.from_pretrained(
373
 
374
  ---
375
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  ## 程式限制
377
 
378
  使用本訓練程式前,請了解以下限制:
@@ -393,7 +549,9 @@ model = AutoModelForCausalLM.from_pretrained(
393
  - PyTorch(CUDA/MPS)與 MLX(Apple Silicon)的 checkpoint 格式不同,無法直接互換。MLX checkpoint 以 `.npz` 儲存,PyTorch checkpoint 以 `.pt` 儲存。
394
 
395
  **Tokenizer 字型依賴**
396
- - 訓練曲線繪圖功能依賴本地安裝的繁體中文字型(Noto Sans CJK TC),字型路徑硬編碼於程式中。若路徑不符繪圖將失敗或顯示亂碼。**此設定不應修改**(程式設計刻意保留)。
 
 
397
 
398
  **資料集格式**
399
  - 目前僅支援 HuggingFace `datasets` 格式的文字資料集,需指定文字欄位名稱。不支援本地 jsonl、txt、csv 直接輸入(需先上傳至 HuggingFace 或自行修改 `build_chunks()` 函式)。
@@ -409,21 +567,26 @@ model = AutoModelForCausalLM.from_pretrained(
409
 
410
  ```
411
  ./
412
- ├── KuiXing_Trainer_MLT.py # 主訓練程式
413
 
414
  ├── kuixing_tokenizer/ # Tokenizer 檔案(自動生成)
415
  │ ├── tokenizer.model
416
  │ └── tokenizer.vocab
417
 
418
  ├── kuixing_checkpoints/ # 訓練 Checkpoint(自動生成)
419
- │ ├── ckpt_ep0_step500.pt
420
- │ ├── ckpt_ep0_step1000.pt
421
- ── ...(保留最新 3 個)
 
 
422
 
423
  ├── kuixing_logs/ # 訓練記錄(自動生成)
424
  │ ├── training_log.jsonl # 每步指標(loss, lr, grad_norm, ...)
425
  │ └── training_curves.png # 訓練曲線圖(每 200 步更新)
426
 
 
 
 
427
  └── kuixing_model/ # 最終輸出(訓練完成後生成)
428
  ├── model.safetensors
429
  ├── config.json
@@ -438,12 +601,12 @@ model = AutoModelForCausalLM.from_pretrained(
438
 
439
  ### 程式碼授權
440
 
441
- 本專案訓練程式碼(`KuiXing_Trainer_MLT.py` 及相關檔案)以 **MIT License** 授權,允許自由使用、修改與散布,包含商業用途,惟需保留原始版權聲明。
442
 
443
  ```
444
  MIT License
445
 
446
- Copyright (c) 2025 Chun-Hsien Lin
447
 
448
  Permission is hereby granted, free of charge, to any person obtaining a copy
449
  of this software and associated documentation files (the "Software"), to deal
@@ -491,7 +654,7 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
491
  若您在研究或作品中使用了 KuiXing,請引用本專案:
492
 
493
  ```bibtex
494
- @misc{kuixing2026,
495
  author = {Chun-Hsien Lin},
496
  title = {KuiXing: A Traditional Chinese Pre-trained Language Model},
497
  year = {2026},
 
9
  - jslin09/KuiXing
10
  ---
11
 
12
+ # 魁星 KuiXing — 繁體中文預訓練語言模型
13
+
14
+ <p align="center">
15
+ <img src="https://img.shields.io/badge/語言-繁體中文-red?style=flat-square" />
16
+ <img src="https://img.shields.io/badge/架構-Decoder--Only Transformer-blue?style=flat-square" />
17
+ <img src="https://img.shields.io/badge/參數量-1.07B-green?style=flat-square" />
18
+ <img src="https://img.shields.io/badge/框架-PyTorch%20%7C%20MLX-orange?style=flat-square" />
19
+ <img src="https://img.shields.io/badge/授權-CC BY--NC 4.0-lightgrey?style=flat-square" />
20
+ </p>
21
 
22
  **魁星(KuiXing)** 是一個從零開始、以繁體中文語料預訓練的 Decoder-Only 大型語言模型。取名自中國傳統文化中掌管文章與科舉的神祇「魁星」,象徵對中文語言理解能力的追求。本專案包含完整的訓練程式碼,可在 Apple Silicon(MLX)或 NVIDIA GPU(CUDA)上執行,並輸出與 HuggingFace `transformers` 相容的模型格式。
23
 
 
35
  - [訓練程式用法](#訓練程式用法)
36
  - [CLI 參數說明](#cli-參數說明)
37
  - [輸出格式與載入方式](#輸出格式與載入方式)
38
+ - [接續訓練與 Replay Buffer](#接續訓練與-replay-buffer)
39
+ - [模型存檔策略](#模型存檔策略)
40
  - [程式限制](#程式限制)
41
  - [目錄結構](#目錄結構)
42
  - [授權事項](#授權事項)
 
83
  │ └── Output Projection(無 bias)
84
  ├── Residual + Dropout
85
  ├── RMSNorm
86
+ ├── Feed-Forward Network(SiLU
87
  │ ├── Linear: d_model → d_ff(無 bias)
88
+ │ ├── SiLU Activation
89
  │ ├── Dropout
90
  │ └── Linear: d_ff → d_model(無 bias)
91
  └── Residual + Dropout
 
132
  | `max_seq_len` | 2,048 | 最大序列長度 |
133
  | `vocab_size` | 99,384 | BPE 詞彙量 |
134
  | `dropout` | 0.1 | Dropout 比率 |
135
+ | `activation` | SiLU | FFN 激活函數 |
136
  | `norm` | RMSNorm | 正規化層類型 |
137
  | `pos_encoding` | Learned | 可學習的位置嵌入 |
138
 
 
146
  | Position Embedding | 4,915,200(4.9M) |
147
  | Attention(×12 層) | 276,480,000(276.5M) |
148
  | Feed-Forward(×12 層) | 552,960,000(553.0M) |
149
+ | RMSNorm(×25 個) | 60,000 |
150
  | LM Head | 0(與 Token Embedding 共享) |
151
  | **合計** | **1,072,936,800(≈ 1.07B)** |
152
 
 
179
  | 有效 Batch Size | 128 | `batch_size × accum_steps` |
180
  | `learning_rate` | 3×10⁻⁴ | AdamW 峰值學習率 |
181
  | LR Schedule | Linear Warmup + Cosine Decay | |
182
+ | `warmup_steps` | 50 | 線性暖身步數 |
183
  | `weight_decay` | 0.1 | AdamW L2 正則化係數 |
184
  | `betas` | (0.9, 0.95) | AdamW 動量係數 |
185
  | `eps` | 1×10⁻⁶ | AdamW 數值穩定項 |
186
  | `grad_clip` | 1.0 | 全局梯度裁剪閾值(L2 norm) |
187
  | `epochs` | 3 | 訓練回合數 |
188
+ | `steps` | 3,000 | 每 epoch 最大步數 |
189
  | 混合精度 | bfloat16(CUDA)/float32(MPS)/bfloat16(MLX) | |
190
 
191
  **Weight Decay 策略:** 僅對 `dim ≥ 2` 的權重矩陣施加 weight decay;bias、RMSNorm 參數不衰減。
 
209
  > **需求說明:**
210
  > - float32 模型權重 ≈ 4.3 GB;加上梯度與 AdamW 狀態(各一份,共 3× 權重大小),訓練峰值顯存約 **90 GB 以上**。
211
  > - Apple Silicon 的統一記憶體由 CPU 與 GPU 共用,128 GB 為能在 MLX bfloat16 模式下穩定訓練的最低配置。
212
+ > - 主機記憶體(系統 RAM)需 ≥ 64 GB,以容納資料集 tokenize、chunk 建構及 PyTorch 的系統側暫存空間。
213
 
214
  ### Python 套件
215
 
 
231
 
232
  ```bash
233
  # 1. 複製專案
234
+ git clone https://github.com/jslin/KuiXing.git
235
  cd kuixing
236
 
237
  # 2. 建立虛擬環境(建議)
 
247
  # 4. 安裝 MLX(Apple Silicon 專用,建議安裝以獲得最佳性能)
248
  pip install mlx
249
 
250
+ # 5. 安裝其餘依
251
  pip install sentencepiece datasets transformers safetensors numpy matplotlib tqdm
252
  ```
253
 
 
258
  ### 互動模式(無參數,推薦���次使用)
259
 
260
  ```bash
261
+ python KuiXing_Trainer_SiLU.py
262
  ```
263
 
264
  程式會自動偵測硬體環境,若有既有模型則詢問是否接續訓練及使用哪個資料集;若無既有模型則從頭開始訓練。
 
267
 
268
  ```bash
269
  # 從頭訓練(強制忽略已存在的模型)
270
+ python KuiXing_Trainer_SiLU.py --from-scratch
271
 
272
  # 直接接續訓練(不互動詢問,使用 config 預設資料集)
273
+ python KuiXing_Trainer_SiLU.py --resume
274
 
275
  # 接續訓練並切換到新資料集
276
+ python KuiXing_Trainer_SiLU.py --resume --dataset jslin09/other_dataset --column text
277
 
278
  # 以新資料集從頭訓練
279
+ python KuiXing_Trainer_SiLU.py --from-scratch --dataset your_org/dataset_name --column article
280
 
281
  # 獨立繪圖模式(讀取訓練記錄後生成曲線圖,不啟動訓練)
282
+ python KuiXing_Trainer_SiLU.py --plot
283
 
284
  # 訓練摘要模式(顯示 loss / perplexity 統計後結束,不啟動訓練)
285
+ python KuiXing_Trainer_SiLU.py --summary
286
  ```
287
 
288
  ---
 
307
  ============================================================
308
  🏁 KuiXing 訓練完成摘要
309
  ============================================================
310
+ 總記錄步數 : 90,000 步(optimizer update)
311
  訓練 Epoch : 3
312
+ 學習率範圍 : 1.20e-06 → 3.00e-04
313
+ 梯度被裁剪次數 : 1,234 次(佔 1.4%)
314
  ============================================================
315
+ 最終 Loss : 3.421500
316
+ 最終 Perplexity : 30.6310
317
  ============================================================
318
+ 最佳 Loss : 3.198200 (第 87,400 步)
319
+ 最佳 Perplexity : 24.4702
320
  ============================================================
321
+ 末 100 步平均 Loss : 3.390000
322
+ 末 100 步平均 PPL : 29.7000
323
  ============================================================
324
  ```
325
 
 
383
 
384
  ---
385
 
386
+ ## 接續訓練與 Replay Buffer
387
+
388
+ ### 災難性遺忘問題
389
+
390
+ 以 `--resume` 接續訓練指定新資料集時,若不加任何防護,模型容易忘記原始語料(如台灣維基百科)的語法與知識,只學會新資料集的風格,此現象稱為**災難性遺忘(Catastrophic Forgetting)**。
391
+
392
+ ### Replay Buffer 機制
393
+
394
+ KuiXing 訓練程式內建 **Replay Buffer** 機制,在接續訓練時自動於每個 mini-batch 中混入一定比例的舊語料樣本,使模型同時學習新舊知識,有效緩解遺忘問題。
395
+
396
+ ```
397
+ 每個 mini-batch(batch_size = 4):
398
+ ┌─────────────────────────────────────┐
399
+ │ 新語料樣本 × 3 (80%,n_new) │
400
+ │ 舊語料樣本 × 1 (20%,n_replay) │ ← Replay Buffer
401
+ └─────────────────────────────────────┘
402
+ 混合後隨機打散順序,再送入模型
403
+ ```
404
+
405
+ ### 啟動條件(全自動,無需額外 CLI 參數)
406
+
407
+ Replay Buffer 在以下條件**同時成立**時自動啟用,無需任何額外操作:
408
+
409
+ | 條件 | 說明 |
410
+ |------|------|
411
+ | 使用 `--resume` 接續訓練 | 從頭訓練(`--from-scratch`)不啟用 |
412
+ | 新資料集與 `replay_dataset` **不同** | 相同資料集接續時自動略過並印出提示 |
413
+ | `replay_ratio > 0.0` | 設為 `0.0` 可手動停用 |
414
+
415
+ 啟用後,程式會在訓練開始前印出確認訊息:
416
+
417
+ ```
418
+ 🔁 Replay Buffer 已啟用:每批 4 筆中 1 筆來自舊語料(20%),3 筆來自新語料。
419
+ ```
420
+
421
+ ### 舊語料快取機制
422
+
423
+ 為避免每次接續訓練都重新下載並 tokenize 舊語料,Replay Buffer 採用磁碟快取:
424
+
425
+ - **第一次**:自動下載舊語料、tokenize、切塊,儲存為 `.npy` 快取檔
426
+ - **之後每次**:直接讀取快取,秒速完成,無需重新處理
427
+
428
+ 快取儲存於 `./kuixing_replay_cache/`,檔名包含資料集名稱與 chunk size,可安全保留供多次訓練共用。
429
+
430
+ ### 相關設定參數(`KuiXingConfig`)
431
+
432
+ | 參數 | 預設值 | 說明 |
433
+ |------|--------|------|
434
+ | `replay_ratio` | `0.2` | 每個 mini-batch 中舊語料所佔比例(0.0 = 停用) |
435
+ | `replay_dataset` | `"jslin09/wikipedia_tw"` | 舊語料的 HuggingFace 資料集名稱 |
436
+ | `replay_column` | `"article"` | 舊語料的文章欄位名稱 |
437
+ | `replay_cache_dir` | `"./kuixing_replay_cache"` | 舊語料 chunk 快取目錄 |
438
+
439
+ > **調整比例:** `replay_ratio = 0.2` 代表 20% 舊語料、80% 新語料,一般建議範圍為 0.1–0.3。比例過高會拖慢新語料的學習速度;過低則防遺忘效果有限。
440
+
441
+ ### 操作範例
442
+
443
+ ```bash
444
+ # 以新資料集接續訓練(Replay Buffer 自動啟用,混入 20% 維基百科舊語料)
445
+ python KuiXing_Trainer_SiLU.py --resume --dataset jslin09/other_dataset --column text
446
+
447
+ # 若想停用 Replay Buffer,在 KuiXingConfig 中將 replay_ratio 設為 0.0
448
+ # self.replay_ratio = 0.0
449
+ ```
450
+
451
+ ---
452
+
453
+ ## 模型存檔策略
454
+
455
+ ### 概覽
456
+
457
+ KuiXing 訓練程式同時維護兩種存檔,各有不同用途:
458
+
459
+ | 檔案 | 存放位置 | 用途 | 保留數量 |
460
+ |------|----------|------|----------|
461
+ | `ckpt_ep*_step*.pt` | `kuixing_checkpoints/` | 意外中斷後接續訓練 | 最多 3 份(滾動刪除) |
462
+ | `ckpt_best.pt` | `kuixing_checkpoints/` | 最終 HuggingFace 輸出來源 | 固定 1 份(覆蓋更新) |
463
+ | `mlx_ckpt_best.npz` | `kuixing_checkpoints/` | MLX 路徑的最佳版本 | 固定 1 份(覆蓋更新) |
464
+
465
+ ### 最佳模型判斷:滑動平均 loss
466
+
467
+ 程式以**近 100 個 optimizer step 的 loss 平均值**作為判斷依據,而非單步 loss。採用滑動平均的原因:
468
+
469
+ - 單步 loss 受 batch 取樣影響,存在隨機雜訊
470
+ - 單步最低 ≠ 泛化能力最好;滑動平均能反映模型真實的學習趨勢
471
+ - 有效過濾掉「剛好抽到簡單 batch」所造成的虛假最低點
472
+
473
+ ### 觸發條件
474
+
475
+ 每次常規存檔(每 `save_interval = 200` 步)時同步比較:
476
+
477
+ ```
478
+ if optimizer_step >= best_ckpt_min_steps (預設 100): # 跳過冷卻期
479
+ avg_loss = mean(losses[-100:]) # 計算滑動平均
480
+ if avg_loss < 歷史最佳滑動平均 loss:
481
+ 覆蓋寫入 ckpt_best.pt # 僅此時才有 I/O
482
+ 印出 🏆 更新訊息
483
+ else:
484
+ 不做任何事(零 I/O)
485
+ ```
486
+
487
+ **冷卻期設計(`best_ckpt_min_steps = 100`):** 訓練初期 loss 快速下降但尚未穩定,冷卻期內不觸發最佳存檔,避免存到不具代表性的早期版本。
488
+
489
+ ### I/O 影響評估
490
+
491
+ | 情境 | 實際 I/O 頻率 | 說明 |
492
+ |------|--------------|------|
493
+ | 訓練初期(loss 快速下降) | 每 200 步最多一次 | 受 `save_interval` 限制 |
494
+ | 訓練中後期(loss 趨於平穩) | 幾乎不觸發 | 滑動平均鮮少繼續改善 |
495
+ | 沒有改善時 | 零 I/O | 完全不寫入 |
496
+
497
+ 結論:**不會成為 I/O bound 程式**,對訓練速度的影響可忽略不計。
498
+
499
+ ### 最終輸出行為
500
+
501
+ 訓練完成後,程式**優先載入 `ckpt_best.pt`** 再進行 HuggingFace 格式輸出,而非直接使用記憶體中訓練結束當下的模型:
502
+
503
+ ```
504
+ 訓練迴圈結束
505
+
506
+ 嘗試載入 kuixing_checkpoints/ckpt_best.pt
507
+ ├── 成功 → 印出 🏆 最佳滑動平均 loss 數值,以最佳版本輸出
508
+ └── 失敗或不存在 → 印出 ℹ️ 提示,以當前模型 fallback 輸出
509
+
510
+ _export_model() → kuixing_model/model.safetensors
511
+ ```
512
+
513
+ ### 相關設定參數(`KuiXingConfig`)
514
+
515
+ | 參數 | 預設值 | 說明 |
516
+ |------|--------|------|
517
+ | `save_interval` | `200` | 常規 checkpoint 存檔間隔(步數) |
518
+ | `max_checkpoints` | `3` | 常規 checkpoint 最多保留份數 |
519
+ | `best_ckpt_window` | `100` | 滑動平均視窗大小(optimizer steps) |
520
+ | `best_ckpt_min_steps` | `100` | 開始比較最佳 loss 的最小步數(冷卻期) |
521
+
522
+ ### 注意事項
523
+
524
+ > ⚠️ **接續訓練時的最佳 checkpoint 覆蓋問題**
525
+ >
526
+ > 使用 `--resume` 接續訓練時,若舊的 `ckpt_best.pt` 仍存在於 `kuixing_checkpoints/`,新一輪訓練的滑動平均 loss 必須**低於舊輪次的最佳值**才會觸發覆蓋。
527
+ >
528
+ > 若新語料訓練後 loss 整體偏高(例如難度較高的領域語料),有可能整輪訓練都不觸發更新,最終輸出的仍是前一輪的最佳版本。這在大多數情況下是**正確行為**(舊版本確實更好),但若您明確希望輸出新語料訓練的版本,請在接續訓練前手動刪除 `kuixing_checkpoints/ckpt_best.pt`。
529
+
530
+ ---
531
+
532
  ## 程式限制
533
 
534
  使用本訓練程式前,請了解以下限制:
 
549
  - PyTorch(CUDA/MPS)與 MLX(Apple Silicon)的 checkpoint 格式不同,無法直接互換。MLX checkpoint 以 `.npz` 儲存,PyTorch checkpoint 以 `.pt` 儲存。
550
 
551
  **Tokenizer 字型依賴**
552
+ - 訓練曲線繪圖功能依賴本地安裝的繁體中文字型(Noto Sans TC),字型路徑與檔名硬編碼於程式中。若路徑或檔名不符��繪圖將失敗或顯示亂碼。
553
+ - 字型下載網址:[Noto Sans TC — Google Fonts](https://fonts.google.com/noto/specimen/Noto+Sans+TC?preview.script=Hant)
554
+ - ⚠️ **使用者需自行將字型檔案安裝至本機,並修改程式碼中對應的字型檔案路徑與檔名**,使其與實際安裝位置一致,繪圖功能方可正常運作。
555
 
556
  **資料集格式**
557
  - 目前僅支援 HuggingFace `datasets` 格式的文字資料集,需指定文字欄位名稱。不支援本地 jsonl、txt、csv 直接輸入(需先上傳至 HuggingFace 或自行修改 `build_chunks()` 函式)。
 
567
 
568
  ```
569
  ./
570
+ ├── KuiXing_Trainer_SiLU.py # 主訓練程式
571
 
572
  ├── kuixing_tokenizer/ # Tokenizer 檔案(自動生成)
573
  │ ├── tokenizer.model
574
  │ └── tokenizer.vocab
575
 
576
  ├── kuixing_checkpoints/ # 訓練 Checkpoint(自動生成)
577
+ │ ├── ckpt_ep0_step200.pt # 常規 checkpoint(最多保留 3 份)
578
+ │ ├── ckpt_ep0_step400.pt
579
+ ── ...(保留最新 3 個)
580
+ │ ├── ckpt_best.pt # 滑動平均 loss 最佳版本(PT/CUDA/MPS)
581
+ │ └── mlx_ckpt_best.npz # 滑動平均 loss 最佳版本(MLX)
582
 
583
  ├── kuixing_logs/ # 訓練記錄(自動生成)
584
  │ ├── training_log.jsonl # 每步指標(loss, lr, grad_norm, ...)
585
  │ └── training_curves.png # 訓練曲線圖(每 200 步更新)
586
 
587
+ ├── kuixing_replay_cache/ # Replay Buffer 快取(接續訓練時自動生成)
588
+ │ └── replay_jslin09_wikipedia_tw_2049.npy # 舊語料 chunk 快取
589
+
590
  └── kuixing_model/ # 最終輸出(訓練完成後生成)
591
  ├── model.safetensors
592
  ├── config.json
 
601
 
602
  ### 程式碼授權
603
 
604
+ 本專案訓練程式碼(`KuiXing_Trainer_SiLU.py` 及相關檔案)以 **MIT License** 授權,允許自由使用、修改與散布,包含商業用途,惟需保留原始版權聲明。
605
 
606
  ```
607
  MIT License
608
 
609
+ Copyright (c) 2026 Chun-Hsien Lin
610
 
611
  Permission is hereby granted, free of charge, to any person obtaining a copy
612
  of this software and associated documentation files (the "Software"), to deal
 
654
  若您在研究或作品中使用了 KuiXing,請引用本專案:
655
 
656
  ```bibtex
657
+ @misc{lin2026kuixing,
658
  author = {Chun-Hsien Lin},
659
  title = {KuiXing: A Traditional Chinese Pre-trained Language Model},
660
  year = {2026},