目录
实验目的:
加深对汉语文本信息处理基础理论及方法的认识和了解,锻炼和提高分析问题、解决问题的能力。通过对具体项目的任务分析、数据准备、算法设计和编码实现以及测试评价几个环节的练习,基本掌握实现一个自然语言处理系统的基本过程。
实验要求:
1.基于文档频率的特征选择方法
2.基于互信息/信息增益的特征选择方法
实验内容及原理:
该子任务利用特征选择算法从给定带有类别标签的句子集中抽取具有最具代表性的N个词作为特征集。
要求分别实现:基于文档频率DF的特征选择方法,以及基于互信息、信息增益两种方法中的任意一种,推荐使用信息增益方法。
主要流程如下:
1)从给定的语料集中提取出带有类别标签的句子并进行预处理(分词、去除停用词),构建候选特征词集S。
2)对候选特征词集S中的所有词汇w,计算其特征得分s(w),计算方法分别使用文档频率、互信息、信息增益三种方法实现。三种方法的计算公式如下所示:
文档频率:通过计算特征词条t在各文档中出现的文档频率来完成提取。对所有词条计算其出现的文档频数,从大到小进行排序,取前K~K+N个词语作为文本特征集合。
互信息:通过计算特征词条t和类别c之间的相关性来完成提取。
如果用A表示包含特征词条t且属于类别c的文档频数,B为包含t但是不属于c的文档频数,C表示属于c但不包含t的文档频数,N表示语料中文档的总数,可构建如图1所示的矩阵形式,t和c的互信息可由下式计算:
对多个类别的特征选择,可采用两种方式选择特征词,并体会其结果差异:
a)计算各个类别下的互信息的平均值作为该词条的互信息值,计算公式为:
b)对每个类别按照特征词与类别的共现概率计算期望值,计算公式为:
信息增益:对于特征词条t和文档类别c,IG考察c中出现和不出现t的文档频数来衡量t对于c的信息增益,定义如下:
其中P(c)表示ci类文档在语料中出现的概率,Pt表示语料中包含特征词条t的文档的概率,P(c, l 八)表示文档包含特征词条t时属于ci类的条件概率,P()表示语料中不包含特征词条t的文档的概率,P(c, l)表示文档不包含特征词条t时属于ci类的条件概率,m表示文档类别数。
如果选择一个特征后,信息增益最大(信息不确定性减少的程度最大),那么我们就选取这个特征。
3)依据候选特征词集S中词汇w的特征得分s(w)进行排序,选择得分最大的前N=1000个词作为文本的表示特征集。存储到文件当中。
存储格式:一行为一个特征词,以utf-8进行编码。
实验数据采用htl_del_4000宾馆情感分析数据进行处理,所有数据已按照情感极性划分为褒(pos)贬(neg)两类,各2000篇,每个文本文件为一篇文章,实验数据需要先进行分词,分词方法不限。
统计频数时按照篇章级共现进行计算。
停用词表采用中文通用停用词表,文件名为
“cn stopwords.txt”,可用于数据预处理中的去除停用词。
参考代码:
#任务1
import jieba
import os
dictionary = {}
dic={}
def fun(d):
if d!={}:
pass
class DF:
def __init__(self):
self.files = {}
self.stop_words = set(())
fun(dic)
content = open('cn_stopwords.txt', 'r',encoding='utf-8').read()
for sl in content.splitlines():
self.stop_words.add(sl)
def add_file(self, file_name):
# Load data and cut #加载
if(os.path.exists('./中文信息处理技术实验数据/htl_del_4000/'+ file_name)):
content = open(file_name, 'rb').read() if file_name[0] == '/' or file_name[0] == 'C' else open('./中文信息处理技术实验数据/htl_del_4000/'+ file_name, 'rb').read()
words = jieba.cut(content)
else:
return
se = set()
for w in words:
if len(w.strip()) < 2 or w.lower() in self.stop_words: #如果词语长度小于2或者读到停止词
continue
se.add(w)
for i in se:
dic[i]=dic.get(i,0.0)+1.0
if __name__ == "__main__":
table = DF()
f1 = 'neg'
f2= 'pos'
# 当前文件的路径
dir = os.path.dirname(__file__)
#拼接文件路径
p1 = os.path.join(dir, './中文信息处理技术实验数据/htl_del_4000/' + f1)
p2=os.path.join(dir, './中文信息处理技术实验数据/htl_del_4000/', f2)
numf1 = len([name for name in os.listdir(p1) if os.path.isfile(os.path.join(p1, name))]) + 1
numf2 = len([name for name in os.listdir(p2) if os.path.isfile(os.path.join(p2, name))]) + 1
fun(dic)
#遍历所有文件
l1=os.listdir(p1)#返回当前文件夹的文件列表
l2=os.listdir(p2)#返回当前文件夹的文件列表
for x in l1:
fname= f1 + '/' + x
table.add_file(fname)
for x in l2:
fname = f2 + '/' + x
table.add_file(fname)
for i in dic:
dic[i]/=(len(l1) + len(l2))
list1=sorted(dic.items(),key=lambda s:s[1],reverse=True)#reverse=True从大到小排列
k = 2345
with open("5-1.txt", 'w+', encoding='utf-8') as f:
for i in range(k, k + 1000):
f.write(list1[i][0] + '\n')
print("任务1成功!数据保存在5-1.txt")
#任务2
import math
import jieba
import os
dictionary = {}
se_all=set() #存储所有的词汇
dic_n={} #
dic_p={}
class MI:
def __init__(self):
self.files = {}
self.stop_words = set(())
content = open('cn_stopwords.txt', 'r',encoding="utf-8").read()
for line in content.splitlines():
self.stop_words.add(line)
def add_file(self, file_name):
# Load data and cut #加载
if(os.path.exists('./中文信息处理技术实验数据/htl_del_4000/'+ file_name)):
content = open(file_name, 'rb').read() if file_name[0] == '/' or file_name[0] == 'C' else open('./中文信息处理技术实验数据/htl_del_4000/'+ file_name, 'rb').read()
words = jieba.cut(content)
else:
return
# Build dictionary
if file_name[0] == "n":#统计neg的词汇
se = set()
for w in words:
if len(w.strip()) < 2 or w.lower() in self.stop_words: #如果词语长度小于2或者读到停止词
continue
se.add(w)
se_all.add(w)
for i in se:
dic_n[i]=dic_n.get(i,0.0)+1.0
if file_name[0]=="p": #统计pos的词汇
se=set()
for w in words:
if len(w.strip()) < 2 or w.lower() in self.stop_words: #如果词语长度小于2或者读到停止词
continue
se.add(w)
se_all.add(w)
for i in se:
dic_p[i]=dic_p.get(i,0.0)+1.0
dic_p_A = {}
dic_p_B = {}
dic_p_C = {}
dic_n_A = {}
dic_n_B = {}
dic_n_C = {}
dic_mi = {}
MI_p = {}
if __name__ == "__main__":
dic_p_A = {}
dic_p_B = {}
dic_p_C = {}
dic_n_A = {}
dic_n_B = {}
dic_n_C = {}
dic_mi = {}
table = MI()
folder_name = 'neg'
folder_name_1='pos'
# 当前文件的绝对路径
dir = os.path.dirname(__file__)
#拼接文件路径
folder = os.path.join(dir, './中文信息处理技术实验数据/htl_del_4000/' + folder_name)
folder_1=os.path.join(dir,'./中文信息处理技术实验数据/htl_del_4000/',folder_name_1)
num_of_files = len([name for name in os.listdir(folder) if os.path.isfile(os.path.join(folder, name))]) + 1
num_of_files_1 = len([name for name in os.listdir(folder_1) if os.path.isfile(os.path.join(folder_1, name))]) + 1
#遍历所有文件
l1=os.listdir(folder) #返回当前文件夹的文件列表 #neg
l2=os.listdir(folder_1) #返回当前文件夹的文件列表 #pos
for x in l1: #neg的文件个数
file_name=folder_name+'/'+x
table.add_file(file_name)
for x in l2: #pos文件个数
file_name = folder_name_1 + '/' + x
table.add_file(file_name)
#计算pos的A B A+C
for i in se_all:
if i in dic_p:
#A
dic_p_A[i]=dic_p[i] #包含特征词条t和类别pos的文档频数
else:
dic_p_A[i]=1
if i in dic_n:
dic_p_B[i]=dic_n[i]
else:
dic_p_B[i]=1
#A+C
dic_p_C[i]= len(l2) - dic_p_A[i]
for i in se_all:
MI_p[i]=math.log10(dic_p_A[i] * (len(l2) + len(l1)) / (dic_p_C[i] + dic_p_A[i]) / (dic_p_A[i] + dic_p_B[i]))
list1 = sorted(MI_p, key=lambda d: d[1], reverse=True)
with open("5-2.txt", 'w+', encoding='utf-8') as f:
for i in range(0, 1000):
f.write(list1[i] + '\n')
print("任务2成功!数据保存在5-2.txt")
实验结果:
1. 基于文档频率的特征选择方法
2. 基于互信息的特征选择方法