ITPub博客

首页 > 大数据 > 数据挖掘 > 信息增益(IG)特征提取实例

信息增益(IG)特征提取实例

原创 数据挖掘 作者:破棉袄 时间:2016-01-28 15:58:49 2 删除 编辑


最近在做贝叶斯文本多分类,记录一下特征提取的过程:


如果你对TF、DF、IDF不懂:
Term Frequency:term 在文档d中的出现次数,记做tf。tf越高,意味着term 对于文档d 就越重要。
Document Frequency:含有term 的文档的数量,记做df。df越高,意味着term在衡量文档之间相似性方面作用越低,比如“的”的df值肯定非常高,因此不具有区别性,这类词称为“非焦点词”。
Inverse Document Frequency:跟df形成“反比关系”,IDF =log(N/df)值越高,意味着term对于文档的区别意义越大。N为全部文档的数量。如果term 仅出现在一个文档中,idf=logN,如果一个项目出现在所有文档中,idf= log1 = 0


为何要进行信息增益:(直接引用其他博文的原话)
TF-IDF可以有效评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。因为它综合表征了该词在文档中的重要程度和文档区分度。但在文本分类中单纯使用TF-IDF来判断一个特征是否有区分度是不够的。
1)它没有考虑特征词在类间的分布。也就是说该选择的特征应该在某类出现多,而其它类出现少,即考察各类的文档频率的差异。如果一个特征词,在各个类间分布比较均匀,这样的词对分类基本没有贡献;但是如果一个特征词比较集中的分布在某个类中,而在其它类中几乎不出现,这样的词却能够很好代表这个类的特征,而TF-IDF不能区分这两种情况。
2)没有考虑特征词在类内部文档中的分布情况。在类内部的文档中,如果特征词均匀分布在其中,则这个特征词能够很好的代表这个类的特征,如果只在几篇文档中出现,而在此类的其它文档中不出现,显然这样的特征词不能够代表这个类的特征。


步骤:
1. python jieba 关键词提取、去停用词
2.根据提取的关键词计算分别对应每种类别文章的df
3.进行信息增益特征提取


关键词提取、去停用词:

  1. #encoding=utf-8
  2. import jieba
  3. import jieba.analyse
  4. import sys
  5. import os

  6. #判断是否为中文
  7. def is_chinese(uchar):
  8.         if uchar >= u'\u4e00' and uchar<=u'\u9fa5':
  9.                 return True
  10.         else:
  11.                 return False

  12. #停用词加载
  13. stopwords = {}.fromkeys([ line.rstrip() for line in open('/usr/wzx/spark/svm/SVM_WZX_lib/stopword.dic') ])
  14. #结果集
  15. resultFile = file("/usr/wzx/spark/bayes/resu",'w')

  16. #训练集根目录
  17. base_dir = '/usr/wzx/spark/bayes/train'
  18. list = os.listdir(base_dir)
  19. #文件集合
  20. filelist = []
  21. for i in range(0, len(list)):
  22.     path = os.path.join(base_dir,list[i])
  23.     lis = os.listdir(path)
  24.     for j in range(0,len(lis)):
  25.         filepath = os.path.join(path,lis[j])
  26.         filelist.append(filepath)

  27. #循环读取文件进行特征词提取
  28. for i in range(0,len(filelist)):
  29.     f = open(filelist[i])
  30.     line = f.readline()
  31.     while line:
  32.        segs = jieba.cut(line,cut_all=False)
  33.        final = ''
  34.        for seg in segs:
  35.           segS = seg.encode('utf-8')
  36.           if segS not in stopwords and is_chinese(seg) and len(segS)>3:
  37.              final += ' '+seg

  38.        seg_list = jieba.analyse.extract_tags(final,5)
  39.        tem = " ".join(seg_list).encode('utf-8')
  40.        resultFile.writelines(tem+' ')
  41.        line = f.readline()

  42. resultFile.close()

