Multi-label image classifier for PonyChart character identification.
Project description
PonyChart Classifier
PonyChart 角色辨識模型,用於自動辨識 HentaiVerse 戰鬥中出現的 PonyChart 圖片中的角色。
目錄結構
ponychart-classifier/
├── app/
│ └── label_images/ # 圖片標註工具 (Tkinter GUI)
│ ├── __main__.py # 進入點
│ ├── app.py # LabelApp 主應用
│ ├── analysis.py # 模型分析 (背景推論)
│ ├── checkpoint_viewer.py # Checkpoint 資訊檢視
│ ├── constants.py # GUI 常數
│ ├── crop_handler.py # 裁切處理
│ ├── distribution_viewer.py # 角色分布統計檢視
│ ├── file_actions.py # 批次檔案操作
│ ├── file_ops.py # 檔案操作
│ ├── filter_builder.py # 篩選條件建構
│ ├── filter_panel.py # 篩選面板 UI
│ ├── image_viewer.py # 圖片顯示元件
│ ├── label_store.py # 標籤儲存
│ └── navigator.py # 圖片導覽
├── src/
│ └── ponychart_classifier/ # PyPI 套件
│ ├── __init__.py # 公開 API (predict, update, preload, get_thresholds)
│ ├── model_spec.py # 推論常數 + PredictionResult / ClassThresholds
│ ├── inference.py # PonyChartClassifier (ONNX 推論)
│ ├── _http.py # SSL-aware URL opener
│ ├── model.onnx # 隨套件發佈的 ONNX 模型
│ ├── thresholds.json # 隨套件發佈的分類閾值
│ └── training/ # 訓練函式庫
│ ├── __init__.py # Re-export 所有 symbol
│ ├── constants.py # 常數與訓練超參數 (single source of truth)
│ ├── device.py # 裝置偵測
│ ├── dataset.py # 資料載入、Dataset、transforms
│ ├── model.py # Backbone registry + build_model()
│ ├── training.py # 訓練迴圈、evaluate、threshold 優化
│ ├── checkpoint.py # Checkpoint val_f1 重新計算與更新
│ ├── sampling.py # 樣本載入與平衡
│ ├── splitting.py # Hash-based group splitting
│ ├── log_helpers.py # 日誌輔助
│ ├── script_utils.py # 腳本共用工具
│ └── export.py # ONNX 匯出
├── scripts/ # 開發用腳本 (不隨套件發佈)
│ ├── train.py # 模型訓練腳本
│ ├── compare_backbones.py # Backbone 架構比較
│ ├── compare_crops.py # 裁切圖片效果分析
│ ├── compare_pos_weight.py # pos_weight 效果比較
│ ├── compare_resolution.py # 輸入解析度比較
│ ├── compare_resume_scratch.py # Resume vs from-scratch 分析
│ ├── evaluate_holdout.py # Holdout 評估
│ ├── analyze_augmentations.py # 資料增強 ablation study
│ ├── analyze_distribution.py # 標籤分布互動式視覺化 (Flask)
│ ├── learning_curve.py # Learning curve 分析 + power-law 外推
│ ├── search_batch_lr.py # LR 超參數搜尋
│ └── profile_dataloader.py # DataLoader 效能分析
├── rawimage/ # 訓練用原始圖片 (PNG)
│ ├── labels.json # 標註資料 {"1/twilight/filename.png": [1,3]}
│ └── checkpoint.pt # PyTorch checkpoint (resume 訓練用)
├── mypy.ini # MyPy strict 設定
├── pyproject.toml
├── uv.lock
└── README.md
標籤對照
| 編號 | 角色 |
|---|---|
| 1 | Twilight Sparkle |
| 2 | Rarity |
| 3 | Fluttershy |
| 4 | Rainbow Dash |
| 5 | Pinkie Pie |
| 6 | Applejack |
安裝
# 推論用 (hbrowser 會自動安裝)
uv pip install ponychart-classifier
# 開發用 (包含訓練依賴)
uv pip install -e ".[train]"
使用方式
from ponychart_classifier import predict, preload, update, get_thresholds
from ponychart_classifier import PonyChartClassifier, PredictionResult, ClassThresholds
# 預先載入模型
preload()
# 檢查並更新模型至最新版本(比對 ETag,有新版才下載)
updated: bool = update()
# 預測圖片中的角色
result: PredictionResult = predict("path/to/image.png")
print(result.labels) # frozenset({'Rarity', 'Fluttershy'})
print(result.rarity) # 0.95
print(result.twilight_sparkle) # 0.02
# 取得各角色的分類閾值
thresholds: ClassThresholds = get_thresholds()
也可以直接使用 PonyChartClassifier 類別:
from ponychart_classifier import PonyChartClassifier
classifier = PonyChartClassifier(model_path="model.onnx", thresholds_path="thresholds.json")
result = classifier.predict("path/to/image.png", min_k=1, max_k=3)
工作流程
1. 收集圖片
將新的 PonyChart 截圖 (PNG) 放入 rawimage/ 資料夾。
2. 安裝訓練依賴
# 只需一次,標註工具與訓練皆需要
uv pip install -e ".[train]"
3. 標註圖片
uv run python -m app.label_images
4. 訓練模型
# 執行訓練 (若存在 checkpoint.pt 則自動從上次結果繼續訓練)
uv run python scripts/train.py
# 強制從頭訓練 (忽略 checkpoint,從 ImageNet 預訓練權重開始)
uv run python scripts/train.py --from-scratch
訓練完成後會覆寫 model.onnx、thresholds.json 和 checkpoint.pt,下次推論自動使用新模型。
Resume 訓練
新增圖片並標註後,直接執行 train.py 即可。腳本會自動偵測 checkpoint.pt:
- 有 checkpoint: 載入之前的模型權重,跳過 Phase 1 (head-only),直接進入 Phase 2 fine-tuning,收斂更快
- 無 checkpoint: 從 ImageNet 預訓練權重開始完整兩階段訓練
訓練超參數
所有超參數集中於 src/ponychart_classifier/training/constants.py,修改後對所有腳本生效:
| 參數 | 預設值 | 說明 |
|---|---|---|
BACKBONE |
efficientnet_b0 |
見下方支援的 backbone |
BATCH_SIZE |
64 | 批次大小 |
SEED |
42 | 隨機種子 |
PHASE1_EPOCHS |
30 | Phase 1 (head-only) 訓練輪數 |
PHASE1_PATIENCE |
5 | Phase 1 early stopping patience |
PHASE2_EPOCHS |
100 | Phase 2 (full fine-tuning) 最大訓練輪數 |
PHASE2_PATIENCE |
12 | Phase 2 early stopping patience |
LR_HEAD |
4e-3 | Head 層學習率 |
LR_FEATURES |
1.2e-4 | Backbone 特徵提取層學習率 |
LR_CLASSIFIER |
1.2e-3 | 分類器層學習率 |
VAL_SIZE |
0.15 | 驗證集比例 |
HOLDOUT_TEST_SIZE |
0.20 | Holdout 測試集比例 |
支援的 Backbone
| Backbone | 參數量 | ONNX 大小 | 說明 |
|---|---|---|---|
mobilenet_v3_small |
2.5M | ~4MB | 輕量快速 |
mobilenet_v3_large |
5.4M | ~9MB | 精度最高 |
efficientnet_b0 |
5.3M | ~11MB | 預設,精度接近 Large,但訓練較慢 |
efficientnet_b2 |
9.1M | ~18MB | 最大模型,較高精度但較慢 |
所有 backbone 都使用 ImageNet 預訓練權重 + transfer learning。
推論端使用 ONNX Runtime,backbone 更換後只需重新匯出 model.onnx,推論程式碼不需改動。
分析腳本
分析腳本使用 training/constants.py 中的超參數設定:
# 比較四種 backbone 的效果
uv run python scripts/compare_backbones.py
# 分析裁切圖片的影響
uv run python scripts/compare_crops.py
# 資料增強 ablation study
uv run python scripts/analyze_augmentations.py
# 標籤分布互動式視覺化 (Flask web UI)
uv run python scripts/analyze_distribution.py
# Learning curve 分析 (估算增加資料的邊際效益)
uv run python scripts/learning_curve.py
# LR 超參數搜尋
uv run python scripts/search_batch_lr.py
模型架構
- Backbone: 可選 MobileNetV3-Small/Large 或 EfficientNet-B0/B2 (預設 EfficientNet-B0,ImageNet 預訓練)
- 訓練策略: Phase 1 head-only + Phase 2 full fine-tuning,支援從 checkpoint 繼續訓練
- 輸出: 6 個 sigmoid 節點 (多標籤分類)
- 推論引擎: ONNX Runtime (CPU)
- 推論速度: 3-21ms / 張
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ponychart_classifier-0.4.1.tar.gz.
File metadata
- Download URL: ponychart_classifier-0.4.1.tar.gz
- Upload date:
- Size: 92.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37e97660ff4b06399a98fe1ca3da996ca4762883eaf09e6cd4aa1c984191ae78
|
|
| MD5 |
bbe7d37a6a46065b65161e23316655f5
|
|
| BLAKE2b-256 |
b7c849d98d827b5f404e2980fb084c897b3dbc7b36cb8813282ef28cfe681a44
|
Provenance
The following attestation bundles were made for ponychart_classifier-0.4.1.tar.gz:
Publisher:
publish.yml on Kuan-Lun/ponychart-classifier
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ponychart_classifier-0.4.1.tar.gz -
Subject digest:
37e97660ff4b06399a98fe1ca3da996ca4762883eaf09e6cd4aa1c984191ae78 - Sigstore transparency entry: 1235314315
- Sigstore integration time:
-
Permalink:
Kuan-Lun/ponychart-classifier@20389ba641cb7264a8e66afba9e64c76d2efef21 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Kuan-Lun
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@20389ba641cb7264a8e66afba9e64c76d2efef21 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ponychart_classifier-0.4.1-py3-none-any.whl.
File metadata
- Download URL: ponychart_classifier-0.4.1-py3-none-any.whl
- Upload date:
- Size: 40.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3143122936525834fb39dbb59e4aa56fd88843696d48395def9e55553857bb6d
|
|
| MD5 |
2589398c63674bc59e8d09990522169a
|
|
| BLAKE2b-256 |
bef4c8ef8f07499b98e833da11e0535284246984f5df3f0aa002d6e73cff746a
|
Provenance
The following attestation bundles were made for ponychart_classifier-0.4.1-py3-none-any.whl:
Publisher:
publish.yml on Kuan-Lun/ponychart-classifier
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ponychart_classifier-0.4.1-py3-none-any.whl -
Subject digest:
3143122936525834fb39dbb59e4aa56fd88843696d48395def9e55553857bb6d - Sigstore transparency entry: 1235314352
- Sigstore integration time:
-
Permalink:
Kuan-Lun/ponychart-classifier@20389ba641cb7264a8e66afba9e64c76d2efef21 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Kuan-Lun
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@20389ba641cb7264a8e66afba9e64c76d2efef21 -
Trigger Event:
push
-
Statement type: