NLP,spaCy:提高文档相似度的策略

NLP, spaCy: Strategy for improving document similarity

一句话背景: 我有自动转录演讲的文本数据,我想比较他们的内容(例如他们在说什么)的相似性来做聚类和推荐。我对 NLP 很陌生。


数据:我使用的数据可用here。对于所有懒惰的人

clone https://github.com/TMorville/transcribed_data

这是将其放入 df 的代码片段:

import os, json
import pandas as pd

from pandas.io.json import json_normalize 

def td_to_df():
    
    path_to_json = '#FILL OUT PATH'
    json_files = [pos_json for pos_json in os.listdir(path_to_json) if pos_json.endswith('td.json')]

    tddata = pd.DataFrame(columns=['trans', 'confidence'])

    for index, js in enumerate(json_files):
        with open(os.path.join(path_to_json, js)) as json_file:
            json_text = json_normalize(json.load(json_file))

            tddata['trans'].loc[index] = str(json_text['trans'][0])
            tddata['confidence'].loc[index] = str(json_text['confidence'][0])

    return tddata

方法:到目前为止,我只使用 spaCy 包来做“开箱即用”的相似性。我只是将 nlp 模型应用于整个文本语料库,并将其与所有其他模型进行比较。

def similarity_get():
    
    tddata = td_to_df()
    
    nlp = spacy.load('en_core_web_lg')
    
    baseline = nlp(tddata.trans[0])
    
    for text in tddata.trans:
        print (baseline.similarity(nlp(text)))

问题几乎所有的相似性都大于 0.95。这或多或少独立于基线。现在,鉴于缺乏预处理,这可能不会令人感到意外。


解决策略:按照中的建议,我想做以下事情(尽可能使用spaCy):1)删除停用词。 2)删除最常用的词。 3)合并词对。 4) 可能在 spaCy 之外使用 Doc2Vec。


问题:以上看起来是不是一个合理的策略?如果没有,缺少什么?如果是,那么使用 nlp = spacy.load('en_core_web_lg') 中加载的预训练模型已经在幕后发生了多少这种情况?

我似乎找不到说明这些模型究竟在做什么或如何配置它们的文档。 A quick google search yields nothing and even the, very neat, api documentation 似乎没有帮助。也许我找错地方了?

您可以使用 SpaCY 和一些正则表达式来完成大部分工作。

所以,你得看看SpaCY API documentation.

任何 NLP 流水线的基本步骤如下:

  1. 语言检测(不言自明,如果您正在处理某些数据集,您知道语言是什么,并且您可以调整您的管道以适应该语言)。当你知道一种语言时,你必须从 SpaCY 下载正确的模型。指令是here。让我们在这个例子中使用英语。在您的命令行中,只需键入 python -m spacy download en,然后将其导入预处理脚本,如下所示:

    import spacy
    nlp = spacy.load('en')
    
  2. 标记化 - 这是将文本拆分为单词的过程。仅执行 text.split() 是不够的(例如 there's 将被视为一个单词,但实际上它是两个单词 thereis)。所以这里我们使用 Tokenizers。在 SpaCy 中,您可以执行以下操作:

    nlp_doc = nlp(text)
    

其中 text 是您的数据集语料库或数据集中的样本。您可以阅读有关文档实例的更多信息 here

  1. 标点删除 - 非常自我解释的过程,通过上一步中的方法完成。要删除标点符号,只需键入:

    import re
    
    # removing punctuation tokens
    text_no_punct = [token.text for token in doc if not token.is_punct]
    
    # remove punctuation tokens that are in the word string like 'bye!' -> 'bye'
    REPLACE_PUNCT = re.compile("(\.)|(\;)|(\:)|(\!)|(\')|(\?)|(\,)|(\")|(\()|(\))|(\[)|(\])")
    text_no_punct = [REPLACE_PUNCT.sub("", tok.text) for tok in text_no_punct]
    
  2. 词性标注 - 词性标注的缩写。它是将文本中的单词标记为对应于特定词性的过程。例如:

    A/DT Part-Of-Speech/NNP Tagger/NNP is/VBZ a/DT piece/NN of/IN
    software/NN that/WDT reads/VBZ text/NN in/IN some/DT
    language/NN and/CC assigns/VBZ parts/NNS of/IN speech/NN to/TO
    each/DT word/NN ,/, such/JJ as/IN noun/NN ,/, verb/NN ,/,
    adjective/NN ,/, etc./FW./.
    

其中斜线后的大写代码是标准的单词标签。可以找到标签列表 here

在 SpaCy 中,这已经通过将文本放入 nlp 实例来完成。您可以通过以下方式获取标签:

    for token in doc:
        print(token.text, token.tag_)
  1. 词法处理:词形还原——这是将单词转换为语言学上有效的基本形式的过程,称为引理:

    nouns → singular nominative form
    verbs → infinitive form
    adjectives → singular, nominative, masculine, indefinitive, positive form
    

在 SpaCy 中,它也已经通过将文本放入 nlp 实例中为您完成。您可以通过以下方式获取每个单词的引理:

    for token in doc:
        print(token.text, token.lemma_)
  1. 删除停用词 - 停用词是不会给句子带来任何新信息或意义的词,可以省略。您猜对了,nlp 实例也已经为您完成了。要过滤停用词,只需键入:

    text_without_stopwords = [token.text for token in doc if not token.is_stop]
    doc = nlp(' '.join(text_without_stopwords))
    

现在你有了一个干净的数据集。您现在可以使用 word2vec or GloVe 预训练模型来创建词向量并将数据输入到某个模型。或者,您可以使用 TF-IDF 通过删除最常见的词来创建词向量。此外,与通常的过程相反,您可能希望保留最具体的词,因为您的任务是更好地区分两个文本。我希望这已经足够清楚了:)