在Doc2Vec标记化中保留数字

2024-09-29 18:40:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用Doc2Vec为大约5000份法律摘要的语料库获取文档相似度值(我知道语料库可能有点小,但这是一个概念验证项目,我将在稍后编译大约15000份摘要的更大语料库)

基本上,到目前为止,模型创建过程中的所有其他组件都进行得比较顺利——我的每个简介都在一个较大文件夹中的文本文件中,因此我使用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的简单预处理功能。然而,我在使用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)

Tags: 代码in文档标记模型功能for数字
1条回答
网友
1楼 · 发布于 2024-09-29 18:40:16

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

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

因此,首先,您可能会惊讶于对原始字符串执行默认Python字符串.split()的效果如何,它只是在空白处打断文本

当然,一堆生成的标记将是单词和字母的混合;相邻的标点符号,这几乎是胡说八道

例如,句子末尾的单词'lawsuit'可能会显示为'lawsuit.',这将不会被识别为与'lawsuit'相同的标记,并且可能不会出现足够多的min_count次,甚至不会被考虑,或者几乎不会超过用作噪音的程度

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

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

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

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

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

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

但你可以从简单开始&;只需增加特定领域知识和评估所证明的复杂性

相关问题 更多 >

    热门问题