词性标注:基于MaxEnt的中文词性标注模型实现
一、前言
1、中文词性标注
2、最大熵模型
二、数据源
本文使用数据源未1998年的人民日报标注语料,手工进行处理,去除一些不符合标注规范(word/pos)的词语,词性标注见中文词性标注一文。
三、实战
1、特征提取
最大熵模型与一般机器学习算法不同之处在于特征是对x,y的联合分布提取,而不是只对x进行特征提取。
这是简单的设定几个模板:
前一个词与前词词性
当前词与当前词词性
后一个词与当前词词性
前一个词词性与当前词词性
当前词部首与当前词词性
这里模板数量还是偏少,还可以再增加关于字的模板或者扩大window范围等,详情可以参考后文贴出的论文。
基于上述的模板,与语料进行匹配,得到输入的特征。
cls.cal_pre_word_to_pos_feature()cls.cal_word_to_pos_feature()cls.cal_las_word_to_pos_feature()cls.cal_pre_pos_to_pos_feature()cls.cal_radical_to_pos_feature()
特征取值这里使用了每一个特征在语料中出现的概率,实验表明,这样的特征取值比单纯的二值方式效果要更好。
上述提到的特征并不能全部作为输入给到模型训练,需要进行筛选,这里简单的用特征出现的频率阈值作为筛选条件,一般选用5~20都可以。
@classmethod
def process_feature(cls, counter, counts, feature_dict_path, feature_path):"""特征筛选、特征值计算及保存 """limit = int(cls._config.get('postagger', 'feature_limit'))feature_dict = {k: {kk: vv/counter[k] for kk, vv in v.items() if vv > limit} for k, v in counts.items()}feature_dict = {k: v for k, v in feature_dict.items() if v}feature = cls.cal_feature_list(feature_dict)cls._feature.save_feature_to_file(feature_dict, feature_dict_path)cls._feature.save_feature_to_file(feature, feature_path)
提取出来的特征数量在十万左右,看起来很多,但实际上还是不够的。
2、语料处理
前面确定了输入的特征,接下来就是把原始语料转为特征的形式。这里采用tri-gram方式,将语料进行切分。
@classmethod
def segment_by_window(cls, words_list=None, window=3):"""窗口切分"""words, pos = [], []pre_words = cls._words if not words_list else words_listbegin, end = 0, windowfor _ in range(1, len(pre_words)):if end > len(pre_words): breakwords.append(pre_words[begin:end])if not words_list: pos.append(cls._pos[begin:end])begin = begin + 1 if words[-1] != u'<EOS>' else begin + windowend = end + 1 if words[-1] != u'<EOS>' else end + windowreturn words, pos
将切分后的语料按模板形式组合,与提取筛选后的特征进行比较,确定输入x的取值形式,构造生成器。
@classmethod
def feature_generator(cls):"""语料特征生成器 """words, pos = cls.segment_by_window()batch_size = int(cls._config.get('model', 'batch_size'))chunk_size = len(words)/batch_sizegenerator_list = [(i*batch_size) - 1 for i in range(chunk_size) if i]features = cls.load_feature()batch_x, batch_y = [], []for index in range(len(words)):x = cls.get_batch_x(words, pos, index, features)batch_x.append(x)batch_y.append(cls._states.index(pos[index][1]))if index in generator_list:print('{} Feature_size{}, Batch_size:{}, Chunk_count:{}, Now_chunk:{}'.format(datetime.now().strftime('%c'), len(x), batch_size, chunk_size, (index+1)/batch_size))yield np.array(batch_x), np.array(batch_y)batch_x, batch_y = [], []
3、模型搭建
最大熵模型实际上可以看成逻辑回归的一般化形式,或者是多项逻辑回归。前面将语料处理完成后,以一个batch的大小为256计算,大概存在百万级别的训练数据,这样的只能进行增量训练。
使用的sklearn的SGDClassifier就可以了,需要把损失函数设定为log,这样才是逻辑回归,如下:
loss : str, 'hinge', 'log', 'modified_huber', 'squared_hinge',\'perceptron', or a regression loss: 'squared_loss', 'huber',\'epsilon_insensitive', or 'squared_epsilon_insensitive'The loss function to be used. Defaults to 'hinge', which gives alinear SVM.The 'log' loss gives logistic regression, a probabilistic classifier.'modified_huber' is another smooth loss that brings tolerance tooutliers as well as probability estimates.'squared_hinge' is like hinge but is quadratically penalized.'perceptron' is the linear loss used by the perceptron algorithm.The other losses are designed for regression but can be useful inclassification as well; see SGDRegressor for a description.
模型训练过程中准确率验证码方面,不能使用简单的交叉验证,这里使用了两个准确率对比,简单解释一下,estimator每次只会拿下一个待训练batch在本次做评估,然后训练完之后,再在这个batch上做一次评估,看看是否有优化。
def train(self, epoch=None, show=None):"""模型训练"""self.initialize_model()g = self.corpus.feature_generator()batch_first_x, batch_first_y = next(g)self.model.partial_fit(batch_first_x, batch_first_y, classes=range(self.classes))train_score, progressive_validation_score = [], []epoch_count = 0for batch_x, batch_y in g:score = self.model.score(batch_x, batch_y)progressive_validation_score.append(score)print('{} Progressive_validation_score:{}'.format(datetime.now().strftime('%c'), score))self.model.partial_fit(batch_x, batch_y, classes=range(self.classes))score = self.model.score(batch_x, batch_y)train_score.append(score)print('{} Train_score:{}'.format(datetime.now().strftime('%c'), score))if epoch and epoch_count == epoch:breakelse: epoch_count += 1self.save_model()
4、模型效果
参数:
[model]
batch_size = 256
loss = log
alpha = 0.001
n_jobs = -1
准确率:
01/02/18 04:25:28 Feature_size63033, Batch_size:256, Chunk_count:9121, Now_chunk:9120
01/02/18 04:25:29 Progressive_validation_score:0.6015625
01/02/18 04:25:31 Train_score:0.6015625
可以看到,到训练完毕时,两个对比准确率趋于稳定,但是都不高,可以判断这里是欠拟合,和上面特征提取时的判断一致,特征数量还是相对较少,需要增加特征模板,将特征数量提升到百万级别。
5、实例
from postagger.api import *
predict = tagger(u'德国 大众 公司 是 欧洲 最 大 的 汽车 制造商 。')
origin = u'德国/ns 大众/nz 公司/n 是/v 欧洲/ns 最/d 大/a 的/u 汽车/n 制造商/n 。/w'
print u'Origin', origin
print u'Predict', predict
输出如下:
Origin 德国/ns 大众/nz 公司/n 是/v 欧洲/ns 最/d 大/a 的/u 汽车/n 制造商/n 。/w
Predict 德国/n 大众/n 公司/n 是/v 欧洲/n 最/d 大/a 的/u 汽车/n 制造商/v 。/w
三、参考
1、汉语词性标注的特征工程 于江德等
2、一种基于改进的最大熵模型的汉语词性自动标注的新方法 赵伟等
3、基于最大熵的哈萨克语词性标注模型 桑海岩等
词性标注:基于MaxEnt的中文词性标注模型实现相关推荐
- 基于HMM的中文词性标注 POSTagging
文章目录 1. 词性标注 1.1 概念 1.2 任务 1.3 预处理 1.4 初步统计预览 2. 最大概率模型 2.1 训练 2.2 预测 2.3 结果评估 2.4 结果可视化 3. 二元隐马尔科夫B ...
- 实战:基于tensorflow 的中文语音识别模型 | CSDN博文精选
作者 | Pelhans 来源 | CSDN博客 目前网上关于tensorflow 的中文语音识别实现较少,而且结构功能较为简单.而百度在PaddlePaddle上的 Deepspeech2 实现功能 ...
- 基于tensorflow 的中文语音识别模型
目前网上关于tensorflow 的中文语音识别实现较少,而且结构功能较为简单.而百度在PaddlePaddle上的 Deepspeech2 实现功能却很强大,因此就做了一次大自然的搬运工把框架转为t ...
- bilstm+crf中文分词_基于LSTM的中文分词模型
中文分词任务是一个预测序列的经典问题,已知的方法有基于HMM[1]的分词方法.基于CRF[2]的方法和基于LSTM的分词方法. 本文介绍Xinchi Chen等人[3]提出的基于LSTM的分词方法.根 ...
- LEBERT:基于词汇增强的中文NER模型
01 任务概述 命名实体识别(简称NER)是NLP中的经典任务,即给定一个输入文本,让模型识别出文本中的实体信息. 在中文NER任务中,可以分为 Character-based (字符粒度) 和 Wo ...
- 从字到词,大词典中文BERT模型的探索之旅
导语: BERT模型自诞生以来统治了各项NLP任务的榜单,谷歌也针对中文给出了基于字的模型.然而我们知道词是语言最重要的组成部分,因此,一个自然的想法就是做基于词的BERT模型.但是受限于显存,谷歌原 ...
- bert 中文 代码 谷歌_从字到词,大词典中文BERT模型的探索之旅
导语: BERT模型自诞生以来统治了各项NLP任务的榜单,谷歌也针对中文给出了基于字的模型.然而我们知道词是语言最重要的组成部分,因此,一个自然的想法就是做基于词的BERT模型.但是受限于显存,谷歌原 ...
- python英文语义角色标注_八款中文词性标注工具使用及在线测试
结束了中文分词工具的安装.使用及在线测试,开启中文词性标注在线测试之旅,一般来说,中文分词工具大多数都附带词性标注功能的,这里测试了之前在AINLP公众号上线的8款中文分词模块或者工具,发现它们都是支 ...
- 中文词性标注学习笔记(三)---词性标注
词性标注 词性标注(part-of-speech tagging),又称为词类标注或者简称标注,是指为分词结果中的每个单词标注一个正确的词性的程序,也即确定每个词是名词.动词.形容词或者其他词性的过程 ...
最新文章
- Android Studio的Gradle常用命令配置和依赖管理
- 梯度下降法和随机梯度下降法的区别
- sklearn:auc、roc_curve、roc_auc_score
- Google Gson 使用简介
- The value of a feed cannot be a tf.Tensor object.
- 查找数据库大小和表大小
- ffmpeg将视频流转化成图片帧,将图片帧转化为视频(基本无损)
- Android开发简易计算器
- 英语六级高频词汇速记 + 2018-6-2听力 Day02
- IEC 60664-1-2020【现行】低压供电系统内设备的绝缘配合第1部分:原则、要求和试验
- html怎么置顶图像,css怎么固定图片位置不变?
- 录音怎么转换成mp3格式?
- 2022全国职业技能大赛大数据技术与应用赛项赛题环境准备
- 百度指数使用小技巧(转)
- 网络营销和电子商务傻傻分不清?
- 超美二次元响应引导页源码
- 攻城掠地服务器维护到几点,攻城掠地玩法全解秘
- 黄大成:中国浙江的“盖茨神话”
- 流程图 选择结构 (一)
- 随便输入两个单词,两个单词之间以空格隔开,输出时每个单词的首字母变为大写。如输入:“hello java”,输出为“Hello Java”
热门文章
- pageadmin CMS网站制作教程:如何修改栏目类型
- 面试经验:腾讯微信事业群 - 微信总部机器学习岗面试
- BAT在互联网医疗的产业布局分析
- 如何保存卡住的wps_我告诉你wps卡住了怎么办
- CH57X/CH58X系列BLE Mesh无线组网方案
- Gym-101173K Key Knocking 思维+贪心
- android app文件夹,android app文件目录结构
- 「ZJOI2009」多米诺骨牌
- Voters in Appalachia Struggling to Identify With Presidential Candidates
- uni-app 和H5页面视频播放flv格式视频监控