【问题标题】:Search for words in text, regardless of inflection: Python搜索文本中的单词,不考虑变形:Python
【发布时间】:2019-11-06 17:08:44
【问题描述】:

我正在尝试在给定的文本中搜索指定的单词列表。代码非常简单。

# put the words you want to match into a list
word_list = ["eat", "car", "house", "pick up", "child"]

# get input text from the user 
user_prompt = input("Please enter some text: ")

# loop over each word in word_list and check if it is a substring of user_prompt
for word in word_list:
    if word in user_prompt:
        print("{} is in the user string".format(word))

问题是,当我输入以下文本时:“我在车上接我的孩子,他们吃了一些梨。” 它与单词不匹配 “pick up ""吃"。我想这是因为在文本中它们是过去形式,而在单词表中它们是不定式。因此,它只会搜索完全匹配,不会考虑变形(动词形式、不规则动词等)。

有没有一种方法可以搜索文本以匹配单词列表中的单词而不考虑变形? 谢谢!

【问题讨论】:

  • 吃/吃会很困难,换句话说stemming应该可以工作。
  • 第二个用于词干化/词形还原。对于诸如吃/吃之类的时态转换,您可能需要使用常用词词典来替换文本,或者使用可以自动执行此操作的 NLP 包

标签: python list text nlp


【解决方案1】:

这是一项自然语言处理任务,即这是一个与我们正在使用的自然语言密切相关的问题。这个问题不仅仅是算法问题,因为算法首先必须“理解”或“代表”屈折在您使用的语言中的工作方式。

这些解决方案适用于统计模型,这意味着我们无法获得 100% 的准确率。这只是因为自然语言过于复杂,无法通过确定性算法以 100% 的准确率解决此问题。

对于英语,有一个 Python 包 LemmInflect,它声称对英语动词有 96.1% 的准确率。

使用它,我们可以执行以下操作:

import lemminflect


def find_lemmas(word_set: set, test_string: str) -> list:
    word_set = set(word_set)
    found_lemmas = []

    for word in test_string.split(" "):
        lemma_dict = lemminflect.getAllLemmas(word)
        if lemma_dict:
            # values of getAllLemmas are tuples, we need a flat set
            lemmas = {y for x in lemma_dict.values() for y in x}
            found_lemma = list(lemmas & word_set)
            if found_lemma:
                found_lemmas.append(found_lemma[0])

    return found_lemmas

这给了我们:

>>> word_set = {"eat", "car", "house", "pick up", "child"}
>>> test_string = """After he ate the cake he left the 
    house and went to his car. Then he wondered whether picking up the 
    children now would really be the best idea."""
>>> find_lemmas(word_set=word_set, test_string=test_string)
['eat', 'house', 'child']

我们可以看到,"pick up" 未被识别。这是因为我们正在逐字解析 test_string,这会破坏任何组合词的结构。因此,获得这些组合的引理需要更复杂的逻辑。

我们可以将word_set 中的项目拆分为它们的组件,并分别检查每个组件是否存在。然后我们仍然需要一个能够确定在word_set in 中组合词的两个组件的屈折形式的出现是否实际上是组合词的屈折形式的出现,即我们需要排除以下场景:

"She bent down to pick a penny. Then she looked up and realised she had lost a pound."

在这种情况下,我们会找到"pick" 的形式和"up" 的形式,但这不是"pick up" 的形式。

【讨论】:

    【解决方案2】:

    正如 jonathan.scholbach 所说,您要做的是对文本中的单词进行词形还原。词的引理是您可以在字典中找到的词的形式。

    spacy 有一个简单的方法可以做到这一点,如下所示:

    import spacy
    
    nlp=spacy.load('en_core_web_sm')
    sent = "  I picked up my children in the car and they ate some pears.."
    word_list = ["eat", "car", "house", "pick up", "child"]
    doc = nlp(sent)
    doc_lemma = " "
    for token in doc:
        #for words without a defined lemma like pronouns, spacy returns -PRON-
        #let's capture those cases and use the form in the text: 
        if token.lemma_[0] == '-':
          doc_lemma = doc_lemma + token.text.lower() + " "
        else:
            #Put the lemmas in a string, so words like "pick up" will be found as well
            doc_lemma = doc_lemma + token.lemma_ + " "
    
    #word_list now lookks like that:
    # i pick up my child in the car and they eat some pear ..
    for word in word_list:
        if word in doc_lemma:
            print(word)
    #output:
    #    eat
    #    car
    #    pick up
    #    child
    

    编辑: 如 cmets 中所述,此解决方案仅匹配直接相邻的化合物:pick upI picked up the apple 中匹配,但在 Did you pick her up? 中不匹配

    pick up这样的动词+助词的解决方法可能是这样的:

    #find root (the verb) and a corresponding particle
    root= None
    particle = None
    for token in doc:
        if token.dep_=="ROOT":
            root= token.lemma_
    if token.dep_ == "prt":
        particle= token.lemma_
    #if both particle and root exist in the sentence, add them together to our final string,
    #so verb + particle like "pick up" is matched, even when not next to each other.
    if root is not None and particle is not None:
        doc_lemma = doc_lemma + root + " " + particle 
    

    此解决方法可能存在其他缺陷,例如涉及子条款时。

    【讨论】:

    • 我编辑了我的答案,更多信息请阅读here
    • 这不应该检测到 "Did you pick everything up?" 中的“pick up"”,对吧?所以我们的两种解决方案都存在传播化合物的问题?
    • 是的,我没想到。让我考虑一下。
    • 对于复合词/短语,例如短语动词“pick up”,我们是否需要运行某种 n-gram?
    • 我编辑了我的帖子,使用依赖项匹配动词+助词短语的解决方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-22
    • 2016-06-18
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多