知识体系篇-数据标注与处理(02)模型测试与评估:自动化测试框架与工具
·
自动化测试框架与工具
专栏:人工智能训练师(三级)备考全攻略
模块:卷三·知识体系 — 第四部分·模型测试与评估
难度:⭐⭐⭐☆☆
考试权重:中频(选择+工具辨析)
一、为什么需要自动化测试?
手动测试的问题
┌─────────────────────────────────────────────────┐
│ 模型每天更新 → 手动跑几百条用例 → 耗时费力 │
│ 测试人员请假 → 无人测试 → 质量失控 │
│ 回归测试 → 每次重复劳动 → 效率低下 │
│ 人为疏忽 → 遗漏测试 → 上线出问题 │
└─────────────────────────────────────────────────┘
自动化测试的价值
✓ 每次提交自动运行,秒级反馈
✓ 覆盖面广,不易遗漏
✓ CI/CD集成,上线前自动卡控
✓ 测试报告自动生成,可追溯
二、自动化测试框架选型
2.1 主流框架对比
| 框架 | 适用模型类型 | 核心功能 | 学习成本 | 语言 |
|---|---|---|---|---|
| pytest | 所有(通用Python测试) | 单元/集成/参数化测试 | 低 | Python |
| Great Expectations | 数据+ML Pipeline | 数据质量验证、异常检测 | 中 | Python |
| DeepChecks | ML/DL模型 | 全自动模型评估、数据漂移检测 | 低 | Python |
| Model Defender | TensorFlow模型 | 对抗鲁棒性测试 | 中 | Python |
| AI Verify | AI系统 | 公平性+可解释性检测 | 中 | Python |
| LangSmith | LLM应用 | Prompt测试、Chain追踪 | 低 | Python |
| Promptfoo | LLM/Prompt | Prompt自动化评估 | 低 | JS/Python |
2.2 框架选择决策树
你的测试需求是什么?
│
├─ 数据质量验证
│ └→ Great Expectations ✅
│
├─ 传统ML/DL模型评估
│ └→ DeepChecks ✅
│
├─ LLM/Prompt测试
│ ├─ 需要Chain追踪 → LangSmith
│ └─ 需要多模型对比 → Promptfoo
│
├─ 安全性与公平性
│ └→ AI Verify ✅
│
└─ 通用自动化测试
└→ pytest + 自定义断言 ✅
三、pytest 实战:模型测试自动化
3.1 项目结构
ml_project/
├── model/
│ ├── __init__.py
│ └── classifier.py # 待测试的模型
├── tests/
│ ├── __init__.py
│ ├── conftest.py # 共享fixtures
│ ├── test_unit.py # 单元测试
│ ├── test_integration.py # 集成测试
│ ├── test_robustness.py # 鲁棒性测试
│ └── golden_set.json # 标准测试集
├── pytest.ini
└── requirements.txt
3.2 完整测试代码
# =========================================
# conftest.py — 共享测试 fixtures
# =========================================
import pytest
import numpy as np
import json
@pytest.fixture
def trained_model():
"""加载训练好的模型"""
from model.classifier import SentimentClassifier
model = SentimentClassifier.load("model/latest/")
return model
@pytest.fixture
def golden_set():
"""加载Golden Set标准测试数据"""
with open("tests/golden_set.json", "r", encoding="utf-8") as f:
return json.load(f)
@pytest.fixture
def sample_texts():
"""常用测试文本"""
return {
"positive": ["产品非常好用", "物流很快,满意", "性价比高,推荐"],
"negative": ["质量差,退货", "太糟糕了", "客服态度恶劣"],
"neutral": ["今天天气不错", "快递已发出", "订单已收到"]
}
# =========================================
# test_unit.py — 模型单元测试
# =========================================
import pytest
class TestModelUnit:
"""模型单元测试"""
def test_output_shape(self, trained_model):
"""验证输出维度"""
result = trained_model.predict(["测试文本"])
assert len(result) == 1
assert "label" in result[0]
assert "confidence" in result[0]
def test_confidence_range(self, trained_model):
"""验证置信度在[0,1]范围内"""
result = trained_model.predict(["测试文本"])
assert 0 <= result[0]["confidence"] <= 1
def test_empty_input(self, trained_model):
"""验证空输入处理"""
with pytest.raises(ValueError):
trained_model.predict([""])
def test_batch_prediction(self, trained_model):
"""验证批量预测"""
texts = ["好评", "差评", "一般"]
results = trained_model.predict(texts)
assert len(results) == 3
def test_long_text(self, trained_model):
"""验证长文本不崩溃"""
long_text = "这个产品" * 500 # 1500字
result = trained_model.predict([long_text])
assert len(result) == 1
# =========================================
# test_integration.py — Golden Set集成测试
# =========================================
class TestGoldenSet:
"""Golden Set回归测试"""
def test_golden_set_accuracy(self, trained_model, golden_set):
"""在Golden Set上验证准确率"""
correct = 0
total = len(golden_set)
for item in golden_set:
result = trained_model.predict([item["text"]])
if result[0]["label"] == item["expected_label"]:
correct += 1
accuracy = correct / total
assert accuracy >= 0.90, \
f"Golden Set准确率{accuracy:.2%}低于阈值90%"
def test_golden_set_no_regression(self, trained_model, golden_set):
"""与基线结果对比,不允许退化"""
baseline_results = json.load(
open("tests/baseline_results.json", "r")
)
current_labels = [
trained_model.predict([item["text"]])[0]["label"]
for item in golden_set
]
mismatches = sum(
1 for cur, base in zip(current_labels, baseline_results)
if cur != base
)
assert mismatches == 0, \
f"发现{mismatches}条回归用例与基线不一致"
# =========================================
# test_robustness.py — 鲁棒性测试
# =========================================
class TestRobustness:
"""鲁棒性测试"""
@pytest.mark.parametrize("perturbation", [
"add_punctuation", # 添加多余标点
"add_whitespace", # 添加多余空格
"typo", # 同音错别字
"uppercase", # 全大写
])
def test_perturbation_stability(
self, trained_model, perturbation
):
"""验证模型对文本扰动的鲁棒性"""
original = "这个产品非常好用"
perturbed = {
"add_punctuation": "这个产品非常好用!!!??",
"add_whitespace": "这 个 产 品 非 常 好 用",
"typo": "这个产口非常好用", # 错别字
"uppercase": "这个产品非常好用".upper(),
}[perturbation]
orig_result = trained_model.predict([original])[0]
pert_result = trained_model.predict([perturbed])[0]
assert orig_result["label"] == pert_result["label"], \
f"扰动类型'{perturbation}'导致分类不一致"
def test_special_characters(self, trained_model):
"""验证特殊字符不崩溃"""
special_texts = [
"<script>alert(1)</script>", # XSS攻击
"你好😊👋🎉", # Emoji
"产品\t很\t好\n换行测试", # 控制字符
"PYTHON", # 全角字符
]
for text in special_texts:
result = trained_model.predict([text])
assert len(result) == 1 # 不崩溃即可
3.3 运行测试与报告
# 运行全部测试
pytest tests/ -v
# 运行指定类型测试
pytest tests/test_robustness.py -v
# 生成HTML报告(需安装 pytest-html)
pytest tests/ -v --html=report.html --self-contained-html
# 只运行上次失败的测试
pytest tests/ --lf
# 并行运行(需安装 pytest-xdist)
pytest tests/ -n auto
四、DeepChecks:一键模型体检
# =========================================
# DeepChecks — 自动化模型评估
# pip install deepchecks
# =========================================
from deepchecks.tabular.suites import model_evaluation_suite
from deepchecks.tabular import Dataset
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
# 加载数据
data = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
data.data, data.target, test_size=0.2, random_state=42
)
# 训练模型
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# 创建DeepChecks数据集
train_ds = Dataset(X_train, label=y_train,
cat_features=[], features=data.feature_names)
test_ds = Dataset(X_test, label=y_test,
cat_features=[], features=data.feature_names)
# 运行模型评估套件(自动检测20+问题)
suite = model_evaluation_suite()
result = suite.run(train_ds, test_ds, model)
# 查看结果
result.show() # 浏览器中打开可视化报告
# 输出示例:
# ✅ Simple Model Comparison PASS
# ✅ Train Test Performance PASS
# ❌ Weak Segments Performance FAIL (发现弱势子群体)
# ⚠️ Feature Drift WARN (特征分布变化)
# ✅ New Labels PASS
五、CI/CD 集成自动化测试
5.1 完整CI/CD Pipeline
代码提交 → 自动化测试流水线
┌──────────────────────────────────────────────────────┐
│ Git Push │
│ │ │
│ ▼ │
│ ① 数据验证测试(Great Expectations) │
│ │ 通过? │
│ ├─ 否 → 阻断,发送告警 │
│ ▼ 是 │
│ ② 模型单元测试(pytest) │
│ │ 通过? │
│ ├─ 否 → 阻断 │
│ ▼ 是 │
│ ③ Golden Set回归测试(pytest + baseline对比) │
│ │ 通过? │
│ ├─ 否 → 阻断,生成差异报告 │
│ ▼ 是 │
│ ④ 鲁棒性/安全测试 │
│ │ 通过? │
│ ├─ 否 → 告警(不一定阻断) │
│ ▼ 是 │
│ ⑤ DeepChecks全面体检 │
│ │ │
│ ▼ │
│ ⑥ 生成测试报告 → 审批 → 部署 │
└──────────────────────────────────────────────────────┘
5.2 GitHub Actions 配置示例
# .github/workflows/model-test.yml
name: Model Testing Pipeline
on:
push:
paths:
- 'model/**'
- 'tests/**'
- 'data/**'
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: pip install -r requirements.txt
- name: Run Unit Tests
run: pytest tests/test_unit.py -v --junitxml=unit-results.xml
- name: Run Golden Set Tests
run: pytest tests/test_integration.py -v --junitxml=integration-results.xml
- name: Run Robustness Tests
run: pytest tests/test_robustness.py -v --junitxml=robustness-results.xml
- name: Generate Report
if: always()
uses: dorny/test-reporter@v1
with:
name: Model Test Results
path: '*.xml'
reporter: java-junit
- name: DeepChecks Evaluation
run: python scripts/run_deepchecks.py
六、考试重点总结
6.1 工具辨析
| 工具 | 一句话定位 | 适用场景 |
|---|---|---|
| pytest | Python通用测试框架 | 所有模型的基础测试 |
| DeepChecks | 一键模型体检 | 传统ML/DL模型全面评估 |
| Great Expectations | 数据质量守门人 | 数据Pipeline验证 |
| LangSmith | LLM应用调试平台 | Prompt测试、Chain追踪 |
| Promptfoo | Prompt评估工具 | 多模型/多Prompt对比 |
6.2 高频选择题
Q: 以下哪个工具最适合做LLM的Prompt测试?
A: LangSmith 或 Promptfoo ✅
Q: DeepChecks 的核心功能是?
A: 自动化模型评估,检测数据漂移、弱子群体等问题 ✅
Q: CI/CD中,模型回归测试应在哪个阶段运行?
A: 每次代码/模型/数据变更后自动触发 ✅
Q: Golden Set的作用是?
A: 作为基线数据集,对比当前模型输出检测退化 ✅
Q: pytest 中 @pytest.mark.parametrize 的作用是?
A: 参数化测试,用不同输入跑同一测试逻辑 ✅
七、思维导图
📌 备考贴士:工具辨析题是重点,记住每个工具的"一句话定位"即可。pytest 是所有测试的基础框架必须掌握,DeepChecks 做模型全面评估是近年新考点,LangSmith/Promptfoo 是 LLM 时代的新工具。CI/CD 集成流程图也常考简答题。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)