从头开始训练一个依存分析器

从头开始训练一个依存分析器

依存句法通过分析语言单位内成分之前的依存关系解释其句法结构,主张句子中核心动词是支配其他成分的中心成分。而它本身却不受其他任何成分的支配,所有受支配成分都以某种关系从属于支配者。

重要概念

  • 依存句法认为“谓语”中的动词是一个句子的中心,其他成分与动词直接或间接地产生联系。
  • 依存句法理论中,“依存”指词与词之间支配与被支配的关系,这种关系不是对等的,这种关系具有方向。确切的说,处于支配地位的成分称之为支配者,而处于被支配地位的成分称之为从属者。
  • 依存语法本身没有规定要对依存关系进行分类,但为了丰富依存结构传达的句法信息,在实际应用中,一般会给依存树的边加上不同的标记。
  • 依存语法存在一个共同的基本假设:句法结构本质上包含词和词之间的依存(修饰)关系。一个依存关系连接两个词,分别是核心词和依存词。依存关系可以细分为不同的类型,表示两个词之间的具体句法关系。

关系标签

标签表示从属的语法功能,名词性的标签是:

  • root:中心词,通常是动词
  • nsubj:名词性主语(nominal subject)
  • dobj:直接宾语(direct object)
  • prep:介词
  • pobj:介词宾语
  • cc:连词

其他常用的标签:

  • compound:复合词
  • advmod:状语
  • det:限定词
  • amod:形容词修饰语-

标注关系

中文依存分析关系如下:
在这里插入图片描述

应用场景

  • 帮助进行NER标注:名词短语通常被标记为一个完整的实体,这些短语经过语法解析后就可以被准确识别。
  • 机器翻译:通过构建完整的语法树,可以正确的建立词语之间的关系避免翻译歧义。
  • 通过重新定义词语之间的联系,识别词语之间的关系,例如:人物亲戚关系。

接下来开始 spaCy 训练依存分析器。

注:本文使用 spaCy 3.0 代码实现。



一、自定义模型


1、导入所需要的包与模块
from __future__ import unicode_literals, print_function
import plac
import random
import spacy
from pathlib import Path
from spacy.training import Example
2、导入训练样本
TRAIN_DATA = [
    ("房祖名 是 成龙 的 儿子", {
        'heads': [2, 4, 2, 2, 0],
        'deps': ['SON', '-', 'ROOT', '-', 'ATT']
    }),
    ("张若昀 的 妻子 是 唐艺昕", {
        'heads': [0, 0, 4, 2, 0],
        'deps': ['ROOT', '-', 'ATT', '-', 'HUS']
    }),
    ("陈凯歌 是 陈赫 的 舅舅", {
        'heads': [2, 4, 2, 2, 0],
        'deps': ['UNCLE', '-', 'ROOT', '-', 'ATT']
    }),
    ("焦曼婷 是 焦恩俊 的 女儿", {
        'heads': [2, 4, 2, 2, 0],
        'deps': ['DAU', '-', 'ROOT', '-', 'ATT']
    })
]

数据可以自己再添加,越多越好,其中heads为根据下标的依存匹配(即从属词与支配词的划分)。



二、训练模型


1、模型参数的注解(语种、输出目录以及训练迭代次数)
@plac.annotations(
    lang=("ISO Code of language to use", "option", "l", str),
    output_dir=("Optional output directory", "option", "o", Path),
    n_iter=("Number of training iterations", "option", "n", int))
2、对现有的模型进行优化
if model is not None:
        nlp = spacy.load(model)  # 加载存在的模型  
        print("Loaded model '%s'" % model)
    else:
        nlp = spacy.blank('en')  # 创建空白模型
        print("Created blank 'en' model")
3、创建内置管道组件

使用 add_pipeline函数创建流水线

if 'parser' in nlp.pipe_names:
    nlp.remove_pipe('parser')
parser = nlp.add_pipe('parser', first=True)
4、添加train data的标签
for text, annotations in TRAIN_DATA:
        for dep in annotations.get('deps', []):
            parser.add_label(dep)
5、构建模型

训练过程本身很简单,nlp.update()方法为我们抽象了所有内容,由 spaCy 处理实际的机器学习和训练过程。

# 禁用流水线中所有其他组件,以便只训练/更新NER标注器
other_pipes = [pipe for pipe in nlp.pipe_names if pipe != 'parser']
    with nlp.disable_pipes(*other_pipes):  # 仅训练我们标注的标签,假如没有则会对所有的标签训练,
        for itn in range(n_iter):
            random.shuffle(TRAIN_DATA)     # 训练数据每次迭代打乱顺序
            losses = {}                    # 定义损失函数
            for batch in spacy.util.minibatch(TRAIN_DATA, size=2):
                for text, annotations in batch:
                    #建立一个案例
                    doc = nlp.make_doc(text)
                    example = Example.from_dict(doc, annotations)
                    nlp.update([example], losses=losses, drop=0.3)
            print(losses)
6、模型保存
test_model(nlp)

if output_dir is not None:
    output_dir = Path(output_dir)
    if not output_dir.exists():
        output_dir.mkdir()
    nlp.to_disk(output_dir)
    print("Saved model to", output_dir)
    print("Loading from", output_dir)
    nlp2 = spacy.load(output_dir)
    test_model(nlp2)


三、模型测试

def test_model(nlp):
    texts = ["小红 是 小绿 的 妻子",
             "房祖名 和 成龙 的 关系 是 父子",
             "张晓龙 和 张佳宁 的 舅舅"]
    docs = nlp.pipe(texts)
    for doc in docs:
        print(doc.text)
        print([(t.text, t.dep_, t.head.text) for t in doc if t.dep_ != '-'])

if __name__ == '__main__':
    plac.call(main)

模型的效果如下

小红 是 小绿 的 妻子
[('小红', 'FAT', '小绿'), ('是', 'dep', '小红'), ('小绿', 'ROOT', '小绿'), ('妻子', 'dep', '小绿')]
房祖名 和 成龙 的 关系 是 父子
[('房祖名', 'SON', '成龙'), ('和', 'dep', '房祖名'), ('成龙', 'ROOT', '成龙'), ('关系', 'ATT', '父子'), ('父子', 'dep', '成龙')]
张晓龙 和 张佳宁 的 舅舅
[('张晓龙', 'UNCLE', '张佳宁'), ('和', 'dep', '张晓龙'), ('张佳宁', 'ROOT', '张佳宁'), ('舅舅', 'dep', '张佳宁')]

可以看到效果还是可以的,只有第一条没有匹配成功。



不足的地方

本文模型用的是英文模型,可以看到本文将中文句子事先用空格隔开,以到达成功训练,后续待改进。



参考

1、【法】巴格夫·斯里尼瓦萨-德西坎.《自然语言处理与计算语言学》.人民邮电出版社

2、https://zhuanlan.zhihu.com/p/51186364

3、https://blog.csdn.net/sinat_33741547/article/details/79258045

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值