在Python 3.6中使用列表推导来循环并比较两个句子的依赖关系三元组时出现语法错误

时间:2018-06-12 09:55:24

标签: python performance numpy nlp list-comprehension

我有以下两句话:

  1. 我想回家。
  2. 我想离开。
  3. 我的目标是使用建议的内核量化两个句子之间的相似性 this paper。我为每个句子提取所有依赖三元组。这些是3项元组,包含句子中单词之间的所有关系,看起来像(尾巴,关系,头部)

    为了计算相似度,我需要遍历句子中三元组的每个可能组合,并根据节点匹配的数量以及关系是否匹配为相似度分数添加特定数字。

    我尝试在for循环中使用列表推导,因为我认为它比另一个嵌套for循环更有效但是我得到了语法错误。这是我的代码:

    sim = 0
    theta = 2.5
    
    for d1 in deps1:
        [sim += theta for d2 in deps2 if ((d1[0]==d2[0] or d1[2]==d2[2]) and d1[1]==d2[1])]
        [sim += 1 for d2 in deps2 if ((d1[0]==d2[0] or d1[2]==d2[2]) and d1[1]!=d2[1])]
    

    作为参考,这里是deps1和deps2在打印时的样子:

    [('I', 'nsubj', 'want'), ('want', 'ROOT', 'want'), ('to', 'aux', 'go'), ('go', 'xcomp', 'want'), ('home', 'advmod', 'go')]
    [('I', 'nsubj', 'like'), ('would', 'aux', 'like'), ('like', 'ROOT', 'like'), ('to', 'aux', 'leave'), ('leave', 'xcomp', 'like')]
    

    问题:

    1. 使用列表解析执行此操作的正确语法是什么?
    2. 是否有更有效的方法,可能使用numpy(?)来进行此计算?

2 个答案:

答案 0 :(得分:1)

您似乎想要实现的是累积结果,但您不能以这种方式执行,因为表达式sim += theta未返回独立对象以被视为最终列表结果的项。您可以做的是将theta变量与计数器相乘或创建theta的列表,然后使用np.cumsum()itertools.accumulate()创建累积版本,不推荐使用除非你想保留原始结果和累积结果。

此外,您可以使用itertools.product来创建三元组的所有组合,而不是使用两个循环,作为计数器,您可以使用itertools.count

In [36]: from itertools import product, count

In [37]: c = count(1)

In [38]: [2.5*next(c) for d1, d2 in product(deps1,deps2) if ((d1[0]==d2[0] or d1[2]==d2[2]) and d1[1]==d2[1])]
Out[38]: [2.5, 5.0]

要在一个列表理解中执行这两个条件,您可以执行以下操作:

[(d1[1]!=d2[1] or 2.5)*next(c) for d1, d2 in product(deps1,deps2) if d1[0]==d2[0] or d1[2]==d2[2]]

答案 1 :(得分:1)

在Python中,您可以在列表推导中使用表达式,但不能在语句中使用表达式。您可能希望查看Python中的diffence between expressions and statements

关于如何计算((# of matching nodes) * (1 if the relationship doesn't match, 2.5 if it does))的评论中的问题,这是您问题中论文的 SABK 相似度函数的分子,您可以使用生成器来完成和sum函数:

theta = 2.5
sim = sum((((d1[0] == d2[0]) + (d1[2] == d2[2])) * (theta if d1[1] == d2[1] else 1) for d1, d2 in product(deps1, deps2)))

或者,如果你想将每个句子的相似性函数的代码分开,这提高了代码的可读性:

def sim_per_sentence(d1, d2):
    matching_nodes = (d1[0] == d2[0]) + (d2[0] == d2[0])
    relation_sim = theta if d1[1] == d2[1] else 1
    return matching_nodes * relation_sim

sim = sum((sim_per_sentence(d1, d2) for d1, d2 in product(deps1, deps2)))

请注意,如果deps1deps2中有许多元素,则使用generator expression instead of a list comprehension可能会更有效率,因为每次迭代的单个结果不需要存储在记忆中。