Wendy-Fly commited on
Commit
de652ba
·
verified ·
1 Parent(s): 92b8e5c

support arbitrary K for estimated_position (top1/top5/top100)

Browse files
Files changed (1) hide show
  1. add_estimated_position.py +63 -40
add_estimated_position.py CHANGED
@@ -1,16 +1,25 @@
1
  #!/usr/bin/env python3
2
- """把 top100 match 估出来的整数 position 写回 golden_set.csv。
3
 
4
- 每条 case:
5
- - 从 golden_top100.jsonl 取它的 100 个最近邻 ruler 的 rank
6
- - 求均值,round 成整数
7
- - 作为新列 estimated_position 写回 csv
8
-
9
- 输出:golden_set_with_estimated.csv(不覆盖原文件)
10
 
11
  用法:
12
- python3 add_estimated_position.py
13
- python3 add_estimated_position.py --csv /path/to.csv --jsonl /path/to.jsonl
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  """
15
  import argparse
16
  import json
@@ -25,78 +34,92 @@ DEFAULTS = dict(
25
  jsonl = "golden_top100.jsonl",
26
  output = "golden_set_with_estimated.csv",
27
  id_col = "task_id",
28
- new_col = "estimated_position",
29
  )
30
 
31
 
32
  def parse_args():
33
  p = argparse.ArgumentParser()
34
- p.add_argument("--csv", default=DEFAULTS["csv"])
35
- p.add_argument("--jsonl", default=DEFAULTS["jsonl"])
36
- p.add_argument("--output", default=DEFAULTS["output"])
37
- p.add_argument("--id-col", default=DEFAULTS["id_col"])
38
- p.add_argument("--new-col", default=DEFAULTS["new_col"])
 
 
 
 
 
39
  return p.parse_args()
40
 
41
 
42
  def main():
43
  args = parse_args()
 
44
 
45
- # 1) 读 jsonl,每条样本算 top-100 rank 均值 → 整数
 
 
 
 
 
 
 
46
  print(f"[1] read jsonl: {args.jsonl}")
47
  estimated = {}
 
48
  with open(args.jsonl, "r", encoding="utf-8") as f:
49
  for line in f:
50
  line = line.strip()
51
  if not line:
52
  continue
53
  r = json.loads(line)
54
- ranks = np.array([t["rank"] for t in r["topk"]], dtype=float)
 
 
 
 
55
  estimated[str(r["task_id"])] = int(round(ranks.mean()))
56
- print(f" -> {len(estimated)} cases estimated")
 
 
57
 
58
  # 2) 读 csv
59
  print(f"[2] read csv: {args.csv}")
60
  df = pd.read_csv(args.csv, keep_default_na=False)
61
- print(f" -> {len(df)} rows")
62
 
63
  if args.id_col not in df.columns:
64
  raise ValueError(f"'{args.id_col}' not in csv. cols: {list(df.columns)}")
65
 
66
- # 3) 给每条 case 加 estimated_position 列
67
- print(f"[3] add column: {args.new_col}")
68
- df[args.new_col] = df[args.id_col].astype(str).map(estimated)
69
 
70
- n_total = len(df)
71
- n_matched = df[args.new_col].notna().sum()
72
- n_missing = n_total - n_matched
73
  print(f" matched: {n_matched}/{n_total}")
74
- if n_missing:
75
- print(f" ⚠️ {n_missing} 条 case 在 jsonl 里没找到对应 task_id")
76
- else:
77
- # 全部匹配上 → 转成 Int64(pandas 的可空整数类型,不会因为没 NaN 变 float)
78
- df[args.new_col] = df[args.new_col].astype("Int64")
79
 
80
  # 4) 写
81
  print(f"[4] write: {args.output}")
82
  df.to_csv(args.output, index=False)
83
- print(f" done. csv 现在有 {len(df.columns)} 列(多了 1 列:{args.new_col})")
84
 
85
- # 5) 预览
86
- print(f"\n[preview] 前 5 行:")
87
- cols = [args.id_col, "label", args.new_col]
88
  cols = [c for c in cols if c in df.columns]
89
  print(df[cols].head(5).to_string(index=False))
90
 
91
- # 6) 简单 stats
92
- s = pd.to_numeric(df[args.new_col], errors="coerce")
93
- print(f"\n[stats] {args.new_col}:")
94
- print(f" min={int(s.min())} max={int(s.max())} mean={s.mean():.1f} median={int(s.median())}")
95
  if "label" in df.columns:
96
  print("\n按 label 分组:")
97
  for lab, sub in df.groupby("label"):
98
- ss = pd.to_numeric(sub[args.new_col], errors="coerce")
99
- print(f" label={lab!r:>4} n={len(sub):>4} mean={ss.mean():.1f} median={int(ss.median())}")
100
 
101
 
102
  if __name__ == "__main__":
 
1
  #!/usr/bin/env python3
