TEST_WORKFLOW.md 6.34 KB

歌词查重测试流程

本文档记录从已有歌词目录建立索引、生成测试集、批量评估和查看结果的完整命令。

1. 准备目录

已有曲库放在:

data/library/

支持文件:

.lrc
.txt

生成的测试样本会放在:

data/generated_eval/incoming/

测试集标注 CSV 会放在:

data/generated_eval/eval_100.csv

评估结果会放在:

outputs/results/

2. 建立已有曲库索引

如果刚往 data/library 新增了一批样本,建议先运行处理脚本:

python scripts/process_library.py \
  --library-dir data/library \
  --index outputs/indexes/library_lyrics.pkl

这个脚本会:

1. 扫描并隔离纯音乐占位样本,例如包含【曲库专用】或“此歌曲为没有填词的纯音乐”的文件。
2. 重建 outputs/indexes/library_lyrics.pkl。
3. 输出处理报告 outputs/results/library_process_report.json。

如果你想先看会处理哪些文件,不实际移动和重建索引:

python scripts/process_library.py \
  --library-dir data/library \
  --dry-run

如果要顺手生成并评估 500 条测试样本:

python scripts/process_library.py \
  --library-dir data/library \
  --index outputs/indexes/library_lyrics.pkl \
  --eval-size 1180 \
  --positive-ratio 0.2 \
  --eval-csv data/generated_eval/eval_1180.csv \
  --eval-out outputs/results/library_eval_1180.csv

隔离出来的文件默认会移动到:

data/quarantine/no_lyrics_placeholders/

也可以只手动建索引:

python -m lyric_dedup.cli build-index \
  --lyrics-dir data/library \
  --index outputs/indexes/library_lyrics.pkl

索引文件:

outputs/indexes/library_lyrics.pkl

注意:如果修改了 data/library,或修改了预处理/判重逻辑,需要重新执行本步骤。

3. 生成 100 条测试样本

python -m lyric_dedup.cli generate-eval-set \
  --library-dir data/library \
  --lyrics-dir data/generated_eval/incoming \
  --csv data/generated_eval/eval_500.csv \
  --size 500 \
  --positive-ratio 0.2

默认生成:

应去重: 60
不应去重: 40

生成器会先清理 data/generated_eval/incoming/ 下旧的 .txt / .lrc 生成文件,再写入新样本。

业务口径:

pos_* = 应去重,全曲歌词样式变化
neg_* = 不应去重,片段/短句碰撞/混合片段/同主题新歌词/仅翻译相似

4. 严格评估:只把 duplicate 算作去重

python -m lyric_dedup.cli evaluate-csv \
  --index outputs/indexes/library_lyrics.pkl \
  --csv data/generated_eval/eval_500.csv \
  --base-dir data/generated_eval \
  --out outputs/results/library_eval_500.csv

这个口径下:

duplicate -> 预测应去重
review    -> 预测不应去重
new       -> 预测不应去重

适合评估自动拦截的 precision,重点看:

false_positive

5. 召回评估:把 duplicate 和 review 都算作抓到可疑样本

python -m lyric_dedup.cli evaluate-csv \
  --index outputs/indexes/library_lyrics.pkl \
  --csv data/generated_eval/eval_500.csv \
  --base-dir data/generated_eval \
  --positive-decisions duplicate,review \
  --out outputs/results/library_eval_500_review_positive.csv

这个口径下:

duplicate -> 预测应去重
review    -> 预测应去重
new       -> 预测不应去重

适合评估可疑样本召回,重点看:

false_negative

6. 查看总体指标

严格口径:

cat outputs/results/library_eval_100.csv.summary.json

召回口径:

cat outputs/results/library_eval_100_review_positive.csv.summary.json

指标含义:

accuracy        总正确率
precision       预测应去重的样本里,有多少是真的应去重
recall          真实应去重的样本里,有多少被系统抓到
f1              precision 和 recall 的综合指标
true_positive   应去重且预测应去重
false_positive  不应去重但预测应去重,误杀
true_negative   不应去重且预测不应去重
false_negative  应去重但预测不应去重,漏召

7. 查看每条样本结果

open outputs/results/library_eval_100.csv

如果不能使用 open,可以直接查看 CSV:

python -c 'import csv; rows=csv.DictReader(open("outputs/results/library_eval_100.csv", encoding="utf-8")); [print(r["id"], r["decision"], r["correct"], r["reason"], sep=" | ") for r in rows]'

8. 查看失败样本

严格口径失败样本:

python -c 'import csv; rows=csv.DictReader(open("outputs/results/library_eval_100.csv", encoding="utf-8")); [print(r["id"], r["source"], r["decision"], r["reason"], sep=" | ") for r in rows if r["correct"] == "False"]'

查看某个样本的完整候选:

python -m lyric_dedup.cli check-file \
  --index outputs/indexes/library_lyrics.pkl \
  --file data/generated_eval/incoming/neg_068_mixed_fragments.txt \
  --max-candidates 10

9. 核对测试集分布

python -c 'import csv, collections; rows=list(csv.DictReader(open("data/generated_eval/eval_10.csv", encoding="utf-8"))); print(len(rows)); print(collections.Counter(r["expected"] for r in rows)); print(collections.Counter(r["sample_type"] for r in rows)); print(collections.Counter(r["sample_type"] for r in rows if r["expected"]=="应去重")); print(collections.Counter(r["sample_type"] for r in rows if r["expected"]=="不应去重"))'

核对生成目录文件数:

find data/generated_eval/incoming -type f | wc -l

10. 运行代码测试

python -m pytest tests

编译检查:

python -m compileall -q lyric_dedup tests

11. 关于测试集不重复

当前自动生成的 100 条是规则覆盖测试集,不保证样本之间规范化后完全不重复。

如果要求 100 条测试样本彼此不重复,并且仍使用默认比例:

size = 100
positive_ratio = 0.6

则至少需要:

60 首互不重复的种子歌词

原因:应去重样本是全曲变体,同一首歌的多个样式变化规范化后仍然是同一首歌。

更稳妥的真实准确率评估方式是准备人工标注 CSV:

id,file,expected
case-001,incoming/song_a.lrc,应去重
case-002,incoming/song_b.txt,不应去重

然后直接执行第 4 节或第 5 节的 evaluate-csv