今天是大年三十儿,祝各位简友新春快乐,心想事成,万事如意!今天也继续来学一波nlp技术。
图片发自简书App
HMM 和 CRF
常被用于分词、句法分析、命名实体识别、词性标注等
HMM是一个生成模型
使用隐含变量生成可观测状态
生成式模型
估计的是联合概率分布
由联合概率密度分布求出条件概率分布
生成模型公式为:P(Y|X)= P(X,Y)/ P(X)
关心的是给定输入 X 产生输出 Y 的生成关系P(Y|X)
其他常见的生成式模型有:Gaussian、 Naive Bayes、Mixtures of multinomials 等
CRF是一个判别模型
判别式模型
估计的是条件概率分布, P(Y|X)
由数据直接学习条件概率分布 P(Y|X)
关心的是对于给定的输入 X,应该预测什么样的输出 Y
其他常见的判别式模型有:K 近邻法、感知机、决策树、逻辑斯谛回归模型、最大熵模型、支持向量机、提升方法等。
HMM 的“五元组”
StatusSet:状态值集合
在分词任务中状态值集合为 (B, M, E, S),每个状态代表的是该字在词语中的位置,其中 B 为词的首个字,M 为词中间的字,E 为词语中最后一个字,S 为单个字
ObservedSet:观察值集合
即所有语料的汉字,包括标点符号
TransProbMatrix:转移概率矩阵
就是从状态 X 转移到状态 Y 的概率,是一个4×4的矩阵,即 {B,E,M,S}×{B,E,M,S}
EmitProbMatrix:发射概率矩阵
矩阵的每个元素都是一个条件概率,代表 P(Observed[i]|Status[j]) 概率
InitStatus:初始状态分布
表示句子的第一个字属于 {B,E,M,S} 这四种状态的概率。
基于 HMM 的中文分词器
在分词上,要做的是:已知 参数(ObservedSet、TransProbMatrix、EmitRobMatrix、InitStatus),求解状态值序列
解决这个问题的最有名的方法是 Viterbi 算法
一般流程为:
语料准备
爬取文本,用空格隔开
定义 HMM 中的状态,初始化概率,以及中文停顿词
将 HMM 模型封装为独立的类 HMM_Model
class HMM_Model:
def __init__(self):
pass
#初始化
def setup(self):
pass
#模型保存
def save(self, filename, code):
pass
#模型加载
def load(self, filename, code):
pass
#模型训练
def do_train(self, observes, states):
pass
#HMM计算
def get_prob(self):
pass
#模型预测
def do_predict(self, sequence):
pass
__init__()
定义了数据结构和初始变量
setup()
初始化第一个方法中的数据结构
save()
用来保存训练好的模型
load()
用来加载模型
do_train()
用来训练模型
训练函数输入观测序列和状态序列进行训练, 依次更新各矩阵数据
get_prob()
在进行预测前,需将数据结构的频数转换为频率
do_predict()
预测采用 Viterbi 算法求得最优路径
get_tags函数
对输入的训练语料中的每个词进行标注
cut_sent函数
根据预测得到的标注序列将输入的句子分割为词语列表
定义分词器类 HMMSoyoger
class HMMSoyoger(HMM_Model):
def __init__(self, *args, **kwargs):
pass
#加载训练数据
def read_txt(self, filename):
pass
#模型训练函数
def train(self):
pass
#模型分词预测
def lcut(self, sentence):
pass
继承 HMM_Model 类并实现中文分词器训练、分词功能
init(),构造函数,定义了初始化变量
read_txt(),加载训练语料,读入文件为 txt,并且 UTF-8 编码,防止中文出现乱码
train(),根据单词生成观测序列和状态序列,并通过父类的 do_train() 方法进行训练
lcut(),模型训练好之后,通过该方法进行分词测试
训练模型
首先实例化 HMMSoyoger 类,然后通过 read_txt() 方法加载语料,再通过 train() 进行在线训练
模型测试
学习资料:
《中文自然语言处理入门实战》