2
+ """把 embedding top-K match 估出来的整数 position 写回 golden_set.csv。
3
 
4
+ 支持任意 K(默认 100),列名自动带 K 后缀,方便同时跑多种 K 比较。
 
 
 
 
 
5
 
6
  用法:
7
+ # top-100 邻居均值
8
+ python3 add_estimated_position.py --k 100
9
+
10
+ # top-5 邻居均值
11
+ python3 add_estimated_position.py --k 5
12
+
13
+ # top-1(最近邻 rank)
14
+ python3 add_estimated_position.py --k 1
15
+
16
+ # 一次跑多种 K(每种生成一列)
17
+ python3 add_estimated_position.py --k 1 --k-suffix top1
18
+ python3 add_estimated_position.py --csv golden_set_with_estimated.csv --k 5 --k-suffix top5
19
+ python3 add_estimated_position.py --csv golden_set_with_estimated.csv --k 100 --k-suffix top100
20
+
21
+ # 自定义列名
22
+ python3 add_estimated_position.py --k 5 --new-col estimated_position_top5
23
  """
24
  import argparse
25
  import json
 
34
  jsonl = "golden_top100.jsonl",
35
  output = "golden_set_with_estimated.csv",
36
  id_col = "task_id",
 
37
  )
38
 
39
 
40
  def parse_args():
41
  p = argparse.ArgumentParser()
42
+ p.add_argument("--csv", default=DEFAULTS["csv"])
43
+ p.add_argument("--jsonl", default=DEFAULTS["jsonl"])
44
+ p.add_argument("--output", default=DEFAULTS["output"])
45
+ p.add_argument("--id-col", default=DEFAULTS["id_col"])
46
+ p.add_argument("--k", type=int, default=100,
47
+ help="用前 K 个邻居算均值(K=1 即 top1 rank)")
48
+ p.add_argument("--new-col", default=None,
49
+ help="新列名;不传则自动用 estimated_position_top{K}")
50
+ p.add_argument("--k-suffix", default=None,
51
+ help="(已弃用,等价于 --new-col estimated_position_{suffix})")
52
  return p.parse_args()
53
 
54
 
55
  def main():
56
  args = parse_args()
57
+ K = args.k
58
 
59
+ if args.new_col:
60
+ col_name = args.new_col
61
+ elif args.k_suffix:
62
+ col_name = f"estimated_position_{args.k_suffix}"
63
+ else:
64
+ col_name = f"estimated_position_top{K}"
65
+
66
+ # 1) 读 jsonl,每条样本算 top-K rank 均值(K=1 时等价于最近邻 rank)
67
  print(f"[1] read jsonl: {args.jsonl}")
68
  estimated = {}
69
+ skipped = 0
70
  with open(args.jsonl, "r", encoding="utf-8") as f:
71
  for line in f:
72
  line = line.strip()
73
  if not line:
74
  continue
75
  r = json.loads(line)
76
+ topk = r.get("topk") or []
77
+ if len(topk) < K:
78
+ skipped += 1
79
+ continue
80
+ ranks = np.array([t["rank"] for t in topk[:K]], dtype=float)
81
  estimated[str(r["task_id"])] = int(round(ranks.mean()))
82
+ print(f" -> {len(estimated)} cases estimated (K={K})")
83
+ if skipped:
84
+ print(f" ⚠️ {skipped} 条 jsonl 邻居数 < K,跳过")
85
 
86
  # 2) 读 csv
87
  print(f"[2] read csv: {args.csv}")
88
  df = pd.read_csv(args.csv, keep_default_na=False)
89
+ print(f" -> {len(df)} rows, {len(df.columns)} cols")
90
 
91
  if args.id_col not in df.columns:
92
  raise ValueError(f"'{args.id_col}' not in csv. cols: {list(df.columns)}")
93
 
94
+ # 3) 给每条 case 加新列
95
+ print(f"[3] add column: {col_name}")
96
+ df[col_name] = df[args.id_col].astype(str).map(estimated)
97
 
98
+ n_total = len(df)
99
+ n_matched = df[col_name].notna().sum()
 
100
  print(f" matched: {n_matched}/{n_total}")
101
+ if n_matched == n_total:
102
+ df[col_name] = df[col_name].astype("Int64")
 
 
 
103
 
104
  # 4) 写
105
  print(f"[4] write: {args.output}")
106
  df.to_csv(args.output, index=False)
107
+ print(f" done. csv 现在有 {len(df.columns)} 列(含新列:{col_name})")
108
 
109
+ # 5) 预览 + stats
110
+ print(f"\n[preview] 前 5 行(task_id / label / {col_name}):")
111
+ cols = [args.id_col, "label", col_name]
112
  cols = [c for c in cols if c in df.columns]
113
  print(df[cols].head(5).to_string(index=False))
114
 
115
+ s = pd.to_numeric(df[col_name], errors="coerce")
116
+ print(f"\n[stats] {col_name}:")
117
+ print(f" min={int(s.min())} max={int(s.max())} mean={s.mean():.2f} median={int(s.median())} std={s.std():.2f}")
 
118
  if "label" in df.columns:
119
  print("\n按 label 分组:")
120
  for lab, sub in df.groupby("label"):
121
+ ss = pd.to_numeric(sub[col_name], errors="coerce")
122
+ print(f" label={lab!r:>4} n={len(sub):>4} mean={ss.mean():.2f} median={int(ss.median())} std={ss.std():.2f}")
123
 
124
 
125
  if __name__ == "__main__":