赞
踩
词性标注(Part-Of-Speech tagging, POS tagging)也被称为语法标注(grammatical tagging)或词类消疑(word-category disambiguation),是语料库语言学(corpus linguistics)中将语料库内单词的词性按其含义和上下文内容进行标记的文本数据处理技术 。常见的词性标注算法包括隐马尔可夫模型(Hidden Markov Model, HMM)、条件随机场(Conditional random fields, CRFs)等 。
词性标注主要被应用于文本挖掘(text mining)和NLP领域,是各类基于文本的机器学习任务,例如语义分析(semantic analysis)和指代消解(coreference resolution)的预处理步骤。
维特比算法(Viterbi algorithm)是一种动态规划算法,它用于寻找最可能产生观测到的事件的序列,这个序列是隐含状态序列,也叫维特比路径(Viterbi path)。观测序列即为分词后的语句,隐藏序列即为经过标注后的词性标注序列。初始状态概率向量,观测矩阵和状态转移矩阵,可以通过大规模语料统计得到。观测序列到隐藏序列的计算通过viterbi算法,利用统计得到的初始状态概率向量pi 观测矩阵A和状态转移矩阵A来得到。得到隐藏序列后,就完成了词性标注过程。
下图为词典的一部分词语。每一行对应一个词语,分为三部分,分别为词语、分隔符以及词性。
tag2id , id2tag = {} , {} word2id , id2word = {} , {} for line in open('D:/nlp/gitlab资料/2.23[直播]Viterbi实战/课程内容/Lesson9-CaseStudy-Viterbi/traindata.txt'): items = line.split('/') word , tag = items[0], items[1].rstrip() # 提取每一行的单词和词性 if word not in word2id : word2id[word] = len(word2id) id2word[len(id2word)] = word if tag not in tag2id : tag2id[tag] = len(tag2id) id2tag[len(id2tag)] = tag M = len(word2id) # 词典中单词数 N = len(tag2id) # 词典中词性数 # 构造 pi ,A , B import numpy as np pi = np.zeros([N]) # 句子中第一个词性的概率 A = np.zeros([N,M]) # 每行为一种词性,每列为一个单词,A[i][j]表示在词性i下,出现单词j的概率 B = np.zeros([N,N]) # 行列均为词性,B[i][j]表示在词性i下,出现词性j的概率 pre_tag = '' for line in open('D:/nlp/gitlab资料/2.23[直播]Viterbi实战/课程内容/Lesson9-CaseStudy-Viterbi/traindata.txt'): items = line.split('/') wordId, tagId = word2id[items[0]], tag2id[items[1].rstrip()] if pre_tag == '' : # 此处意味着句子的开头 pi[tagId] +=1 A[tagId][wordId] +=1 # 统计在每个词性下,出现每个词的次数,用于后面转化为概率 else : # 若不是句子的开头 A[tagId][wordId] += 1 B[tag2id[pre_tag]][tagId] +=1 # 统计在前个词性下,出现其它词性(包括自身)的次数 if items[0] == '.' : pre_tag = '' else : pre_tag = items[1].rstrip() # 将上述统计值转化为概率值 pi = pi/sum(pi) for i in range(N): A[i] /= sum(A[i]) B[i] /= sum(B[i]) def log(v): if v == 0: return np.log(v+0.000001) return np.log(v) def viterbi(x,pi,A,B): """ :param x: 用户输入的句子 :param pi: 句子中第一个词性的概率 :param A: 给定词性下,每个单词出现的概率 :param B: 词性间的转移概率 """ x = [word2id[word] for word in x.split(' ')] # x=[1,5,3....],句子中每个词的ID T = len(x) dp = np.zeros((T,N)) # dp[i][j]:存放在第i个word下是第j个tag的概率 ptr = np.array([[0 for x in range(N)] for y in range(T)]) # T*N 或 ptr = np.zeros((T,N), dtype=int) for j in range(N): # basecase for DP算法 dp[0][j] = log(pi[j]) + log(A[j][x[0]]) for i in range(1,T): # 每个单词 for j in range(N): # 每个词性 # TODO:以下几行代码可以写成一行(vectorize的操作, 会使得效率变高) dp[i][j] = -9999999 for k in range(N): # 从每一个k到达j score = dp[i-1][k] + log(A[j][x[i]]) + log(B[k][j]) if score > dp[i][j] : dp[i][j] = score ptr[i][j] = k # 存放选择的前一个最佳词性的位置 # decoding: 打印最佳tag sequence best_seq = [0]*T # step1: 找出对应于最后一个单词的词性 best_seq[T-1] = np.argmax(dp[T-1]) # step2: 通过从后到前的循环来依次求出每个单词的词性 for i in range(T-2,-1,-1): best_seq[i] = ptr[i+1][best_seq[i+1]] # 到目前为止, best_seq存放了对应于x的词性序列 for i in range(len(best_seq)): print(id2tag[best_seq[i]]) x = "Social Security number , passport number and details about the services provided for the payment" viterbi(x,pi,A,B)
NNP
NNP
NN
,
NN
NN
CC
NNS
IN
DT
NNS
VBN
IN
DT
NN
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。