如何使用Python或Lucene提取摘要含公共n-gram的Xsum数据集文章
XSum数据集公共n-gram关联文章筛选实现方案
一、Python 实现方案
20万条数据规模用原生Python即可高效完成,不需要引入复杂框架,实现步骤如下:
实现逻辑
- 遍历所有文档,为每条摘要生成长度≥4的连续n-gram,同一条摘要内重复的n-gram仅保留一次,避免重复计数
- 建立倒排字典:key为n-gram字符串,value为包含该n-gram的文档ID列表
- 过滤倒排字典,仅保留value长度≥2的条目,即为你需要的公共n-gram及对应文档集合
示例代码
from collections import defaultdict def generate_ngrams(text, min_n=4): tokens = text.split() ngrams = set() # 同一条摘要内去重 max_n = len(tokens) if max_n < min_n: return ngrams # 可根据需求调整最大n长度,降低内存占用 for n in range(min_n, max_n + 1): for i in range(max_n - n + 1): ngram = ' '.join(tokens[i:i+n]) ngrams.add(ngram) return ngrams # 模拟数据集,实际使用时替换为读取XSum数据集的逻辑 dataset = [ {"doc_id": "article1", "summary": "x a a b d m"}, {"doc_id": "article2", "summary": "x a b d c e m"}, {"doc_id": "article3", "summary": "y z c f a b d c e q u"}, {"doc_id": "article4", "summary": "m g a a b d v r a"}, {"doc_id": "article5", "summary": "r a e q u d x"}, ] ngram_doc_map = defaultdict(list) for item in dataset: doc_id = item["doc_id"] summary = item["summary"] ngrams = generate_ngrams(summary) for gram in ngrams: ngram_doc_map[gram].append(doc_id) # 过滤得到出现次数≥2的公共n-gram common_ngrams = {gram: docs for gram, docs in ngram_doc_map.items() if len(docs) >= 2} # 输出结果 print("Articles. Common n-gram") for gram, docs in common_ngrams.items(): print(f"{', '.join(docs)} : {gram}")
性能优化建议
如果运行时内存占用过高,可以做两级优化:
- 限制最大n-gram长度(比如最长设为10,符合摘要常用公共片段的长度范围)
- 先用计数器统计所有n-gram的出现频次,先过滤掉频次为1的n-gram,再关联对应文档ID
二、Lucene 实现方向指引
你提到的直接将n-gram作为索引token的思路是可行的,不需要掌握复杂的Java开发也能实现:
- 若不想写Java代码,可以直接用PyLucene绑定,API和Java版完全一致
- 自定义分析器,使用
NGramTokenizer,配置minGramSize=4,maxGramSize按你的需求设置,不要用默认的分词器 - 索引时仅需要存储文档ID和摘要字段即可
- 索引构建完成后,遍历索引的term词典,每个term对应就是一个n-gram,通过
termsEnum.docFreq()可以获取出现的文档数,过滤掉文档数<2的term后,再拉取term对应的所有文档ID即可得到结果
内容的提问来源于stack exchange,提问作者Kiera.K
相关产品推荐
相关产品推荐