信息增益:

  1. #encoding=utf-8
    import sys
    import os
    import math


    def IG_count(c1,c2,c3,c4):
        list1 = []
        list2 = []
        list3 = []
        dict1 = dict()
        ig_dict = dict()

  2.     class_count = 4
        doc_count = 2400
        
        c1_file = open(c1,"r")
        #c1_word_sets = c1_file.read()
        for line in c1_file:
            list1.append(line.split(" "))        
        
        c2_file = open(c2,"r")
        for line in c2_file:
            list1.append(line.split(" "))


        c3_file = open(c3,"r")
        for line in c3_file:
            list1.append(line.split(" "))


        c4_file = open(c4,"r")
        for line in c4_file:
            list1.append(line.split(" "))

        #计算word-doc—count矩阵
        for i in list1:
            if dict1.get(i[1]) == None:
                list2 = list()
                if i[2] == None:
                    list2.insert((int)(i[0]) - 1,0)
                else:                
                    list2.insert((int)(i[0]) - 1,(int)(i[2]))
                dict1[i[1]] = list2
            else:
                if i[2] == None:
                    dict1[i[1]].insert((int)(i[0]) - 1,0)
                else:                
                    dict1[i[1]].insert((int)(i[0]) - 1,(int)(i[2]))


        #计算每个Word的信息增益IG并保存到dit中
        print "word-doc—count矩阵"                
        for dict_cont in dict1.keys():
            #print dict_cont,dict1[dict_cont][0],dict1[dict_cont][1]

            t= class_count
            entropy = class_count * 1/class_count * math.log(t,2);
            wcount = 0 # // 出现word的文档的文档数量

            category_doc_count = doc_count/class_count #每个类别中的文档数量
            wcount_class = [0 for i in range(class_count)] #// 每个类别中出现单词word的文档数

            pw = 0.0# // 出现word的文档占全部文档的比重
            pcw = [0 for i in range(class_count)]# // 在单词word出现时各个类别中文档数占总文档数的比重
            pcw_b = [0 for i in range(class_count)]#// 在单词word不出现时各个类别中文档数占总文档数的比重
            #listabc = [0 for i in range(100)] or [0] * 100

            for i in range(0,class_count):  
                num = dict1[dict_cont][i]
                wcount_class[i] = num
                wcount += num
         
            #print wcount, dict_cont   
            #print wcount, wcount_class

            pw = 1.0 * wcount / doc_count;
            for i in range(0,class_count):
                    pcw[i] = 1.0 * wcount_class[i] / wcount;
                    #print doc_count, wcount
                    pcw_b[i] = 1.0 * (category_doc_count - wcount_class[i])/ (doc_count - wcount);


            d1 = 0.0;
            d2 = 0.0;


            for i in range(0,class_count):
                    #print pcw[i],pcw_b[i]
                    if pcw[i] == 0:
                            t1 = 0
                    else:
                            t1 = math.log(pcw[i],2)                        
                    d1 += pcw[i] * t1;
                    if pcw_b[i] == 0:
                            t2 = 0
                    else:
                            t2 = math.log(pcw_b[i],2)
                    d2 += pcw_b[i] * t2;


            ig = entropy + pw * d1 + (1.0 - pw) * d2;
            ig_dict[dict_cont] = ig
                
            
        #保存信息增益信息
        #print "word IG"
        #for dict_cont in ig_dict.keys():
        #    print dict_cont,ig_dict[dict_cont]

        #print "sort word IG"
        num = 0
        word_dicts_list = sorted([(v, k) for k, v in ig_dict.items()], reverse=True)
        wzx_f = open('/usr/wzx/spark/bayes/result_gain','w')
        wzx_f_temp = open('/usr/wzx/spark/bayes/result_gain_temp','w')
        for i in word_dicts_list:
            wzx_f.write(i[1]+' ')
            wzx_f_temp.write(i[1]+' '+str(i[0])+' \n')
            num = num+1
        wzx_f.close()                 
        wzx_f_temp.close()       
        print(num)

        c1_file.close()
        c2_file.close()
        c3_file.close()
        c4_file.close()


    #---------我是开心快乐的分割线-----------


    #获取全部关键词
    all_the_text = open('/usr/wzx/spark/bayes/resu').read()
    arrText = all_the_text.split(' ')
    fileLocalNames=os.listdir('/usr/wzx/spark/bayes/train')
    for fn in fileLocalNames: 
      #创建类别文件
      f=open('/usr/wzx/spark/bayes/gain/'+fn,'w')
      #打开该类别文件读取获取DF
      f2 = open('/usr/wzx/spark/bayes/train/'+fn+'/'+fn+'.txt')
      wzxDict = {}
      #遍历关键词添加到字典,并初始化为0
      for temKey in arrText:
         wzxDict[temKey] = 0
      line = f2.readline()
      while line:
         for te in wzxDict.keys():
           if te in line:
             wzxDict[te] = wzxDict[te] + 1     


         line = f2.readline()
      #将dict中的数据插入到文件中
      for k in wzxDict.keys():
         if k.strip()!='':
            f.write(fn+' '+k+' '+str(wzxDict[k])+'\n')
      f2.close()
      f.close()


    wzxLocal='/usr/wzx/spark/bayes/gain/'
    IG_count(wzxLocal+fileLocalNames[0],wzxLocal+fileLocalNames[1],wzxLocal+fileLocalNames[2],wzxLocal+fileLocalNames[3])



OK,根据提取的特征将文本向量化即可进行贝叶斯分类,向量维度即特征个数

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29754888/viewspace-1983595/,如需转载,请注明出处,否则将追究法律责任。

下一篇: Python Flask
请登录后发表评论 登录
全部评论

注册时间:2014-07-16

  • 博文量
    180
  • 访问量
    1107437