hanlp学习七:依存句法分析


一 概念:

       从属词:一个词修饰另一个词

       支配词:被修饰的词语

       依存关系:从属词与支配词间语法关系

       依存句法树:将一个句子中所有词语的依存关系以有 向的形式表示出来,就会得到一颗树

       依存句法树库:由大量人工标注的依存句法树组成的语料库

       依存句法分析:分析句子的依存语法的一种中高级NLP人物,其输入通常是词语与词性,输出则是一棵依存句法树。

二 基于转移的依存句法分析流程:

     将一棵依存句法树的构建过程表示为两个动作,如果机器学习模型能够根据句子的某些特征准确预测这些动作,那么计算机能够根据这些动作拼装出正确的依存句法树了。这种拼装动作称为转移

      a.确定转移系统

            转移系统(虚拟机器)根据自己的状态和输入的单词预测下一步要执行的移动动作,最后根据转移动作拼装句法树

            转移系统主要负责制定所有可执行的动作以及相应的条件

      b.特征提取 

             有了特征之后,转移系统的一个状态就被表示为一个稀疏的二进制向量

      c.规范:

              将语料库中的依存句法树转换为正确的转移动作序列,以供机器 学习

      c.分类器预测转移动作

三  代码:

          训练模型

# -*- coding:utf-8 -*-
# Author: hankcs
# Date: 2019-02-11 23:18
# 《自然语言处理入门》12.5.1 训练模型
# 配套书籍:http://nlp.hankcs.com/book.php
# 讨论答疑:https://bbs.hankcs.com/

from pyhanlp import *
import zipfile
import os

from pyhanlp.static import download, remove_file, HANLP_DATA_PATH


def test_data_path():
    """
    获取测试数据路径,位于$root/data/test,根目录由配置文件指定。
    :return:
    """
    data_path = os.path.join(HANLP_DATA_PATH, 'test')
    if not os.path.isdir(data_path):
        os.mkdir(data_path)
    return data_path


def ensure_data(data_name, data_url):
    root_path = test_data_path()
    dest_path = os.path.join(root_path, data_name)
    if os.path.exists(dest_path):
        return dest_path
    if data_url.endswith('.zip'):
        dest_path += '.zip'
    download(data_url, dest_path)
    if data_url.endswith('.zip'):
        with zipfile.ZipFile(dest_path, "r") as archive:
            archive.extractall(root_path)
        remove_file(dest_path)
        dest_path = dest_path[:-len('.zip')]
    return dest_path

KBeamArcEagerDependencyParser = JClass('com.hankcs.hanlp.dependency.perceptron.parser.KBeamArcEagerDependencyParser')
CTB_ROOT = ensure_data("ctb8.0-dep", "http://file.hankcs.com/corpus/ctb8.0-dep.zip")
CTB_TRAIN = CTB_ROOT + "/train.conll"#训练集
CTB_DEV = CTB_ROOT + "/dev.conll" # 开发集
CTB_TEST = CTB_ROOT + "/test.conll" # 词聚类问件
CTB_MODEL = CTB_ROOT + "/ctb.bin" # 模型
BROWN_CLUSTER = ensure_data("wiki-cn-cluster.txt", "http://file.hankcs.com/corpus/wiki-cn-cluster.zip")

if __name__ == '__main__':
    parser = KBeamArcEagerDependencyParser.train(CTB_TRAIN, CTB_DEV, BROWN_CLUSTER, CTB_MODEL)
    print(parser.parse("人吃鱼"))
    score = parser.evaluate(CTB_TEST)
    print("UAS=%.1f LAS=%.1f\n" % (score[0], score[1]))

    意见抽取例子

# -*- coding:utf-8 -*-
# Author: hankcs
# Date: 2019-06-02 18:03
# 《自然语言处理入门》12.6 案例:基于依存句法树的意见抽取
# 配套书籍:http://nlp.hankcs.com/book.php
# 讨论答疑:https://bbs.hankcs.com/

from pyhanlp import *

CoNLLSentence = JClass('com.hankcs.hanlp.corpus.dependency.CoNll.CoNLLSentence')
CoNLLWord = JClass('com.hankcs.hanlp.corpus.dependency.CoNll.CoNLLWord')
IDependencyParser = JClass('com.hankcs.hanlp.dependency.IDependencyParser')
KBeamArcEagerDependencyParser = JClass('com.hankcs.hanlp.dependency.perceptron.parser.KBeamArcEagerDependencyParser')


def main():
    parser = KBeamArcEagerDependencyParser()
    tree = parser.parse("电池非常棒,机身不长,长的是待机,但是屏幕分辨率不高。")
    print(tree)
    print("第一版")
    extactOpinion1(tree)
    print("第二版")
    extactOpinion2(tree)
    print("第三版")
    extactOpinion3(tree)


def extactOpinion1(tree):
    for word in tree.iterator():
        if word.POSTAG == "NN" and word.DEPREL == "nsubj":
            print("%s = %s" % (word.LEMMA, word.HEAD.LEMMA))


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))


def extactOpinion3(tree):
    for word in tree.iterator():
        if word.POSTAG == "NN":
            if 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))
            elif word.DEPREL == "attr":
                top = tree.findChildren(word.HEAD, "top")  # ②主题

                if not top.isEmpty():
                    print("%s = %s" % (word.LEMMA, top.get(0).LEMMA))


if __name__ == '__main__':
    main()

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM