download_glue_full.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. #!/usr/bin/env python
  2. """
  3. 下载 GLUE Benchmark 完整数据集(不采样)
  4. GLUE 子集说明:
  5. - MNLI: 多段落自然语言推理 (392,702 训练样本)
  6. - QNLI: 问答自然语言推理 (108,431 训练样本)
  7. - SST-2: 情感分析 (67,349 训练样本)
  8. - STS-B: 语义相似度 (8,628 训练样本)
  9. - CoLA: 语法判断 (8,551 训练样本)
  10. - MRPC: 释义识别 (3,668 训练样本)
  11. - RTE: 文本蕴含 (2,490 训练样本)
  12. 用法:
  13. python database/download_glue_full.py
  14. """
  15. import os
  16. import json
  17. from pathlib import Path
  18. from typing import List, Optional
  19. from datasets import load_dataset
  20. # 设置 HuggingFace 镜像(国内加速)
  21. os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
  22. def preprocess_text(text: str, lang: str = "en", min_len: int = 20, max_len: int = 300) -> Optional[str]:
  23. """
  24. 预处理文本:去特殊符号、控制长度
  25. """
  26. import re
  27. text = text.strip()
  28. if not text:
  29. return None
  30. # 清理特殊字符
  31. text = re.sub(r'[^\w\s.,!?;:()"\']', '', text)
  32. words = text.split()
  33. if len(words) < min_len:
  34. return None
  35. # 截断到最大长度
  36. text = ' '.join(words[:max_len]).strip()
  37. return text if text else None
  38. def save_corpus(texts: List[str], domain: str, output_dir: str = "database/corpus") -> bool:
  39. """保存语料到 JSONL 文件"""
  40. if not texts:
  41. print(f" ⚠️ 警告:没有语料可保存")
  42. return False
  43. output_path = Path(output_dir) / domain / "texts.jsonl"
  44. output_path.parent.mkdir(parents=True, exist_ok=True)
  45. with open(output_path, "w", encoding="utf-8") as f:
  46. for i, text in enumerate(texts):
  47. record = {
  48. "text": text,
  49. "metadata": {
  50. "index": i,
  51. "domain": domain,
  52. "source": "GLUE Benchmark"
  53. }
  54. }
  55. f.write(json.dumps(record, ensure_ascii=False) + "\n")
  56. print(f" ✅ 已保存至:{output_path} ({len(texts)} 条)")
  57. return True
  58. def load_mnli() -> List[str]:
  59. """
  60. MNLI (Multi-Genre Natural Language Inference)
  61. 多段落自然语言推理 - 最大子集
  62. 格式:premise, hypothesis, label
  63. 使用 premise 字段作为语料
  64. """
  65. corpus = []
  66. print("加载 MNLI (Multi-Genre Natural Language Inference)...")
  67. print(" 预期规模:~392K 训练样本")
  68. try:
  69. ds = load_dataset("glue", "mnli", split="train")
  70. for item in ds:
  71. premise = item.get("premise", "")
  72. hypothesis = item.get("hypothesis", "")
  73. # 合并 premise 和 hypothesis 作为完整语料
  74. full_text = f"{premise} {hypothesis}"
  75. processed = preprocess_text(full_text, lang="en", min_len=20, max_len=300)
  76. if processed and processed not in corpus:
  77. corpus.append(processed)
  78. print(f" ✅ 成功提取 {len(corpus):,} 条 MNLI 语料")
  79. except Exception as e:
  80. print(f" ❌ 加载失败:{e}")
  81. return corpus
  82. def load_qnli() -> List[str]:
  83. """
  84. QNLI (Question Natural Language Inference)
  85. 问答自然语言推理
  86. 格式:question, sentence, label
  87. 使用 sentence 字段作为语料(维基百科句子)
  88. """
  89. corpus = []
  90. print("加载 QNLI (Question NLI)...")
  91. print(" 预期规模:~108K 训练样本")
  92. try:
  93. ds = load_dataset("glue", "qnli", split="train")
  94. for item in ds:
  95. sentence = item.get("sentence", "")
  96. question = item.get("question", "")
  97. # 合并句子和问题
  98. full_text = f"{sentence} {question}"
  99. processed = preprocess_text(full_text, lang="en", min_len=20, max_len=300)
  100. if processed and processed not in corpus:
  101. corpus.append(processed)
  102. print(f" ✅ 成功提取 {len(corpus):,} 条 QNLI 语料")
  103. except Exception as e:
  104. print(f" ❌ 加载失败:{e}")
  105. return corpus
  106. def load_sst2() -> List[str]:
  107. """
  108. SST-2 (Stanford Sentiment Treebank)
  109. 情感分析
  110. 格式:sentence, label
  111. 使用完整句子
  112. """
  113. corpus = []
  114. print("加载 SST-2 (Stanford Sentiment Treebank)...")
  115. print(" 预期规模:~67K 训练样本")
  116. try:
  117. ds = load_dataset("glue", "sst2", split="train")
  118. for item in ds:
  119. sentence = item.get("sentence", "")
  120. processed = preprocess_text(sentence, lang="en", min_len=10, max_len=200)
  121. if processed and processed not in corpus:
  122. corpus.append(processed)
  123. print(f" ✅ 成功提取 {len(corpus):,} 条 SST-2 语料")
  124. except Exception as e:
  125. print(f" ❌ 加载失败:{e}")
  126. return corpus
  127. def load_stsb() -> List[str]:
  128. """
  129. STS-B (Semantic Textual Similarity Benchmark)
  130. 语义相似度
  131. 格式:sentence1, sentence2, score
  132. 合并两个句子作为语料
  133. """
  134. corpus = []
  135. print("加载 STS-B (Semantic Textual Similarity)...")
  136. print(" 预期规模:~8.6K 训练样本")
  137. try:
  138. ds = load_dataset("glue", "stsb", split="train")
  139. for item in ds:
  140. sentence1 = item.get("sentence1", "")
  141. sentence2 = item.get("sentence2", "")
  142. full_text = f"{sentence1} {sentence2}"
  143. processed = preprocess_text(full_text, lang="en", min_len=15, max_len=250)
  144. if processed and processed not in corpus:
  145. corpus.append(processed)
  146. print(f" ✅ 成功提取 {len(corpus):,} 条 STS-B 语料")
  147. except Exception as e:
  148. print(f" ❌ 加载失败:{e}")
  149. return corpus
  150. def load_cola() -> List[str]:
  151. """
  152. CoLA (Corpus of Linguistic Acceptability)
  153. 语法判断
  154. 格式:sentence, label
  155. """
  156. corpus = []
  157. print("加载 CoLA (Corpus of Linguistic Acceptability)...")
  158. print(" 预期规模:~8.5K 训练样本")
  159. try:
  160. ds = load_dataset("glue", "cola", split="train")
  161. for item in ds:
  162. sentence = item.get("sentence", "")
  163. processed = preprocess_text(sentence, lang="en", min_len=10, max_len=200)
  164. if processed and processed not in corpus:
  165. corpus.append(processed)
  166. print(f" ✅ 成功提取 {len(corpus):,} 条 CoLA 语料")
  167. except Exception as e:
  168. print(f" ❌ 加载失败:{e}")
  169. return corpus
  170. def load_mrpc() -> List[str]:
  171. """
  172. MRPC (Microsoft Research Paraphrase Corpus)
  173. 释义识别
  174. 格式:sentence1, sentence2, label
  175. """
  176. corpus = []
  177. print("加载 MRPC (Paraphrase Corpus)...")
  178. print(" 预期规模:~3.6K 训练样本")
  179. try:
  180. ds = load_dataset("glue", "mrpc", split="train")
  181. for item in ds:
  182. sentence1 = item.get("sentence1", "")
  183. sentence2 = item.get("sentence2", "")
  184. full_text = f"{sentence1} {sentence2}"
  185. processed = preprocess_text(full_text, lang="en", min_len=15, max_len=250)
  186. if processed and processed not in corpus:
  187. corpus.append(processed)
  188. print(f" ✅ 成功提取 {len(corpus):,} 条 MRPC 语料")
  189. except Exception as e:
  190. print(f" ❌ 加载失败:{e}")
  191. return corpus
  192. def load_rte() -> List[str]:
  193. """
  194. RTE (Recognizing Textual Entailment)
  195. 文本蕴含
  196. 格式:sentence1, sentence2, label
  197. """
  198. corpus = []
  199. print("加载 RTE (Textual Entailment)...")
  200. print(" 预期规模:~2.5K 训练样本")
  201. try:
  202. ds = load_dataset("glue", "rte", split="train")
  203. for item in ds:
  204. sentence1 = item.get("sentence1", "")
  205. sentence2 = item.get("sentence2", "")
  206. full_text = f"{sentence1} {sentence2}"
  207. processed = preprocess_text(full_text, lang="en", min_len=15, max_len=250)
  208. if processed and processed not in corpus:
  209. corpus.append(processed)
  210. print(f" ✅ 成功提取 {len(corpus):,} 条 RTE 语料")
  211. except Exception as e:
  212. print(f" ❌ 加载失败:{e}")
  213. return corpus
  214. # ==================== 主流程 ====================
  215. DOMAIN_LOADERS = {
  216. "glue_mnli": load_mnli, # ~392K - 多段落推理
  217. "glue_qnli": load_qnli, # ~108K - 问答推理
  218. "glue_sst2": load_sst2, # ~67K - 情感分析
  219. "glue_stsb": load_stsb, # ~8.6K - 语义相似度
  220. "glue_cola": load_cola, # ~8.5K - 语法判断
  221. "glue_mrpc": load_mrpc, # ~3.6K - 释义识别
  222. "glue_rte": load_rte, # ~2.5K - 文本蕴含
  223. }
  224. def main():
  225. print("=" * 70)
  226. print("GLUE Benchmark - 完整数据集下载(不采样)")
  227. print("=" * 70)
  228. print()
  229. print("GLUE 是 NLP 领域公认的标准评测基准,包含 7 个子任务")
  230. print("数据将用于模型表示提取和谱分析实验")
  231. print()
  232. domains = list(DOMAIN_LOADERS.keys())
  233. print(f"可用子集:{len(domains)} 个")
  234. for domain in domains:
  235. print(f" - {domain}")
  236. print()
  237. print(f"输出目录:database/corpus/")
  238. print()
  239. results = {}
  240. for domain in domains:
  241. print(f"\n{'='*60}")
  242. print(f"[{domain}]")
  243. print(f"{'='*60}")
  244. loader = DOMAIN_LOADERS[domain]
  245. texts = loader()
  246. if texts:
  247. success = save_corpus(texts, domain)
  248. results[domain] = len(texts) if success else 0
  249. else:
  250. print(f" ⚠️ 警告:未能获取有效语料")
  251. results[domain] = 0
  252. # 汇总
  253. print("\n" + "=" * 70)
  254. print("下载完成!汇总:")
  255. print("=" * 70)
  256. for domain, count in results.items():
  257. status = "✅" if count > 0 else "❌"
  258. print(f" {status} {domain}: {count:,} 条")
  259. total = sum(results.values())
  260. print(f"\n总计:{total:,} 条")
  261. print()
  262. print("下一步:")
  263. print(" 1. 查看数据:head database/corpus/glue_mnli/texts.jsonl")
  264. print(" 2. 提取表示:python model/extract_representations.py")
  265. print(" 3. 运行实验:python experiments/verify.py")
  266. if __name__ == "__main__":
  267. main()