Commit 03dd9219 03dd92196d55822e6cd885f1ffe25b7b0c2642ac by 沈秋雨

fix

1 parent 04c78716
......@@ -11,7 +11,7 @@ python results/fix_same_singer_samples.py \
--input results/dna_eval.csv \
--queries downloads_db/queries.csv \
--output results/dna_eval_fixed.csv \
--threshold 0.05
--threshold 0.01
"""
import argparse
......@@ -70,20 +70,21 @@ def compute_summary(rows: list[dict], threshold: float, out_path: str) -> dict:
"""计算评测指标。"""
tp = fp = tn = fn = 0
upload_ms, poll_ms, total_ms = [], [], []
by_variant: dict[str, dict] = {}
# 按 (sample_class, variant) 逐行统计,避免同一 variant 跨类混淆
by_class_variant: dict[str, dict[str, dict]] = {}
for r in rows:
pred = r.get("predicted_duplicate", "").lower() == "true"
exp = r.get("expected_duplicate", "").lower() == "true"
correct = r.get("correct", "").lower() == "true"
sample_class = r.get("sample_class", "unknown")
variant = r.get("variant", "unknown")
if variant not in by_variant:
by_variant[variant] = {"correct": 0, "total": 0, "sample_class": sample_class}
by_variant[variant]["total"] += 1
cls_dict = by_class_variant.setdefault(sample_class, {})
entry = cls_dict.setdefault(variant, {"correct": 0, "total": 0})
entry["total"] += 1
if correct:
by_variant[variant]["correct"] += 1
entry["correct"] += 1
if exp and pred:
tp += 1
......@@ -127,6 +128,12 @@ def compute_summary(rows: list[dict], threshold: float, out_path: str) -> dict:
"max": round(s[-1], 1),
}
def _variant_stats(cls_dict):
return {
v: {"accuracy": round(d["correct"] / d["total"], 4), "total": d["total"]}
for v, d in sorted(cls_dict.items())
}
return {
"total": total,
"duplicate_threshold": threshold,
......@@ -139,23 +146,9 @@ def compute_summary(rows: list[dict], threshold: float, out_path: str) -> dict:
"upload_time_ms": _stats(upload_ms),
"poll_time_ms": _stats(poll_ms),
"by_sample_class": {
cls: {
"by_variant": {
v: {"accuracy": round(d["correct"] / d["total"], 4), "total": d["total"]}
for v, d in sorted(by_variant.items())
if d["sample_class"] == cls
}
}
cls: {"by_variant": _variant_stats(by_class_variant.get(cls, {}))}
for cls in ("positive", "negative")
},
"by_variant": {
v: {
"sample_class": d["sample_class"],
"accuracy": round(d["correct"] / d["total"], 4),
"total": d["total"],
}
for v, d in sorted(by_variant.items())
},
"out": out_path,
}
......@@ -196,7 +189,7 @@ def main():
print(f"原始行数: {len(rows)}")
removed = []
relabeled = []
kept = []
for r in rows:
if r.get("sample_class") != "negative":
......@@ -214,23 +207,30 @@ def main():
main_dur = main_durations.get(song_id)
cover_dur = cover_durations.get(r.get("audio_path", ""))
is_same_recording = False
if main_dur and cover_dur:
diff_ratio = abs(cover_dur - main_dur) / main_dur
if diff_ratio < args.threshold:
removed.append(r)
continue
is_same_recording = abs(cover_dur - main_dur) / main_dur < args.threshold
elif main_dur:
# 没有 cover 时长信息但同歌手,保守移除
removed.append(r)
continue
is_same_recording = True # 没有 cover 时长,保守认为同录音
if is_same_recording:
# 重新标注为正样本:同录音跨平台分发,应该匹配
r = dict(r)
r["expected"] = "duplicate"
r["sample_class"] = "positive"
r["expected_song_id"] = song_id
# 重算 correct:预测为 duplicate 才算对
predicted = r.get("predicted_duplicate", "").lower() == "true"
r["correct"] = str(predicted)
relabeled.append(r)
kept.append(r)
print(f"移除行数: {len(removed)}(同歌手且时长相近)")
print(f"重新标注行数: {len(relabeled)}(同歌手且时长相近,改为 expected=duplicate)")
print(f"保留行数: {len(kept)}")
# 写修复后的文件(去掉冗余列)
DROP_COLS = {"topk_hit", "expected_duplicate", "predicted_duplicate", "sample_class"}
DROP_COLS = {"topk_hit", "expected", "sample_class"}
out_fieldnames = [f for f in fieldnames if f not in DROP_COLS]
out_path = Path(args.output)
......@@ -294,12 +294,12 @@ def main():
for v, d in variants.items():
print(f" {v:20s} acc={d['accuracy']:.4f} n={d['total']}")
# 打印被移除的样本明细
if removed:
print(f"\n移除的 {len(removed)} 条负样本:")
for r in removed:
# 打印重新标注的样本明细
if relabeled:
print(f"\n重新标注的 {len(relabeled)} 条(负样本→正样本):")
for r in relabeled:
print(f" song_id={r.get('query_song_id')} variant={r.get('variant')} "
f"singer={r.get('singer_name')} correct_was={r.get('correct')}")
f"singer={r.get('singer_name')} correct={r.get('correct')}")
if __name__ == "__main__":
......