中文词性标注

中文词性标注

最近我想练习一下中文词性标注,所以找了一个数据集,人民日报PKU数据集。


数据集

数据集来自北大计算语言所,对1998年1月《人民日报》中的句子进行词性标注,语料格式为:

19980101-01-001-001/m 迈向/v 充满/v 希望/n 的/u 新/a 世纪/n ——/w 一九九八年/t 新年/t 讲话/n (/w 附/v 图片/n 1/m 张/q )/w

这个数据集中总共19484个句子提供训练测试。我对语料集做了特殊处理,去掉了不规范的不含’/'的标注,使得标注更加规范。


工具脚本

由于数据集内并不附赠脚本,所以我自己实现了一个工具脚本tool.py

tool.py
'''
	tool.py
	This is a tool for scoring posTag algorithm.
	Just scoring an algorithm with:
		> driver(trainLines, testLines, trainFunction, posTagFunction):
	And this tool will print a report of accuracy.
	Note: There are 19484 sentences in data set 'data.txt'.
	
	Zhang Zhiyuan ,EECS Peking Univ. 2017/02/23
'''

class dataType:
	def __init__(self):
		self.__fd = open('data.txt', 'r')
		self.__total = 0
		self.__correct = 0
		
	def getTrainLine(self):
		while True:
			bufferLine = self.__fd.readline().strip()
			if len(bufferLine) > 0:
				return bufferLine
		
	def getTestLine(self):
		while True:
			self.__buffer = self.__fd.readline().strip()
			line = self.__buffer
			for word in line.split():
				line = line.replace(word, word.split('/')[0])
			if len(line) > 0:
				return line
	
	def testLine(self, line):
		lineList = line.split()
		bufferList = self.__buffer.split()
		l = len(lineList)
		for i in range(l):
			self.__total += 1
			if lineList[i].split('/')[1] == bufferList[i].split('/')[1]:
				self.__correct += 1
	
	def report(self):
		print('Accuracy = %.5f' % (self.__correct / self.__total))

def driver(trainLines, testLines, trainFunction, posTagFunction):
	totalLines = 19484
	if trainLines + testLines > totalLines:
		print('Too many lines!')
		return
	data = dataType()
	for i in range(trainLines):
		line = data.getTrainLine()
		trainFunction(line)
	for i in range(testLines)
		data.testLine(posTagFunction(data.getTestLine()))
	data.report()

脚本使用方法如注释所示,只需要调用函数driver()即可,下面举个例子来说明工具脚本使用方法

import tool

def train(line):
	line = line

def posTag(line):
	return('19980131-04-013-027/m  才/d  发觉/v  已/d  迷失/v  了/u  来路/n  。/w')
	
tool.driver(19483, 1, train, posTag)

请注意这个版本并不做实际计算,只是示意了训练函数和分词函数如何测试,而分词函数只是输来自数据集的答案,那么脚本会输出成绩:

Accuracy = 1.00000

如果修改训练句子数量为19484,那么因为用光了数据集,会输出:

Too many lines!

这些工具用面向对象风格实现,并封装在tool.py,以后测试不同算法只需要调用tool即可。如果有自然语言处理领域的爱好者学习者,可以自行下载数据集,并且把我的脚本拿去用使用。

朴素版本示例

最朴素的想法,对于一个词,给出最常见的标注方法。实现如下,做一个测试。

naive.py
import tool

dic = {}

def train(line):
	for wordTag in line.split():
		word, tag = wordTag.split('/')
		if word in dic:
			if tag in dic[word]:
				dic[word][tag] += 1
			else:
				dic[word][tag] = 1
		else:
			dic[word] = {tag: 1}
			
def posTag(line):
	lineList = line.split()
	l = len(lineList)
	for i in range(l):
		word = lineList[i]
		if word in dic:
			bestTag = ''
			bestTagFreq = 0
			for tag in dic[word]:
				if dic[word][tag] > bestTagFreq:
					bestTagFreq = dic[word][tag]
					bestTag = tag		
			lineList[i] = lineList[i] + '/' + bestTag
		else:
			lineList[i] = lineList[i] + '/' + 'unknow'
	return(' '.join(lineList))
		
tool.driver(10000, 5000, train, posTag)

测试结果也不错,说明汉语中大部分词词性是很固定的,所以统计表词性可以直接获得不低的成绩。

Accuracy = 0.86114

做好了准备工作,可以开始学习中文词性标注,实现其他脚本了~

你可能感兴趣的:(Machine,Learing)