依存句法分析工具调研小结

调研了一下依存句法分析,了解了依存句法分析是什么,有什么用,并试用了两个NLP库的句法分析。

依存关系分析是什么

句法分析(syntactic parsing)是自然语言处理中的关键技术之一, 其基本任务是确定句子的句法结构或句子中词汇之间的依存关系。并将句子的语法结构表示为容易理解的结构(通常是树形结构)。

依存句法认为“谓语”中的动词是一个句子的中心,其他成分与动词直接或间接地产生联系。

“依存”指词与词之间支配与被支配的关系,这种关系不是对等的。这种从属关系是由支配词和从属词联结而成。

依存句法本身没有规定要对依存关系进行分类,但为了丰富依存结构传达的句法信息,在实际应用中,一般会给依存树的边加上不同的标记。

图片.png

依存句法分析的作用

假如要翻译以下两个句子。


对于句式灵活的句子,如果不考虑其语法结构,很难直接给用户返回正确的结果。

为了让计算机能够分清指代关系,句法分析非常重要,更是下一步语义分析的前提。
比如“去医院看癌症病人”,“看”可以有“治疗”的意思也有“看望”的意思,容易产生歧义。如果引入句法分析,就会确定意思为“看望”,因为“看”的宾语是“病人”。

API

调研了两个NLP库,分别对句子“1998年11月11日,马化腾和同学张志东在广东省深圳市正式注册成立‘深圳市腾讯计算机系统有限公司’。”进行词法分析,对比效果。

HanLP

https://github.com/hankcs/pyhanlp

from pyhanlp import *

if __name__=="__main__":
    sentence=HanLP.parseDependency("1998年11月11日,马化腾和同学张志东在广东省深圳市正式注册成"
                               "立‘深圳市腾讯计算机系统有限公司’。")
    print(sentence)

    #print(dir(sentence))    #dir()可以查看sentence的方法、属性
    
    '''
    for word in sentence.iterator():
        print("%s --(%s)--> %s" % (word.LEMMA, word.DEPREL, word.HEAD.LEMMA))
    print()
    '''
    # 也可以直接拿到数组,任意顺序或逆序遍历
    word_array=sentence.getWordArray()
    for word  in word_array:
        print("%s --(%s)--> %s" % (word.LEMMA, word.DEPREL, word.HEAD.LEMMA))
    print()

    # 还可以直接遍历子树,从某棵子树的某个节点一路遍历到虚根
    CoNLLWord = JClass("com.hankcs.hanlp.corpus.dependency.CoNll.CoNLLWord")
    head = word_array[12]
    while head.HEAD:
        head = head.HEAD
        if (head == CoNLLWord.ROOT):
            print(head.LEMMA)
        else:
            print(" % s - -(% s) --> " % (head.LEMMA, head.DEPREL))

输出结果

1   1998年   1998年   nt  t   _   2   定中关系    _   _
2   11月11日  11月11日  nt  t   _   11  状中结构    _   _
3   ,   ,   wp  w   _   2   标点符号    _   _
4   马化腾 马化腾 nh  nr  _   7   定中关系    _   _
5   和   和   c   c   _   6   左附加关系   _   _
6   同学  同学  n   n   _   4   并列关系    _   _
7   张志东 张志东 nh  nr  _   11  主谓关系    _   _
8   在   在   p   p   _   11  状中结构    _   _
9   广东省深圳市  广东省深圳市  ns  ns  _   8   介宾关系    _   _
10  正式  正式  a   ad  _   11  状中结构    _   _
11  注册  注册  v   v   _   0   核心关系    _   _
12  成立  成立  v   v   _   11  并列关系    _   _
13  ‘   ‘   wp  w   _   14  标点符号    _   _
14  深圳市腾讯计算机系统有限公司  深圳市腾讯计算机系统有限公司  ni  nt  _   12  动宾关系    _   _
15  ’   ’   wp  w   _   14  标点符号    _   _
16  。   。   wp  w   _   11  标点符号    _   _

1998年 --(定中关系)--> 11月11日
11月11日 --(状中结构)--> 注册
, --(标点符号)--> 11月11日
马化腾 --(定中关系)--> 张志东
和 --(左附加关系)--> 同学
同学 --(并列关系)--> 马化腾
张志东 --(主谓关系)--> 注册
在 --(状中结构)--> 注册
广东省深圳市 --(介宾关系)--> 在
正式 --(状中结构)--> 注册
注册 --(核心关系)--> ##核心##
成立 --(并列关系)--> 注册
‘ --(标点符号)--> 深圳市腾讯计算机系统有限公司
深圳市腾讯计算机系统有限公司 --(动宾关系)--> 成立
’ --(标点符号)--> 深圳市腾讯计算机系统有限公司
。 --(标点符号)--> 注册

 深圳市腾讯计算机系统有限公司 - -(动宾关系) --> 
 成立 - -(并列关系) --> 
 注册 - -(核心关系) --> 
