• 文本自动分类(续)


    文本自动分类

    关于单个文本处理时间显著增长的讨论


    今天下午  

    使用了 stopwords 从网上搜了下 中文停用词

    并解决了 Python 中文显示/输入输出的问题 line.decode('gbk')


    __author__ = 'LiFeiteng'
    # -*- coding: utf-8 -*-
    import os
    import  jieba
    import nltk
    
    ## 由搜狗语料库 生成数据
    folder_path = 'C:LIFEITENGSogouC.reduced\Reduced'
    #folder_path = 'C:LIFEITENGSogouC.miniSample'
    folder_list = os.listdir(folder_path)
    class_list = [] ##由于乱码等问题 仅以数字[0,1,...]来代表文件分类
    nClass = 0
    N = 100  #每类文件 最多取 50 个样本 70%train 30%test
    train_set = []
    test_set = []
    all_words = {}
    import time
    process_times = [] ## 统计处理每个文件的时间
    for i in range(len(folder_list)):
    	new_folder_path = folder_path + '\' + folder_list[i]
    	files = os.listdir(new_folder_path)
    	class_list.append(nClass)
    	nClass += 1
    	j = 0
    	nFile = min([len(files), N])
    	for file in files:
    		if j > N:
    			break
    		starttime = time.clock()
    
    		fobj = open(new_folder_path+'\'+file, 'r')
    		raw = fobj.read()
    		word_cut = jieba.cut(raw, cut_all=False)
    		word_list = list(word_cut)
    		for word in word_list:
    			if all_words.has_key(word):#if word in all_words.keys():
    				all_words[word] += 1
    			else:
    				all_words[word] = 0
    		if j > 0.3 * nFile:
    			train_set.append((word_list, class_list[i]))
    		else:
    			test_set.append((word_list, class_list[i]))
    		fobj.close()
    		j += 1
    		endtime = time.clock()
    		process_times.append(endtime-starttime)
    
    		print "Folder ",i,"-file-",j, "all_words length = ", len(all_words.keys()),
    			"process time:",(endtime-starttime)
    
    
    ## 根据word的词频排序
    all_words_list = sorted(all_words.items(), key=lambda e:e[1], reverse=True)
    
    ## 由于乱码的问题,没有正确使用 stopwords;简单去掉 前100个高频项
    ## word_features 是选用的 word-词典
    stopwords_file = open('stopwords_cn.txt', 'r')
    stopwords_list = []
    for line in stopwords_file.readlines():
    	#print line.decode('gbk')
    	stopwords_list.append(line.decode('gbk')[:-2])
    #print stopwords_list
    
    def words_dict_no_use_stopwords(deleteN):
    	#dict_name = "dict_"+str(deleteN)+".txt"
    	#dict = open(dict_name, 'w')
    	n = 0
    	word_features = []
    	for t in range(deleteN, len(all_words), 1):
    			if n > 1000:
    						break
    			#print all_words_list[t][0]
    			#dict.writelines(str(all_words_list[t][0]))
    			#dict.writelines(' ')
    			n += 1
    			word_features.append(all_words_list[t][0])
    	return word_features
    	#dict.close()
    
    def words_dict_use_stopwords(deleteN):
    	#dict_name = "dict_stopwords_"+str(deleteN)+".txt"
    	#dict = open(dict_name, 'w')
    	n = 0
    	word_features = []
    	for t in range(deleteN, len(all_words), 1):
    			if n > 1000:
    						break
    			#print all_words_list[t][0]
    			if all_words_list[t][0] not in stopwords_list and (not all_words_list[t][0].isdigit()):
    				#dict.writelines(str(all_words_list[t][0]))
    				#dict.writelines(' ')
    				n += 1
    				word_features.append(all_words_list[t][0])
    	return word_features
    	#dict.close()
    
    def document_features(document):
    	document_words = set(document)
    	features = {}
    	for word in word_features: ## 根据词典生成 每个document的feature True or False
    		features['contains(%s)' % word] = (word in document_words)
    	return features
    
    def TextClassification():
    	## 根据每个document 分词生成的 word_list 生成 feature
    	train_data = [(document_features(d), c) for (d,c) in train_set]
    	test_data = [(document_features(d), c) for (d,c) in test_set]
    	print "train number:",len(train_data),"
     test number:",len(test_data)
    	## 朴素贝叶斯分类器
    	classifier = nltk.NaiveBayesClassifier.train(train_data)
    	test_error = nltk.classify.accuracy(classifier, test_data)
    	print "test accuracy:", test_error
    	return test_error
    
    deleteNs = range(0, 1000, 20)
    test_errors_no_use = []
    test_errors_use = []
    for n in deleteNs:
    	word_features = words_dict_no_use_stopwords(n)
    	test_error = TextClassification()
    	test_errors_no_use.append(test_error)
    
    	word_features = words_dict_use_stopwords(n)
    	test_error = TextClassification()
    	test_errors_use.append(test_error)
    
    
    ## 处理每个文件所用的时间 可见到后面 处理单个文件的时间显著增长
    ## 原因 已查明
    import pylab
    plot1 = pylab.plot(deleteNs, test_errors_no_use)
    plot2 = pylab.plot(deleteNs, test_errors_use)
    pylab.legend(('no use stopwords', 'using stopwords'), 'best')
    #pylab.xlabel("no using stopwords")
    pylab.show()



    对数据的处理:

    由于没有事先的词典dict  

    我的处理方法是:把所有文档的分词结果放到一个 dictionary里面,然后根据词频从高到低 排序

    由于处理每个文档的时候,就没有去除一些杂乱信息,比如标点符号,无意义的数字等

    所以 在试验中 构造最终词典(固定选取1000个词)的时候 逐渐去除词典的部分高频项,观察正确率的变化


    (图像:纵轴代表分类9个文档的正确率,横轴-去除高频项的个数(0::20::1000),绿线-使用停用词的正确率)


    从测试准确率图像中可以看到此举 在初期还是有显著效果的 当去除更多高频词汇的数据时 正确率又会显著下降

    这跟理论分析是符合的——应该观察排序后的字典,深入到数据中去

    同时也可看到 使用停用词 在前半段 争取率有不错的提升

    ==========================================================


    1.应该在 处理每个文本的时候  应该去除一些杂乱信息 减少内存占用等

    2.如果在事先有 词典的情况下 可以直接提取文本特征

    3.没有词典的时候, 程序员应该自己 构造词典 甚至在大量样本中 学习词典

    4.特征维数的选取 在本文中固定 1000 维,可以做做 正确率关于维数的变化

    5.特别说明:因为 分类器用的是 朴素贝叶斯 所以文本特征是 [TRUE, FALSE, ...]  文本是否包含字典中词的判别

      p(feature_i | C_k) = ... 见文本自动分类 贝叶斯介绍部分

       如果是使用 SVM softmax等 那么特征应该是 词频 或者 TDIDF等




  • 相关阅读:
    软件的竞争力:性能 CQ
    2010.7.11 OA项目组一周工作报告 CQ
    2010.8.22 OA项目组一周工作报告 CQ
    2010.7.18 OA 项目组一周工作报告 CQ
    我的音乐 CQ
    2010.7.25 OA项目组一周工作报告 CQ
    JavaScript中的关于this
    递归函数的应用
    es6中的对象的可计算的属性名
    undefined 和 undeclared 的区别
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3360948.html
Copyright © 2020-2023  润新知