【问题标题】:Keeping Numbers in Doc2Vec Tokenization在 Doc2Vec 标记化中保留数字
【发布时间】:2021-09-26 20:21:24
【问题描述】:

我正在尝试使用 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)

【问题讨论】:

    标签: python tokenize word-embedding doc2vec


    【解决方案1】:

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

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

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

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

    例如,句子末尾的单词'lawsuit' 可能会显示为'lawsuit.',然后不会被识别为与'lawsuit' 相同的标记,并且可能出现min_count 的次数不够甚至被认为是,否则几乎不会超越作为噪音。

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

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

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

    例如,进一步的改进可能包括:

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

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

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

    【讨论】:

    • 谢谢!自从我发布以来,我一直在研究这个问题,我认为我正在朝着基本的标记化功能前进,并重写了我上面用来执行此操作的代码,但是发生了一些变化,导致单词被标记到错误的文件!我已经发布了下面的代码,但我不确定如何调整以确保标签与相应的文档对齐。
    • for brief in BriefList: str = open("FILEPATH" + brief,'r').read() tokens = re.findall("[\w']+", str) tagged_data = [TaggedDocument(tokens, [brief]) for brief in BriefList]
    • 在没有缩进的情况下很难在 cmets 中显示代码 - 所以编辑问题通常会更好。但即使在这个片段中,看起来你在BriefList (两个for…in 构造)上都有两个循环,而应该只有一个。并且tagged_data 被重新分配,而不是附加到,每次last tokens,而不是每个独特的简介一个 tokens
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多