02_split_cleaned_medical_dataset.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. """将清洗后的完整数据去重,并按 8:2 切分训练集和验证集。"""
  2. import json
  3. import random
  4. from pathlib import Path
  5. ROOT = Path(__file__).resolve().parent
  6. SOURCE_FILE = ROOT / "medical_o1_sft_mix_Chinese_cleaned.json"
  7. OUTPUT_DIR = ROOT / "medical_o1_sft_mix_Chinese_cleaned_dedup_split_80_20"
  8. RANDOM_SEED = 42
  9. def question_key(record):
  10. """统一问题首尾及连续空白,用于问题级去重。"""
  11. return " ".join(record["Question"].split())
  12. def save_json(path, records):
  13. path.write_text(
  14. json.dumps(records, ensure_ascii=False, indent=4) + "\n",
  15. encoding="utf-8",
  16. )
  17. def main():
  18. records = json.loads(SOURCE_FILE.read_text(encoding="utf-8"))
  19. required_fields = {"Question", "Complex_CoT", "Response"}
  20. if not isinstance(records, list) or any(
  21. not isinstance(record, dict) or not required_fields <= record.keys()
  22. for record in records
  23. ):
  24. raise ValueError(f"每条记录必须包含字段:{required_fields}")
  25. # 同一个规范化问题只保留第一次出现的完整记录。
  26. unique = {}
  27. for record in records:
  28. unique.setdefault(question_key(record), record)
  29. unique_records = list(unique.values())
  30. random.Random(RANDOM_SEED).shuffle(unique_records)
  31. train_size = len(unique_records) * 8 // 10
  32. train = unique_records[:train_size]
  33. validation = unique_records[train_size:]
  34. train_keys = {question_key(record) for record in train}
  35. validation_keys = {question_key(record) for record in validation}
  36. if len(train_keys) != len(train) or len(validation_keys) != len(validation):
  37. raise RuntimeError("训练集或验证集内部仍然存在重复问题。")
  38. if train_keys & validation_keys:
  39. raise RuntimeError("训练集与验证集之间仍然存在重复问题。")
  40. if OUTPUT_DIR.exists() and any(OUTPUT_DIR.iterdir()):
  41. raise FileExistsError(f"为避免覆盖已有结果,请先确认目录:{OUTPUT_DIR}")
  42. OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
  43. save_json(OUTPUT_DIR / "train.json", train)
  44. save_json(OUTPUT_DIR / "validation.json", validation)
  45. print(f"清洗后原始记录:{len(records)}")
  46. print(f"问题去重后记录:{len(unique_records)}")
  47. print(f"删除重复记录:{len(records) - len(unique_records)}")
  48. print(f"训练集:{len(train)}")
  49. print(f"验证集:{len(validation)}")
  50. print(f"训练/验证问题交集:{len(train_keys & validation_keys)}")
  51. print(f"随机种子:{RANDOM_SEED}")
  52. print(f"保存目录:{OUTPUT_DIR}")
  53. if __name__ == "__main__":
  54. main()