星标/置顶小屋,带你解锁
最萌最前沿的NLP、搜索与推荐技术
文 | 匿名大佬
编 | 北大小才女小轶
本文将为大家介绍如何使用百度开源的词法分析工具LAC实现个性化分词(附代码),并展示LAC在各数据集上惊艳的性能表现。
背景介绍
分词是中文自然语言处理基础且重要的任务。词是表意的完整单位。“张三”这个词中,“张”其实既可以是姓也可以表“张开”之意,而“三”则常被表示为数字。但“张三”作为一个词出现在一起时,大家明确知道这表示的是个人名,故而句子经过分词后可降低理解的难度。
分词也是文本检索、知识图谱等自然语言处理应用的重要基础。这些下游任务的效果很大程度受限于分词的准确率。在问答对话、信息抽取、机器翻译等任务也常用采用分词后的结果作为模型输入。在深度学习模型中,分词除了能降低学习难度外,还可以缩短输入序列长度,从而降低模型运算量。
在分词任务中,最主要的挑战包括以下三点:
没有统一的分词标准:因为“词”的本身并没有一个非常明确的界定,比如“夕小瑶”可以看做是一个名字组成的词,“夕”和“小瑶”分别以姓和名作为一个词也是有意义的。
持续增加的未登录词:未登录词(Out of Vocabulary,OOV),也叫生词,主要指未在词典或训练语料中出现过的词,这是目前导致分词错误最主要的原因,并且每年都会有一些新的概念词或网络用语出现,如“c位”、“打call”、“新冠”等。
歧义切分:一方面,同一个词可能存在多个语义,在不同语义下需要进行不同的切分,比如“努力/才/能/成功”、“发挥/才能”中的“才能”;另一方面,不同的切分结果可能导致完全不一样的语义,如”无线电法/国别/研究“、“无线电/法国/别/研究”;这个时候,往往都需要理解上下文的语义才能得到一个合理的切分结果。
对于分词标准问题,总是众口难调的,因为分词标准上存在人的主观性,而且其实对于不同的应用,所需要的分词粒度也是不同的。比如检索相关的应用往往偏向于更细粒度的分词,甚至同时使用多种粒度的分词构建索引,如果我们仅仅采用粗粒度的分词,比如以“夕小瑶”进行搜索,就会难以匹配到包含“小瑶”的结果。而在实体抽取时,知识图谱等领域则会更加偏向于粗粒度的分词结果,比如“夕小瑶”才是一个完整的人名,对应于一个实体,而“夕”或“小瑶”则不是。而在医疗、音乐、法律等不同应用领域,所采用的分词标准往往也是有所差异的。这个时候我们就需要打造一个属于自己的个性化分词工具。
此前,在领域个性化分词方面,比较出名的工具当属北大分词工具pkuseg。而近期,百度开源的词法分析工具LAC刚刚进行了一次比较大的升级,大大提升了其易用性,并提供了增量训练的接口。在使用这个增量训练的接口进行简单测试发现,LAC在个性化分词训练的效果惊艳,在测试的多个数据集中上的表现明显优于pkuseg。
个性化分词的实现
数据集
我们搜刮了一些不同领域的分词数据集,用于对个性化分词的效果进行测试,数据集整理如下:
PKU:新闻数据 (http://sighan.cs.uchicago.edu/bakeoff2005/)
MSR:新闻数据 (http://sighan.cs.uchicago.edu/bakeoff2005/)
CityU:繁体字新闻数 (http://sighan.cs.uchicago.edu/bakeoff2005/)
weibo:微博文本数据 (https://github.com/FudanNLP/NLPCC-WordSeg-Weibo)
law:法律文书数据 (https://github.com/FanhuaandLuomu/BiLstm_CNN_CRF_CWS)
medical: 医疗论坛数据 (https://github.com/adapt-sjtu/AMTTL/tree/538258cdcc58dc66761e87db690658da5c0f498f)
HKCanCor:粤语对话数据 (http://compling.hss.ntu.edu.sg/hkcancor/)
CTB8:新闻、广播、微博及网页等综合数据 (https://catalog.ldc.upenn.edu/LDC2013T21)
我们整理了以上数据,对部分需要进行格式转换的数据进行了预处理,已将预处理脚本上传到云盘。
在订阅号「夕小瑶的卖萌屋」后台回复关键词【0720】,即可下载各领域分词数据集的预处理脚本。
分词模型的安装与训练
pkuseg安装:
pip install pkuseg
LAC安装:
pip install lac
pkuseg和LAC的训练代码都非常简洁,安装并准备好训练数据后,只需运行以下几行代码即可完成模型训练:
train_file = 'train.txt' # 训练数据
test_file = 'test.txt' # 测试数据# LAC 训练
from LAC import LAC
lac = LAC(mode='seg')
lac.train('my_lac_model', train_file)
lac = LAC('my_lac_model') # 装载新模型# pkuseg训练
import pkuseg
pkuseg.train(train_file, test_file, 'my_pku_model')
pkusegger = pkuseg.pkuseg('my_pkumodel') # 装载新模型
实验
评估指标
训练好模型后,就需要对模型进行评估了。在这里我们使用SIGHAN 2005的评估标准:以词为粒度,统计其准确率和召回率的。以“夕小瑶的卖萌屋”的分词结果为例,如果模型对于“卖萌屋”这一个单词进行了分割,预测错误。其准确率,召回率和F1值的计算结果如下所示:
测试结果
下表列出了LAC、pkuseg、thulac在各数据集上的测试结果。可以看到,LAC在大多数的数据集的效果要显著优于pkuseg,以及thulac。除了HKCanCor数据集外,LAC的F1值大约要比pkuseg高2-3个百分点。因为HKCanCor是粤语方面的数据,LAC原本模型的训练语料中应该没什么粤语数据,所以这个效果优势不是很明显似乎也能理解。
(可左右滑动查看完整表格)
数据集 | 数据量(字) | LAC | pkuseg 增量 | pkuseg | thulac |
---|---|---|---|---|---|
CTB8 | 232W | 95.7(96.0/95.3) | 93.7(95.4/92.0) | 92.9(94.7/91.1) | 91.4(90.4/92.4) |
MSR | 405W | 97.3(97.2/97.3) | 95.2(96.3/94.1) | 94.9(95.9/93.9) | 93.0(92.1/93.8) |
PKU | 182W | 95.8(96.2/95.4) | 94.0(95.5/92.6) | 93.6(95.1/92.2) | 92.0(91.9/92.0) |
107W | 95.2(94.7/95.6) | 93.1(93.7/92.4) | 92.7(93.4/91.9) | 89.7(88.4/91.0) | |
CityU | 240W | 96.1(95.9/96.3) | 93.6(94.2/93.0) | 92.8(93.6/92.1) | 92.7(92.1/93.3) |
law | 9.83W | 97.7(97.9/97.6) | 96.5(95.8/93.7) | 95.8(96.5/95.2) | 94.5(95.0/94.1) |
medical | 9.37W | 86.9(86.4/87.5) | 84.1(85.2/83.1) | 83.7(84.6/82.8) | 80.5(78.5/82.6) |
HKCanCor | 17.6W | 96.7(96.5/96.8) | 96.6(96.5/96.6) | 96.3(96.4/96.3) | 93.8(93.2/94.5) |
注:pkuseg 增量训练的参数初始化均使用pkuseg提供的default模型
事实上,LAC直接采用默认参数、未经调参操作得出的结果,都已经接近近年顶会论文中呈现的结果。以下是一篇ACL2020论文(Improving Chinese Word Segmentation with Wordhood Memory Networks)所罗列的近几年分词测试结果。其中,近两年的模型大多都是基于BERT等大规模预训练模型,非常需要的算力,相信会让不少读者望而却步。
而在医疗垂类的测试结果中,LAC的结果也是要远优于COLING2018提出的AMTTL模型的,所以可以看出LAC的结果还是比较惊艳的。
完整的模型评估和训练代码
如下所示,为了方便读者自行体验感受其效果,我们提供得到上述结果的完整测试代码。各位可下载相应数据集后直接运行以下脚本:
# 评估函数
def seg_eval(gold_file, predict_file):def convert2set(word_list):offset = 0res = []for word in word_list:res.append((offset, offset + len(word), word))offset += len(word)return set(res)gold_num = 0.0predict_num = 0.0correct_num = 0.0golds = open(gold_file, 'r', encoding='utf8')predicts = open(predict_file, 'r', encoding='utf8')for gold, predict in zip(golds, predicts):words_gold = gold.strip().split()words_predict = predict.strip().split()gold_num += len(words_gold)predict_num += len(words_predict)correct_num += len(convert2set(words_gold) &convert2set(words_predict))P = correct_num / predict_numR = correct_num / gold_numF1 = 2 * P * R / (P + R)return P, R, F1datanames = ['lac', 'medical', 'pku', 'msr', 'ctb8', 'weibo', 'cityu', 'hkcantcor']# 训练代码
from LAC import LAC
import pkusegfor dataname in datanames:train_file = 'cws_data/%s_train.txt'%datanametest_file = 'cws_data/%s_test.txt'%datanamelac_predict_file = '%s_lacout.txt'%datanamepku_predict_file = '%s_pkuout.txt'%dataname# lac 训练并装载新模型lac = LAC(mode='seg')lac.train(dataname + '_lacmodel', train_file)lac = LAC(dataname + '_lacmodel', mode='seg')# pku 训练并装载新模型pkuseg.train(train_file, test_file, dataname + '_pkumodel')pkusegger = pkuseg.pkuseg(dataname + '_pkumodel')# 执行评估with open(test_file, 'r', encoding='utf8') as fi:with open(lac_predict_file, 'w', encoding='utf8') as lacfo:with open(pku_predict_file, 'w', encoding='utf8') as pkufo:for line in fi:words = line.strip().split()# 执行并保存lac模型结果words_lac = lac.run("".join(words))print(" ".join(words_lac), file=lacfo)# 执行并保存pku模型结果words_pku = pkusegger.cut("".join(words))print(" ".join(words_pku), file=pkufo)print('lac', dataname, seg_eval(test_file, lac_predict_file))print('pku', dataname, seg_eval(test_file, pku_predict_file))
LAC个性化增量训练后的效果
以下展示了LAC在各自不同领域数据上训练前后的一些case。不难发现,LAC默认模型其实在法律、医疗、新闻等相关领域的分词效果其实都已经比较好了。通过增量训练,主要调整了模型的分词粒度(目测LAC默认模型的分词粒度都比较粗)。而对于粤语数据,LAC默认模型的效果表现比较差。通过训练后效果后明显提升。这可能是LAC原有模型的训练语料没什么粤语语料的原因。
粤语数据
LAC:
我 哋 而 家 返 屋企 睇 電視 囉 !
LAC-HKCanCor:
我哋 而家 返 屋企 睇 電視 囉 !
普通话:
我们现在回家看电视了!
LAC:
琴日嘅嗰啲 問題 真 係 唔知 點解
LAC-HKCanCor:
琴日 嘅 嗰啲 問題 真係 唔 知 點解
普通话:
昨天的那些问题真的不知道为什么
法律数据
LAC:
据此 , 依照 《 中华人民共和国合同法 》 第一百零七条 、 第一百九十六条 、 第二百条 、 第二百零五条 、 第二百零六条 、 第二百零七条 、 第二百一十一条 第二款
LAC-law:
据 此 , 依照 《 中华 人民 共和国 合同法 》 第一百零七 条 、 第一百九十六 条 、 第二百 条 、 第二百零五 条 、 第二百零六 条 、 第二百零七 条 、 第二百一十一 条 第二 款
LAC:
以上 事实 , 有 《 借款协议 》 、 《 收款确认书 》 、 工商银行 账户 历史 明细 清单 、 《 委托代理合同 》 、 律师 收费 发票 及 当事人 陈述 记录 在案 为证 。
LAC-lac:
以上 事实 , 有 《 借款 协议 》 、 《 收款 确认书 》 、 工商 银行 账户 历史 明细 清单 、 《 委托 代理 合同 》 、 律师 收费 发票 及 当事人 陈述 记录 在案 为 证 。
医疗数据
LAC:
慢性支气管炎 冠状动脉 肺动脉瘘 , 心律失常 完全性 左束支 传导 阻滞 , 阻塞性肺气肿
LAC-medical:
慢性 支气管 炎 冠状 动脉 肺动脉 瘘 , 心律失常 完全性 左束支 传导 阻滞 , 阻塞性 肺气肿
新闻数据
LAC:
北京新年音乐会 展现 经典 魅力 尉健行 李岚清 与 数千 首都 观众 一起 欣赏
LAC-pku:
北京 新年 音乐会 展现 经典 魅力 尉 健行 李 岚清 与 数千 首都 观众 一起 欣赏
LAC:
2000年12月22日 下午 2 时 ( 北京 时间 23日 凌晨 2 时 ) , 我 作为 鹭江出版社 “ 2000 人文 学者 南极行 ” 活动 的 代表
LAC-pku:
2000年 12月 22日 下午 2时 ( 北京 时间 23日 凌晨 2时 ) , 我 作为 鹭江 出版社 “ 2000 人文 学者 南极 行 ” 活动 的 代表
卖萌屋成立了自然语言处理、搜索技术、推荐系统、算法岗求职等方向大群和知识图谱与信息抽取、智能问答、对话系统等垂类讨论群。不仅可以认识众多志同道合的优秀小伙伴,而且还有若干卖萌屋美丽小姐姐(划掉)、顶会审稿人、大厂研究员、知乎大V等你来撩哦。后台回复关键词【入群】即可获取入口。
记得扫描下方二维码关注并星标置顶,我才能来到你面前哦。
夕小瑶的卖萌屋
关注&星标小夕,带你解锁AI秘籍
订阅号主页下方「撩一下」有惊喜