挑战实现P、R、F(精准率、召回率和调和数)的python程序


——————————————


王老师就留了课后作业,让算一下训练出来结果的P(精准率)、R(召回率)、F(调和数),以展示我们所应用CRF机器学习的显著效果。

1.模板

首先模板是最简单的模板,没有加入什么特征。所以训练出来能达到70%我就很满意了。

模板如下:

# Unigram 
U01:%x[-2,0]
U02:%x[-1,0]
U03:%x[0,0]
U04:%x[1,0]
U05:%x[2,0]
U06:%x[-2,0]/%x[-1,0]
U07:%x[-1,0]/%x[0,0]
U08:%x[0,0]/%x[1,0]
U09:%x[1,0]/%x[2,0]
# Bigram
B



确实没什么。。

2.语料

我们全班标注了数据科学相关招聘信息中的需求实体词,如:“本科”、“硕士及以上”、“Java”、“Python”、“团队协作”……等等(一句话中你看什么是需求就取出来这种)

收齐全班四十多人的结果,最后转化一下成为BEMS的格式。

大	B
专	M
及	M
以	M
上	E
学	S
历	S
,	S
要	S
有	S
一	S
定	S
的	S
逻	B
辑	M
思	M
维	E
,	S
热	S
爱	S
互	B
联	M
网	E
工	S
作	S
。	S




3.训练并开放测试获得最终结果

CRF封装的真是很好,跑完就得到了如下的结果(部分)。第一、二列同上,第三列为机器学习后的结果。

大	B	B
专	M	M
及	M	S
以	M	S
上	E	S
学	S	S
历	S	S
,	S	S
要	S	S
有	S	S
一	S	S
定	S	S
的	S	S
逻	B	B
辑	M	M
思	M	M
维	E	E
,	S	S
热	S	S
爱	S	S
互	B	B
联	M	M
网	E	E
工	S	S
作	S	S
。	S	S


4.P、R、F是什么?怎么算?

下面是今天的主要挑战部分,如何根据我们的结果来计算P、R、F值呢

第一,我们要知道这里的的P、R、F是什么?这里极力推荐这篇博客(点击连接)。


P(查准率or准确率):分母是第二列机器识别出来的个数,分子是第二列识别出来中正确的个数。精确率和自己比较。

R(查全率or召回率):分母是第一列中识别出来的个数,分子是第二列识别出来中正确的个数。召回率和标准答案比较。

F(调和平均数):综合P、R的共同指标。


第二,回到我们的第三节的例子中,怎么样算是识别出来了呢?

1)情况一:

工	S	S
作	S	S

像这种S S对应的算是识别出来的。因为答案是“错”,机器说的也是“错”,那么机器不就作对了么。

2)情况二:

逻	B	B
辑	M	M
思	M	M
维	E	E

像这种标签一一对应的,也是机器答对了的情况。

那么,除了上面两种情况,其他不算识别出来。


最后,我们就可以进行算法转化成程序了。要做的很简单,

1.分别记录第一列、第二列所识别出来的个数。

2.识别一、二两种情况的个数。

3.计算。

(下面附上没有算法只有暴力匹配的Python代码)

# coding=utf-8
# author:Zzh-748
# 程序功能:计算有两列对照的结果文件的P、R、F值。

def count_right_term(list1,list2): # 核心
	flag=False
	c_r_term=0 # 记录正确数
	for i in range(len(list1)):
		tags=list1[i]+list2[i]
		# print(tags,end='  ')
		if flag==False:
			if tags=='SS': # 识别第一种情况
				c_r_term+=1
				# print('------------ss')
			elif tags=='BB':
				flag=True # 开始判断是否为识别出第二种情况
				# print()
			else:
				# print()
				pass
		else:
			if ((tags)!='MM' and (tags)!='EE') and 'E' not in tags:
				flag=False # 识别错误,退出识别
				# print()
			elif (tags)=='EE':
				flag=False # 识别结束,退出识别
				# print("------------BMES")
				c_r_term+=1
			else:
				     # print()
				pass # go on...
	return c_r_term


def count_B_and_S(list_n): # 此处以B和S的总数作为识别出的个数
	count=0
	for term in list_n:
		if term=='S' or term=='B':
			count+=1
	return count

def Cal_PRF(lines):
	list1=[]
	list2=[]

	for line in lines:
		if line!='\n':
			list1.append(line.split('\t')[1]) # 记录第一列
			list2.append(line.split('\t')[2].replace('\n','')) # 记录第二列
	print('list1 and list2 --- Loaded..')
	li_count1=count_B_and_S(list1) # R 的分母
	li_count2=count_B_and_S(list2) # P 的分母
	# print(li_count1,li_count2)
	right_term=count_right_term(list1,list2) # 分子
	# P、R、F计算核心
	P=right_term/li_count2
	R=right_term/li_count1
	F=2*P*R/(P+R)
	return {'P':P,'R':R,'F':F} #返回字典格式的PRF值

def main():
	with open("result.txt","r",encoding='utf-8') as fr:
		lines=fr.readlines()
	result=Cal_PRF(lines)
	print('P:',result['P'],'\nR:',result['R'],'\nF:',result['F'])

if __name__=="__main__":
	main()


main()中打开的“result.txt”为需要计算PRF的文本。


结果:更多的特征

list1 and list2 --- Loaded..
P: 0.8 
R: 0.9411764705882353 
F: 0.8648648648648648


至此,PRF值的计算过程就算告一段落了。接下来的工作是对模版进行优化,加入新的特征等等。



你可能感兴趣的:(Python探索笔记)