仔细观察,不难发现“电池”与“棒”、“机身”与“长”、“分辨率”与“高”之间的依存关系都是 nsubj (名词性主语)。1.利用这一规律, 不难写出第一版遍历算法, 也就是用个for 循环去遍历树中的每个节点。对于算法遍历树中的每一个词语, 如果其词性为名词且作为某个形容词的名词性主语,则认为该名词是属性,而形容词是意见。运行代码如下:
def extactOpinion1(tree): for word in tree.iterator(): if word.POSTAG == "NN" and word.DEPREL == "nsubj": print("%s = %s" % (word.LEMMA, word.HEAD.LEMMA)) print("第一版") extactOpinion1(tree)
结果如下:
第一版 电池 = 棒 机身 = 长 分辨率 = 高
2.虽然的确提取出了一些意见,然而后两个都是错误的。这一版算法存在的问题之一是没有考虑到“机身不长””“分辨率不高"等否定修饰关系。否定修饰关系在依存句法中的标记为 neg,于是我们只需检查形容词是否存在否定修饰的支配词即可。于是得出第二版算法:
def extactOpinion2(tree): for word in tree.iterator(): if word.POSTAG == "NN" and word.DEPREL == "nsubj": if tree.findChildren(word.HEAD, "neg").isEmpty(): print("%s = %s" % (word.LEMMA, word.HEAD.LEMMA)) else: print("%s = 不%s" % (word.LEMMA, word.HEAD.LEMMA)) print("第二版") extactOpinion2(tree)
结果如下:
第二版 电池 = 棒 机身 = 不长 分辨率 = 不高
3.接下来思考如何提取“待机”的意见,“待机”与“长”之间的公共父节点为“是”,于是我们得到第三版算法如下:
def extactOpinion3(tree): for word in tree.iterator(): if word.POSTAG == "