【问题标题】:search similar meaning phrases with nltk使用 nltk 搜索相似含义的短语
【发布时间】:2014-03-17 11:06:43
【问题描述】:

我有一堆不相关的段落,我需要遍历它们以找到类似的事件,例如,给定搜索 object falls,我找到一个布尔值 True 用于包含以下内容的文本:

  • 盒子从架子上掉下来
  • 灯泡摔在地上
  • 一块石膏从天花板上掉下来

还有False

  • 责任落在了莎拉身上
  • 气温骤降

我可以使用 nltktokenisetag 并获得 Wordnet synsets,但我发现很难弄清楚如何适应nltk 的运动部件一起达到预期的效果。在寻找同义词之前我应该​​chunk 吗?我应该写context-free grammar 吗?从 treebank 标记转换为 Wordnet 语法标记时是否有最佳实践? nltk book 没有解释这些,我在nltk cookbook 上也找不到。

答案中包含pandas 的答案可获得奖励积分。


[编辑]:

一些开始工作的代码

In [1]:

from nltk.tag import pos_tag
from nltk.tokenize import word_tokenize
from pandas import Series

def tag(x):
    return pos_tag(word_tokenize(x))

phrases = ['Box fell from shelf',
           'Bulb shattered on the ground',
           'A piece of plaster fell from the ceiling',
           'The blame fell on Sarah',
           'Berlin fell on May',
           'The temperature fell abruptly']

ser = Series(phrases)
ser.map(tag)

Out[1]:

0    [(Box, NNP), (fell, VBD), (from, IN), (shelf, ...
1    [(Bulb, NNP), (shattered, VBD), (on, IN), (the...
2    [(A, DT), (piece, NN), (of, IN), (plaster, NN)...
3    [(The, DT), (blame, NN), (fell, VBD), (on, IN)...
4    [(Berlin, NNP), (fell, VBD), (on, IN), (May, N...
5    [(The, DT), (temperature, NN), (fell, VBD), (a...
dtype: object

【问题讨论】:

  • 以前发过similar question,但我希望至少能用pseudocode 来吸引答案。

标签: python search nlp nltk


【解决方案1】:

我会这样做的方式如下:

使用 nltk 查找后跟一两个动词的名词。为了符合您的确切规格,我将使用 Wordnet: 唯一应该找到的名词(NN、NNP、PRP、NNS)是那些与“物理”或“物质”有语义关系的名词和唯一的动词(VB、VBZ、VBD 等......)应该找到与“fall”有语义关系的那些。

我提到了“一两个动词”,因为动词前面可以有助动词。您还可以创建一个依赖树来发现主谓关系,但在这种情况下似乎没有必要。

您可能还想确保排除地点名称并保留人名(因为您会接受“约翰倒下”而不是“柏林倒下”)。这也可以通过 Wordnet 来完成,位置有标签“noun.location”。

我不确定您必须在哪种情况下转换标签,所以我无法提供正确的答案,在我看来,在这种情况下您可能不需要这样:您使用 POS 标签来识别名词和动词,然后检查每个名词和动词是否属于同义词。

希望这会有所帮助。

【讨论】:

  • 我如何使用 NLTK 来查找后跟一两个动词的名词?我应该使用RegexpParser 和语法吗?您的回答很有帮助,但使用代码示例会更有用。
  • 从 ser.map(tag) 获取结果并循环遍历每个元素,如果当前元素是 NN、NNP 或 PRP,则检查下两个是否为 VB*。如果标签合适,取出单词并使用 wordnet 检查它们(我不知道如何从 python 中做到这一点)。
【解决方案2】:

不完美,但大部分工作都在那里。现在开始硬编码代词(例如'it')和closed-class words,并添加多个目标来处理'shattered'之类的事情。不是单行,但也不是不可能完成的任务!

from nltk.tag import pos_tag
from nltk.tokenize import word_tokenize
from pandas import Series, DataFrame
import collections
from nltk import wordnet
wn = wordnet.wordnet

def tag(x):
    return pos_tag(word_tokenize(x))

def flatten(l):
    for el in l:
        if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
            for sub in flatten(el):
                yield sub
        else:
            yield el

def noun_verb_match(phrase, nouns, verbs):
    res = []
    for i in range(len(phrase) -1):
        if (phrase[i][1] in nouns) &\
            (phrase[i + 1][1] in verbs):
            res.append((phrase[i], phrase[i + 1]))
    return res

def hypernym_paths(word, pos):
    res = [x.hypernym_paths() for x in wn.synsets(word, pos)]
    return set(flatten(res))

def bool_syn(double, noun_syn, verb_syn):
    """
    Returns boolean if noun/verb double contains the target Wordnet Synsets.
    Arguments:
    double: ((noun, tag), (verb, tag))
    noun_syn, verb_syn: Wordnet Synset string (i.e., 'travel.v.01')
    """
    noun = double[0][0]
    verb = double[1][0]
    noun_bool = wn.synset(noun_syn) in hypernym_paths(noun, 'n')
    verb_bool = wn.synset(verb_syn) in hypernym_paths(verb, 'v')
    return noun_bool & verb_bool

def bool_loop(l, f):
    """
    Tests all list elements for truthiness and
    returns True if any is True.
    Arguments:
    l: List.
    e: List element.
    f: Function returning boolean.
    """
    if len(l) == 0:
        return False
    else:
        return f(l[0]) | bool_loop(l[1:], f)

def bool_noun_verb(series, nouns, verbs, noun_synset_target, verb_synset_target):
    tagged = series.map(tag)
    nvm = lambda x: noun_verb_match(x, nouns, verbs)
    matches = tagged.apply(nvm)
    bs = lambda x: bool_syn(x, noun_synset_target, verb_synset_target)
    return matches.apply(lambda x: bool_loop(x, bs))

phrases = ['Box fell from shelf',
           'Bulb shattered on the ground',
           'A piece of plaster fell from the ceiling',
           'The blame fell on Sarah',
           'Berlin fell on May',
           'The temperature fell abruptly',
           'It fell on the floor']

nouns = "NN NNP PRP NNS".split()
verbs = "VB VBD VBZ".split()
noun_synset_target = 'artifact.n.01'
verb_synset_target = 'travel.v.01'

df = DataFrame()
df['text'] = Series(phrases)
df['fall'] = bool_noun_verb(df.text, nouns, verbs, noun_synset_target, verb_synset_target)
df

【讨论】:

    猜你喜欢
    • 2012-02-01
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多