gensim corpora.textcorpus 完全指南:TextCorpus 与 TextDirectoryCorpus 实现从纯文本到 BoW 语料库的自动化管线
发布时间:2026/9/21 15:55:13 作者:尧图编辑部 阅读量:1,286

gensim corpora.textcorpus 完全指南TextCorpus 与 TextDirectoryCorpus 实现从纯文本到 BoW 语料库的自动化管线【免费下载链接】gensimTopic Modelling for Humans项目地址: https://gitcode.com/gh_mirrors/ge/gensimcorpora.textcorpus是 gensim 语料库子包gensim/corpora/init.py 中导出的TextCorpus与TextDirectoryCorpus中用于构建带词典的语料库的核心脚手架模块它把磁盘上存放的纯文本 → 预处理 → 词典word→id 映射→ 稀疏词袋BoW向量(word_id, word_weight) 序列这条高频流水线封装成开箱即用的基类。本文以 docs/src/corpora/textcorpus.rst 的 API 文档为主体结合 gensim/corpora/textcorpus.py 的源码实现与其测试用例gensim/test/test_corpora.py、gensim/test/test_miislita.py系统讲解 TextCorpus 的设计思想、默认预处理管线、子类化扩展方式、TextDirectoryCorpus 的目录级语料读取能力以及如何将产出直接接入 TfidfModel、LsiModel、LdaModel 等模型与各类序列化格式。模块定位为什么需要文本 → BoW脚手架在实际项目中文本语料通常以某种纯文本格式驻留在磁盘上。最常见的场景是我们需要先构建一个词典word-integer id的映射再用它把每篇文档转换成稀疏词袋向量即(word_id, word_weight)的可迭代对象最终交给模型使用。这段代码位于 gensim/corpora/textcorpus.py 的模块文档中给出了该模块的设计动机提供脚手架code scaffolding来简化这条管线。例如假设语料中每篇文档是磁盘文件中单独的一行你只需要覆写TextCorpus.get_texts让它在每次迭代中读取一行 一篇文档、做必要的处理转小写、分词等并以词序列sequence of words的形式 yield 出来。之后用MyTextCorpus(mycorpus.txt.bz2)初始化语料对象它就会像一个稀疏向量语料库一样正确工作__iter__方法自动就绪无需手动实现词典自动填充所有word-id映射self.dictionary。产出的语料对象可以直接作为 gensim 各类模型的输入包括 TfidfModel、LsiModel、LdaModel 等也可以序列化为任意格式——Matrix Market、SvmLight、Blei 的 LDA-C 格式等。模块文档还特别推荐了一个小而美的示例gensim.test.test_miislita.CorpusMiislita定义于 gensim/test/test_miislita.py它是 TextCorpus 子类化的经典范例下文会详细展开。TextCorpus抽象基类的核心契约TextCorpus继承自interfaces.CorpusABC见 gensim/corpora/textcorpus.py是一个抽象基类。类文档明确指出需要覆写get_texts与__len__两个方法来匹配你的特定输入格式而只要在构造函数中传入文件名或文件类对象语料对象就会自动初始化self.dictionary并支持标准的语料库迭代协议__iter__。构造函数参数详解__init__的完整签名如下gensim/corpora/textcorpus.pydef __init__(self, inputNone, dictionaryNone, metadataFalse, character_filtersNone, tokenizerNone, token_filtersNone):各参数含义与默认行为参数类型默认行为inputstr可选顶层目录或文件路径用于遍历语料文档。传入None时词典保持未初始化dictionaryDictionary可选若传入词典初始化时不会用当前语料更新它若为None则自动为当前语料新建词典metadatabool可选为True时迭代 yield 的每篇文档附带元数据character_filterscallable 的可迭代对象可选按顺序作用于每篇文档文本每个 filter 应返回一个修改后的字符串。为None时默认使用lower_to_unicode、deaccent、strip_multiple_whitespacestokenizercallable可选文档分词器。为None时默认使用simple_tokenizetoken_filterscallable 的可迭代对象可选按顺序作用于分词结果token 迭代对象每个 filter 应返回另一个 token 迭代对象可以增、删、替换 token也可以什么都不做。为None时默认使用remove_short_tokens与remove_stopword_tokens默认预处理管线六步类文档与源码gensim/corpora/textcorpus.py共同确认默认预处理由三组可注入组件组成0 个或多个character_filters、一个tokenizer、0 个或多个token_filters。完整的默认管线如下lower_to_unicode——转小写并转换为 Unicode假定 utf8 编码定义于 gensim/parsing/preprocessing.pydeaccent——去重音符号ASCII 折叠定义于 gensim/utils.pystrip_multiple_whitespaces——把多个连续空白折叠为一个定义于 gensim/parsing/preprocessing.pysimple_tokenize——按空白切分完成分词定义于 gensim/utils.pyremove_short_tokens——移除长度小于 3 个字符的词默认minsize3定义于 gensim/parsing/preprocessing.pyremove_stopword_tokens——移除停用词默认使用STOPWORDS词表见 gensim/parsing/preprocessing.py。preprocess_text方法gensim/corpora/textcorpus.py实现了这条链式调用先依次执行所有字符过滤器输入输出均为字符串把最终结果喂给分词器得到 token 列表再让每个 token 过滤器依次处理该列表最后一个 token 过滤器的输出就是preprocess_text的最终返回值。这套默认管线的实际效果可由测试用例验证。TestTextCorpus.test_default_preprocessinggensim/test/test_corpora.py输入三行文本Šéf chomutovských komunistů dostal poštou bílý prášek经转小写、去重音后得到[Sef, chomutovskych, komunistu, dostal, postou, bily, prasek]注意Šéf被折叠为Sefthis is a test for stopwords因is、a、for为停用词且过短被过滤最终只剩[test, stopwords]zf tooth spaces 中zf长度不足 3 被移除多空白被折叠得到[tooth, spaces]。预处理链的调试利器step_through_preprocess当自定义预处理管线出现异常时step_through_preprocess(text)gensim/corpora/textcorpus.py可以逐个步骤应用预处理并 yield(callable, 输出)二元组方便你观察每一步 filter 的中间产物从而定位是哪个环节出了问题。类文档特别标注这个方法就是为调试语料预处理管线而设计的。子类化实战覆写 get_texts 与lenTextCorpus 的核心扩展方式有两种传参composition或子类化subclassing。官方示例CorpusMiislita模块文档推荐的经典示例是CorpusMiislita。它在__init__的 doctest 中有完整版gensim/corpora/textcorpus.py并在测试模块中作为可复用实现gensim/test/test_miislita.py from gensim.corpora.textcorpus import TextCorpus from gensim.test.utils import datapath from gensim import utils class CorpusMiislita(TextCorpus): ... stopwords set(for a of the and to in on.split()) ... ... def get_texts(self): ... for doc in self.getstream(): ... yield [word for word in utils.to_unicode(doc).lower().split() if word not in self.stopwords] ... ... def __len__(self): ... self.length sum(1 for _ in self.get_texts()) ... return self.length corpus CorpusMiislita(datapath(head500.noblanks.cor.bz2)) len(corpus) 250 document next(iter(corpus.get_texts()))这个示例揭示出子类化时的完整契约get_texts内部通过self.getstream()逐行逐文档读取底层输入流然后做自定义处理这里是小写化 按空白切分 过滤自定义停用词表最终以 token 列表形式 yield__len__通过一次性遍历get_texts统计文档数并缓存在self.length使len(corpus)可用底层输入文件是head500.noblanks.cor.bz2位于 gensim/test/test_data/说明 smart_open 透明支持 bz2 压缩格式。三种子类化覆写维度类文档gensim/corpora/textcorpus.py明确给出了三个覆写切入点覆写getstream——当需要从不同输入源、以不同格式读取文本时例如 XML、数据库、网络流覆写preprocess_text——当需要提供不同的初始预处理时可在新实现内部再调用基类的preprocess_text来叠加默认管线覆写get_texts——当需要给文档token 列表附加不同的元数据时metadataTrue时以(tokens, metadata)二元组 yield。get_texts 的内部流程基类get_textsgensim/corpora/textcorpus.py的实现分两步调用getstream获得文本生成器对每篇文档调用preprocess_text得到 token 列表若metadataTrue则以(token列表, (行号,))的形式 yield。而__iter__gensim/corpora/textcorpus.py进一步把 token 列表通过self.dictionary.doc2bow(text, allow_updateFalse)转换为 BoW 格式。注意这里显式使用allow_updateFalse训练期间词典已在初始化阶段填充完毕迭代阶段不再更新词典。若metadataTrue则 yield(bow向量, 元数据)二元组。词典的自动构建发生在init_dictionarygensim/corpora/textcorpus.py若未传入现成词典则新建空Dictionary并通过add_documents(self.get_texts())扫描一遍语料完成填充此时会临时关闭 metadata 以加快扫描若传入词典则保持不变若inputNone则仅告警等待后续以其他方式初始化。TextDirectoryCorpus整目录递归读取TextDirectoryCorpus继承自TextCorpus专门解决从目录递归读取文档的场景gensim/corpora/textcorpus.py。它把目录树中的每个文件或每行取决于lines_are_documents解释为一篇纯文本文档。构造参数构造函数签名gensim/corpora/textcorpus.pydef __init__(self, input, dictionaryNone, metadataFalse, min_depth0, max_depthNone, patternNone, exclude_patternNone, lines_are_documentsFalse, encodingutf-8, **kwargs):参数默认值说明input必填输入文件或文件夹路径min_depth0目录树中开始搜索文件的最小深度max_depthNone目录树中不再考虑文件的最大深度None表示不限制实现中映射为sys.maxsize见 gensim/corpora/textcorpus.pypatternNone文件名包含正则不匹配该正则的文件被忽略内部re.compile缓存exclude_patternNone文件名排除正则匹配该正则的文件被忽略lines_are_documentsFalse为True时每行算一篇文档否则每个文件算一篇文档encodingutf-8读取文件时使用的编码**kwargs—透传给TextCorpus构造函数即上文各预处理参数值得注意的是pattern、exclude_pattern、min_depth、max_depth、lines_are_documents都实现了属性 setter且在赋值时会自动把缓存的self.length置回None例如 gensim/corpora/textcorpus.py保证修改过滤条件后重新计算语料长度。文件发现iter_filepaths 与 walkiter_filepathsgensim/corpora/textcorpus.py惰性生成目录结构中指定深度范围内的每个文件路径并依次应用pattern包含过滤与exclude_pattern排除过滤。它基于模块级函数walkgensim/corpora/textcorpus.py实现——这是 Python 2 源码中os.walk的移植版唯一区别是额外返回当前所处的目录树深度从而支持min_depth/max_depth的深度裁剪逻辑。getstreamgensim/corpora/textcorpus.py随后打开每个文件lines_are_documentsTrue时逐行 yield每行strip()后作为一篇文档否则把整个文件read().strip()作为一篇文档。结束后把文档数缓存在self.length。__len__gensim/corpora/textcorpus.py在长度未缓存时调用_cache_corpus_lengthgensim/corpora/textcorpus.py计算非逐行模式下只需数文件路径逐行模式下才需要真正读取流。测试验证的典型用法gensim/test/test_corpora.py 中的TestTextDirectoryCorpus完整覆盖了这些能力多层级目录test_two_level_directory第 847 行验证默认递归读取两层共 4 篇文档min_depth1与max_depth0都能把结果裁剪为 2 篇文件名过滤test_filename_filtering第 865 行展示patternrtest.*\.log只匹配test1.log、test2.log运行时还可直接改corpus.pattern .*.txt或切换为exclude_pattern无需重建对象逐行文档test_lines_are_documents第 882 行验证同一目录在lines_are_documentsTrue/False两种模式下分别得到 5 篇逐行文档与 1 篇整文件文档且corpus.length会被正确缓存非平凡目录结构test_non_trivial_structure第 899 行构建了嵌套三层的目录树验证默认全量发现 5 个文件随后通过max_depth、min_depth、pattern的组合逐步裁剪到目标子集。高级工具sample_texts 随机抽样sample_texts(n, seedNone, lengthNone)gensim/corpora/textcorpus.py从语料中不放回地随机抽取n篇文档以 token 序列形式 yield适用于快速抽样子集做实验或人工检查。n需要抽取的文档数seed指定后用于本地随机数生成器保证抽样可复现length语料长度。由于计算完整语料长度代价较高可手动传入缓存值不传则调用len(self)。算法采用经典的水库式不放回抽样设剩余文档数为remaining当前元素被选中的概率为n / remaining选中则n减一后继续。其边界约束由测试test_sample_textgensim/test/test_corpora.py验证n大于语料长度时抛出ValueErrorn is larger/equal than length of corpusn为负数时抛出ValueErrorNegative sample size nsample_texts(len(lines))恰好按原顺序抽回全部文档此时不放回抽样等价于全量有序遍历指定seed42两次抽样结果完全一致test_sample_text_seed第 600 行传入length参数可跳过len(self)计算test_sample_text_length第 588 行。此外若传入的length大于语料实际文档数会在流结束后抛出ValueError提示。生态接入模型输入与序列化TextCorpus 的产出是标准 gensim 语料库对象因此与生态无缝衔接模型输入。可直接作为 TfidfModel、LsiModel、LdaModel 等模型的训练语料。CorpusMiislita的端到端用例见 gensim/test/test_miislita.py构造语料后训练 TfidfModel、构建SparseMatrixSimilarity索引再对查询latent semantic indexing计算相似度并断言与论文结果一致期望值[0.0, 0.2560, 0.7022, 0.1524, 0.3334]。序列化。CorpusMiislita可被corpora.MmCorpus.save_corpus(ftmp, miislita)保存为 Matrix Market 格式并重新加载后逐文档等价gensim/test/test_miislita.pyTextCorpus 对象本身也支持save/loadpickle 持久化前提是输入不是文件类对象见 gensim/test/test_miislita.py。此外TextCorpus 还被WikiCorpus继承gensim/corpora/wikicorpus.py后者通过覆写getstream/get_texts将 XML 格式的 Wikipedia 转储解析为 token 流——这正是覆写 getstream 以适配不同输入源这一扩展点的真实工业案例。总结与选型建议需求选择单个纯文本文件每行一篇文档支持 bz2/gz 等 smart_open 透明压缩TextCorpus子类化覆写get_texts/__len__无需改预处理仅换分词/过滤规则直接构造并传入character_filters、tokenizer、token_filters整个目录树的文件或行作为语料TextDirectoryCorpus配合min_depth/max_depth/pattern/exclude_pattern/lines_are_documents需要调试自定义预处理链step_through_preprocess逐步观察中间结果快速抽样子集做实验sample_texts(n, seed...)非纯文本输入XML、数据库等继承 TextCorpus 覆写getstream参考 WikiCorpus 的实现TextCorpus的价值在于把文本→词典→BoW这条高频管线固化为可复用契约默认预处理开箱即用getstream/preprocess_text/get_texts三个覆写点分别对应输入源、预处理、元数据三个维度的定制而TextDirectoryCorpus把文件发现逻辑深度裁剪 正则过滤也一并标准化。理解这套脚手架就能以最小代码量把任意纯文本语料接入 gensim 的向量空间建模与主题建模工作流。【免费下载链接】gensimTopic Modelling for Humans项目地址: https://gitcode.com/gh_mirrors/ge/gensim创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考