1

我正在尝试使用 Doc2Vec 获取大约 5,000 个法律摘要的语料库的文档相似性值(我认识到语料库可能有点小,但这是一个更大语料库的概念验证项目大约 15,000 份简报,我稍后将进行编译)。

基本上,到目前为止,模型创建中的每个其他组件都进行得相对较好——我拥有的每个简报都在一个较大文件夹中的文本文件中,所以我在我的脚本中使用它们编译它们glob.glob——但我遇到了一个标记化问题. 困难在于,由于这些文件是法律摘要,它们包含我想保留的数字,而且我用来帮助我编写代码的许多指南都使用 Gensim 的简单预处理,我相信它可以消除数字语料库,与 TaggedDocument 功能相结合。但是,我想尽可能少地对文本进行预处理。

下面是我使用的代码,我尝试将 simple_preprocess 替换为 genism.utils.tokenize,但是当我这样做时,我得到的生成器对象在我的最终 Doc2Vec 模型中似乎不可用,而且我不能实际看看语料库的样子。当我尝试使用其他标记器时,例如nltk,我不知道如何将其放入 TaggedDocument 组件中。

brief_corpus = []
for brief_filename in brief_filenames:
    with codecs.open(brief_filename, "r", "utf-8") as brief_file:
        brief_corpus.append(
            gensim.models.doc2vec.TaggedDocument(
                gensim.utils.simple_preprocess( 
                    brief_file.read()),
                    ["{}".format(brief_filename)])) #tagging each brief with its filename

我很感激任何人都可以提供的任何建议,这将帮助我结合一个仅在空格上分隔并且没有消除任何数字与 TaggedDocument 功能的标记器。谢谢!

更新:我能够为一些基本的标记化创建一个基本代码(我确实计划进一步完善它),而不必求助于 Gensim 的 simple_preprocessing 功能。但是,我在使用 TaggedDocument 功能时遇到了困难(再次!) - 但是这一次,标签(我想成为每个简报的文件名)与标记化的文档不匹配。基本上,每个文档都有一个标签,但它不是正确的。

谁能告诉我下面的新代码哪里出错了?谢谢!

briefs = []
BriefList = [p for p in os.listdir(FILEPATH) if p.endswith('.txt')]
for brief in BriefList:
     str = open(FILEPATH + brief,'r').read()
     tokens = re.findall(r"[\w']+|[.,!?;]", str)
     tagged_data = [TaggedDocument(tokens, [brief]) for brief in BriefList]
     briefs.append(tagged_data)
4

1 回答 1

0

您可能想要编写自己的预处理/标记化函数。simple_preprocess不过不用担心,即使是非常粗略的代码,也不难超越 Gensim 。

作为a的唯一Doc2Vec需要的是字符串标记列表(通常是单词)。wordsTaggedDocument

因此,首先,您可能会对在原始字符串上执行默认 Python 字符串的效果感到惊讶.split()——这只会破坏空格上的文本。

当然,一堆生成的标记将是单词和相邻标点符号的混合,这可能几乎是无稽之谈。

例如,'lawsuit'句子末尾的单词可能显示为'lawsuit.',那么它不会被识别为与 相同的标记'lawsuit',并且可能出现的min_count次数甚至不足以被考虑,或者几乎没有超过作为噪音的作用。

但尤其是对于较长的文档和较大的数据集,没有一个令牌,甚至 1% 的令牌,具有如此大的影响力。这不是精确关键字搜索,如果无法返回带有'lawsuit.'查询的文档'lawsuit'将是致命的失败。一堆“丢失”到这种杂乱无章的词可能对整个文档或模型的性能有任何影响。

由于您的数据集似乎易于管理以进行大量实验,因此我建议尝试这种最愚蠢的标记化 - 仅.split()作为基线,以确信该算法仍然大部分工作以及一些更具侵入性的操作(如simple_preprocess())。

然后,当您注意到、怀疑或通过一些可重复的评估进行理想测量时,您希望成为有意义标记的某些事情没有得到正确处理,逐渐添加剥离/分割/规范化字符或标记的额外步骤。但尽可能多地:检查代码的额外复杂性和运行时是否确实带来了好处。

例如,进一步的改进可能是以下几种组合:

  • 对于由 simple 创建的每个标记split(),去掉任何非字母数字的前导/尾随字符。(优点:消除了标点符号的污点。缺点:可能会丢失有用的符号,例如$货币金额的前导。)
  • 在拆分之前,将某些单字符标点符号(例如 say ['.', '"', ',', '(', ')', '!', '?', ';', ':'])替换为相同的字符,两边都有空格 - 这样它们就不会与附近的单词连接,而是作为一个简单.split()的独立标记保留下来。(优点:还可以防止单词加标点符号。缺点:分解数字2,345.77或一些有用的缩写。)
  • 在标记化的某个适当阶段,将许多不同的标记规范化为一组较小的标记,这些标记可能比它们中的每一个作为稀有的独立标记更有意义。例如,$0.01through$0.99可能都被转化为$0_XX- 与原始的独立令牌相比,它更有可能影响模型,并与“微量”概念相关联。或者用 替换所有数字#,这样大小相似的数字共享影响,而不用每个数字的标记稀释模型。

启发式方法和操作顺序的确切组合将取决于您的目标。但是只有数千个文档(而不是数十万或数百万)的语料库,即使您以相当低效的方式进行这些替换(大量单独的字符串或正则表达式替换),它也会可能是可管理的预处理成本。

但是您可以从简单开始,只增加您的特定领域知识和评估证明的复杂性。

于 2021-09-27T01:06:13.427 回答