跳转至

使用 Spacy和 FuzzyWuzzy 构建关键字提取API

通常,在处理长文本序列时,您需要分解这些序列并提取单个关键字以执行搜索或查询数据库。

如果输入文本是自然语言,您很可能不想用每个单词查询数据库,那么您可能想要从输入中选择一组唯一的关键字,并使用这些单词或单词短语执行有效的搜索。

此任务称为关键字提取,得益于生产级 NLP 工具如Spacy 只需几行 Python 就可以完成。在这篇文章中,我们将介绍:

  • 如何使用 Spacy 构建简单而健壮的关键字提取工具
  • 如何使用模糊模糊处理拼写错误并查找给定关键字的 fuzzyWuzzy

在开始之前,请确保运行: pip install spacy fuzzywuzzy 安装所有必需的包。

使用 Spacy 的关键字提取

对于关键字提取功能,我们将使用 Spacy 的两个中心思想 - 核心语言模型和文档对象。

Spacy 核心语言模型 包括:

用于预测命名实体、部分语音标记和句法依赖项的通用预训练模型。可以开箱即用,对更具体的数据进行微调。

Spacy 文档 对象为:

用于访问语言注释的容器...(和)token 结构的数组

因此,通过模型创建文档对象,我们有权访问许多非常有用(且功能强大的)NLP 派生属性和函数,包括语音部分标记和名词块,这些属性和函数将是关键字提取器功能的核心。

下载语言模型

有了 Spacy,我们必须首先下载我们想使用的语言模型。截至今天,Spacy 的 version 2.2.4 当前语言型号为 10 种不同的语言,所有语言大小不一。我将使用英文核心模型的小版本。我选择了小型模型,因为我在 Heroku 部署的内存中大模型的大小有问题。根据部署此模型的地点/方法,您可能能够使用大型模型。要使用 Spacy 的 CLI 下载语言模型,请运行以下命令::

python -m spacy download en_core_web_sm

现在下载了模型,您可以加载它并创建 nlp 对象:

import spacy
nlp = spacy.load("en_core_web_sm”)

我们的语言 nlp 模型将作为参数传递给下面的 extract_keywords() 函数以生成 doc 对象。

关键字提取函数采用 3 个参数:

  • 语言模型 nlp
  • sequence 我们要从中提取关键字的单词字符串。
  • 和字符串的可选列表 special_tags 。此参数允许用户指定一个单词/短语的特殊列表,如果这些单词/短语存在于序列中,则默认情况下要添加到输出中。

下面的代码段显示了函数的工作原理:

  1. 通过 doc 语言模型传递字符串序列来创建对象。
  2. 如果特殊tokens以序列中显示,则将它们添加到最终结果中。
  3. 迭代文档名词 chunks 所需的列表中时向结果添加名词 pos_tag 区块。
  4. 最后,我们遍数所有单个令牌,并添加那些在所需集 pos_tag 中的令牌,这些令牌不是语言模型的默认停止字列表的一部分。如果需要,可以将自定义停止词追加到此列表中。

然后,该函数返回结果变量中最终出现的所有唯一单词的列表

import spacy
import subprocess
from string import punctuation

def extract_keywords(nlp, sequence, special_tags : list = None):
    """ Takes a Spacy core language model,
    string sequence of text and optional
    list of special tags as arguments.

    If any of the words in the string are 
    in the list of special tags they are immediately 
    added to the result.  

    Arguments:
        sequence {str} -- string sequence to have keywords extracted from

    Keyword Arguments:
        tags {list} --  list of tags to be automatically added (default: {None})

    Returns:
        {list} -- list of the unique keywords extracted from a string
    """    
    result = []

    # custom list of part of speech tags we are interested in
    # we are interested in proper nouns, nouns, and adjectives
    # edit this list of POS tags according to your needs. 
    pos_tag = ['PROPN','NOUN','ADJ']

    # create a spacy doc object by calling the nlp object on the input sequence
    doc = nlp(sequence.lower())

    # if special tags are given and exist in the input sequence
    # add them to results by default
    if special_tags:
        tags = [tag.lower() for tag in special_tags]
        for token in doc:
            if token.text in tags:
                result.append(token.text)

    for chunk in doc.noun_chunks:
        final_chunk = ""
        for token in chunk:
            if (token.pos_ in pos_tag):
                final_chunk =  final_chunk + token.text + " "
        if final_chunk:
            result.append(final_chunk.strip())


    for token in doc:
        if (token.text in nlp.Defaults.stop_words or token.text in punctuation):
            continue
        if (token.pos_ in pos_tag):
            result.append(token.text)
    return list(set(result))

if __name__ == "__main__":
  """
  install the langauge model using the subprocess package
  useful when hosting the service in the cloud as it prevents against
  us forgetting to do this via the CLI
  """
  subprocess.call("python -m spacy download en_core_web_sm",shell=True)

  # load the small english language model, 
  nlp = spacy.load("en_core_web_sm")

  print("Loaded language vocabulary")
  print(extract_keywords(nlp,"""Learning how to use natural language
   processing in python and build Flask API's is easy when you have packages like spacy and fuzzywuzzy"""))

另一个例子 Hotword 函数

def get_hotwords(text):
    result = []
    pos_tag = ['PROPN', 'ADJ', 'NOUN'] # 1
    doc = nlp(text.lower()) # 2
    for token in doc:
        # 3
        if(token.text in nlp.Defaults.stop_words or token.text in punctuation):
            continue
        # 4
        if(token.pos_ in pos_tag):
            result.append(token.text)

    return result # 5

模糊字符串匹配与模糊模糊

当人类键入单词时,错别字和错误是不可避免的。在关键字搜索/匹配的上下文中,这是一个问题,但它是一个可以使用模糊匹配算法优雅地解决的问题。

Python包 FuzzyWuzzy 实现了一种非常有效的模糊匹配算法 Levenshtein Distance

Levenshtein 距离是计算将源词 S 转换为目标单词 T 的成本的公式。该算法惩罚需要许多更改才能转换为目标词的源词,并倾向于需要小转换的单词。

使用FuzzyWuzzy

FuzzyWuzzy匹配实现速度非常快。从 ratio 包导入导入默认的 Levenshtein 距离评分 process.extractBests() 机制,并允许我们在目标列表中计算 Levenshtein 距离,并返回定义截止点上方的结果。 score_cutoff 参数是您可能想要微调自己,以获得最佳匹配结果。

from fuzzywuzzy import process
from fuzzywuzzy.fuzz import ratio

def get_fuzzy_similarity(token = None, dictionary = None):
    """Returns similar words and similarity scores for a given token
    from a provided dictionary of words

    Keyword Arguments:
        token {str} -- the reference word (default: {None})
        dictionary {list} -- the list of target words (default: {None})

    Returns:
        [list] -- a list of tuples in the form `(matched_word, similarity score)`
    """    

    if token and dictionary:
        return process.extractBests(token, dictionary, scorer= ratio, score_cutoff=70)
    else:
        return []
if __name__ == "__main__":
  # toy dictionary of words we will query our mispelt input against
  word_dictionary = ['medium','twitter','google','linkedIn','facebook']

  # print the results of the fuzzy match search
  print(get_fuzzy_similarity('mediaum',word_dictionary))

原文翻译自网文,作者: Charles Pierse
原文: https://towardsdatascience.com/build-a-keyword-extraction-api-with-spacy-flask-and-fuzzywuzzy-4909d7ffc105

参考: 1. Extract Keywords Using spaCy in Python