GooGooLM / scripts /01_data /vocab_coverage.py
XiaoyanLi's picture
Initial upload: code, training data, tokenizers, notes
83112d8 verified
Raw
History Blame Contribute Delete
3.35 kB
"""
vocab.txt 覆盖率分析
对每个训练文件统计:
- token 级覆盖率:训练文件中的词有多少 % 在 vocab.txt 里
- 类型级覆盖率:训练文件中的唯一词有多少 % 在 vocab.txt 里
- OOV(out-of-vocab)最高频词 Top 20
"""
import re
from pathlib import Path
from collections import Counter
VOCAB_PATH = Path(__file__).parent.parent / "evaluation-pipeline-2025/evaluation_pipeline/ewok/vocab.txt"
DATA_DIR = Path(__file__).parent.parent / "data/raw_files"
FILES = [
"childes.train.txt",
"gutenberg.train.txt",
"open_subtitles.train.txt",
"simple_wiki.train.txt",
"bnc_spoken.train.txt",
"open_subtitles_cleaned_ckpt_70.txt",
"switchboard.train.txt",
]
def tokenize(line):
return re.findall(r"[a-zA-Z']+|[0-9]+", line.lower())
def analyze(file_name, vocab):
path = DATA_DIR / file_name
total_tokens = 0
in_vocab_tokens = 0
total_counter = Counter()
oov_counter = Counter()
with open(path, "r", encoding="utf-8", errors="ignore") as f:
for line in f:
tokens = tokenize(line)
for t in tokens:
total_tokens += 1
total_counter[t] += 1
if t in vocab:
in_vocab_tokens += 1
else:
oov_counter[t] += 1
total_types = len(total_counter)
in_vocab_types = sum(1 for w in total_counter if w in vocab)
token_cov = in_vocab_tokens / total_tokens * 100 if total_tokens else 0
type_cov = in_vocab_types / total_types * 100 if total_types else 0
return {
"file": file_name,
"total_tokens": total_tokens,
"in_vocab_tokens":in_vocab_tokens,
"token_coverage": round(token_cov, 2),
"total_types": total_types,
"in_vocab_types": in_vocab_types,
"type_coverage": round(type_cov, 2),
"top20_oov": oov_counter.most_common(20),
}
def main():
print(f"读取 vocab.txt ...")
vocab = set(Path(VOCAB_PATH).read_text().splitlines())
print(f"vocab 大小: {len(vocab):,} 词\n")
results = []
for fname in FILES:
path = DATA_DIR / fname
if not path.exists():
print(f"[skip] {fname} 不存在")
continue
print(f"分析: {fname} ...")
r = analyze(fname, vocab)
results.append(r)
print(f" token覆盖率: {r['token_coverage']}% | 类型覆盖率: {r['type_coverage']}%")
print(f" 总词数: {r['total_tokens']:,} vocab内: {r['in_vocab_tokens']:,}")
print(f" 总唯一词: {r['total_types']:,} vocab内: {r['in_vocab_types']:,}")
print(f" Top10 OOV: {[w for w,c in r['top20_oov'][:10]]}")
print()
# 汇总表
print("\n" + "="*70)
print(f"{'文件':<40} {'token覆盖率':>10} {'类型覆盖率':>10} {'总词数':>12}")
print("="*70)
for r in results:
print(f"{r['file']:<40} {r['token_coverage']:>9}% {r['type_coverage']:>9}% {r['total_tokens']:>12,}")
# 保存结果
import json
out = Path(__file__).parent.parent / "results/analysis/vocab_coverage.json"
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(json.dumps(results, ensure_ascii=False, indent=2))
print(f"\n结果已保存: {out}")
if __name__ == "__main__":
main()