##核心##

FudanNLP

https://github.com/FudanNLP/fnlp
用提供的demo来进行使用

package org.fnlp.demo.nlp;
import org.fnlp.nlp.cn.tag.POSTagger;
import org.fnlp.nlp.parser.dep.DependencyTree;
import org.fnlp.nlp.parser.dep.JointParser;
/**
 * 依存句法分析使用示例
 * @author xpqiu
 *
 */
public class DepParser {

    private static JointParser parser;

    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        parser = new JointParser("./models/dep.m");
        
        System.out.println("得到支持的依存关系类型集合");
        System.out.println(parser.getSupportedTypes());
        
        String word = "1998年11月11日,马化腾和同学张志东在广东省深圳市正式注册成立‘深圳市腾讯计算机系统有限公司’。";
        test(word);

    }

    /**
     * 只输入句子,不带词性
     * @throws Exception 
     */
    private static void test(String word) throws Exception {        
        POSTagger tag = new POSTagger("./models/seg.m","./models/pos.m");
        String[][] s = tag.tag2Array(word);
        try {
            DependencyTree tree = parser.parse2T(s[0],s[1]);
            System.out.println(tree.toString());
            String stree = parser.parse2String(s[0],s[1],true);
            System.out.println(stree);
        } catch (Exception e) {         
            e.printStackTrace();
        }
    }

}

得到输出结果

0 1998年 时间短语 2 定语
1 11月 时间短语 2 定语
2 11日 时间短语 7 定语
3 , 标点 2 标点
4 马化腾 人名 7 并列
5 和 并列连词 4 关联
6 同学 名词 7 定语
7 张志东 人名 -1 核心词
8 在 介词 7 标点
9 广东省 地名 10 定语
10 深圳市 地名 8 介宾
11 正式 副词 12 状语
12 注册 动词 8 介宾
13 成立 动词 12 并列
14 ‘ 标点 20 标点
15 深圳市 地名 20 定语
16 腾讯 机构名 20 定语
17 计算机 名词 18 定语
18 系统 名词 20 定语
19 有限 形容词 20 定语
20 公司 名词 13 宾语
21 ’ 标点 20 标点
22 。 标点 8 标点

1998年 11月 11日 , 马化腾 和 同学 张志东 在 广东省 深圳市 正式 注册 成立 ‘ 深圳市 腾讯 计算机 系统 有限 公司 ’ 。
时间短语 时间短语 时间短语 标点 人名 并列连词 名词 人名 介词 地名 地名 副词 动词 动词 标点 地名 机构名 名词 名词 形容词 名词 标点 标点
2 2 7 2 7 4 7 -1 7 10 8 12 8 12 20 20 20 18 20 20 13 20 8
定语 定语 定语 标点 并列 关联 定语 核心词 标点 定语 介宾 状语 介宾 并列 标点 定语 定语 定语 定语 定语 宾语 标点 标点

对比

效果对比

对于句子 “上海浦东机场西货运区货运工王某某被确诊为新冠肺炎”。
HanLP结果

1   上海浦东机场  上海浦东机场  ni  nt  _   4   定中关系    _   _
2   西   西   nd  f   _   3   定中关系    _   _
3   货运区 货运区 n   n   _   4   定中关系    _   _
4   货运工 货运工 n   n   _   5   定中关系    _   _
5   王某某 王某某 nh  nr  _   7   前置宾语    _   _
6   被   被   p   p   _   7   状中结构    _   _
7   确诊  确诊  v   v   _   0   核心关系    _   _
8   为   为   v   v   _   7   动补结构    _   _
9   新冠肺炎    新冠肺炎    n   n   _   8   动宾关系    _   _
10  。   。   wp  w   _   7   标点符号    _   _

fudanNLP结果

0 上海 地名 1 定语
1 浦东 地名 4 定语
2 机场 名词 4 定语
3 西货运区 名词 4 定语
4 货运工 名词 5 定语
5 王某某 人名 6 主语
6 被 被动词 -1 核心词
7 确诊 动词 6 补语
8 为 介词 7 补语
9 新 形容词 10 定语
10 冠肺炎 名词 8 介宾
11 。 标点 6 标点

fudanNLP对于“新冠肺炎”这个分词并不准确,同时核心词感觉也不准确。

时间效率对比

HanLP


HanLP的python版时间效率
HanLP的java1.x版本

可以看出HanLP的python版本和Java版本的运行速度是差不多的。

FudanNLP


FudanNLP的时间效率

fudanNLP的速度要稍快于HanLP

参考链接

句法分析 (syntactic parsing) 在 NLP 领域的应用是怎样的? - cstghitpku的回答 - 知乎
https://www.zhihu.com/question/39034550/answer/79419855

https://blog.csdn.net/zkq_1986/article/details/106412110

https://www.cnblogs.com/smartisn/p/13823316.html

你可能感兴趣的:(依存句法分析工具调研小结)