机器学习算法的空间、时间复杂度依赖于输入数据的规模,维度规约(Dimensionality reduction)则是一种被用于降低输入数据维数的方法。维度规约可以分为两类:

  • 特征选择(feature selection),从原始的d维空间中,选择为我们提供信息最多的k个维(这k个维属于原始空间的子集)
  • 特征提取(feature extraction),将原始的d维空间映射到k维空间中(新的k维空间不输入原始空间的子集)

  在文本挖掘与文本分类的有关问题中,常采用特征选择方法。原因是文本的特征一般都是单词(term),具有语义信息,使用特征选择找出的k维子集,仍然是单词作为特征,保留了语义信息,而特征提取则找k维新空间,将会丧失了语义信息。

  对于一个语料而言,我们可以统计的信息包括文档频率和文档类比例,所有的特征选择方法均依赖于这两个统计量,目前,文本的特征选择方法主要有:DF, MI, IG, CHI,WLLR,WFO六种。

  为了方便描述,我们首先一些概率上的定义:

    p(t):一篇文档x包含特征词t的概率。

    :文档x不属于Ci的概率。

    p(Ci|t):已知文档x的包括某个特征词t条件下,该文档属于Ci的概率

    : 已知文档属于C条件下,该文档不包括特征词t的概率

  类似的其他的一些概率如p(Ci), 等,有着类似的定义。

为了估计这些概率,我们需要通过统计训练样本的相关频率信息,如下表:

其中:

   Aij: 包含特征词ti,并且类别属于Cj的文档数量    Bij: 包含特征词ti,并且类别属于不Cj的文档数量

   Cij:不包含特征词ti,并且类别属于Cj的文档数量 Dij:不包含特征词ti,并且类别属于不Cj的文档数量

   Aij + Bij: 包含特征词ti的文档数量          Cij  + Dij:不包含特征词ti的文档数量

   Aij + Cij:Cj类的文档数量数据             Bij + Dij:非Cj类的文档数量数据

   Aij + Bij + Cij  + Dij = N :语料中所有文档数量。

有了这些统计量,有关概率的估算就变得容易,如:

   p(ti) =     (Aij + Bij) / N;    p(Cj) = (Aij +  Cij) / N;

    p(Cj|tj) = Aij  / (Aij + Bij)

......类似的一些概率计算可以依照上表计算。

  介绍了事情发展的前因,现在进入正题:常见的四种特征选择方法如何计算。

  1)DF(Document Frequency)

DF:统计特征词出现的文档数量,用来衡量某个特征词的重要性,DF的定义如下:

  DF的动机是,如果某些特征词在文档中经常出现,那么这个词就可能很重要。而对于在文档中出现很少(如仅在语料中出现1次)特征词,携带了很少的信息量,甚至是"噪声",这些特征词,对分类器学习影响也是很小。

  DF特征选择方法属于无监督的学习算法(也有将其改成有监督的算法,但是大部分情况都作为无监督算法使用),仅考虑了频率因素而没有考虑类别因素,因此,DF算法的将会引入一些没有意义的词。如中文的"的"、"是", "个"等,常常具有很高的DF得分,但是,对分类并没有多大的意义。

  2)MI(Mutual Information)

  互信息法用于衡量特征词与文档类别直接的信息量,互信息法的定义如下:

  继续推导MI的定义公式:

  从上面的公式上看出:如果某个特征词的频率很低,那么互信息得分就会很大,因此互信息法倾向"低频"的特征词。相对的词频很高的词,得分就会变低,如果这词携带了很高的信息量,互信息法就会变得低效。

  3)IG(Information Gain)

  信息增益法,通过某个特征词的缺失与存在的两种情况下,语料中前后信息的增加,衡量某个特征词的重要性。

信息增益的定义如下:

依据IG的定义,每个特征词ti的IG得分前面一部分:计算值是一样,可以省略。因此,IG的计算公式如下:

IG与MI存在关系:

因此,IG方式实际上就是互信息与互信息加权。

4)CHI(Chi-square)

CHI特征选择算法利用了统计学中的"假设检验"的基本思想:首先假设特征词与类别直接是不相关的,如果利用CHI分布计算出的检验值偏离阈值越大,那么更有信心否定原假设,接受原假设的备则假设:特征词与类别有着很高的关联度。CHI的定义如下:

对于一个给定的语料而言,文档的总数N以及Cj类文档的数量,非Cj类文档的数量,他们都是一个定值,因此CHI的计算公式可以简化为:

CHI特征选择方法,综合考虑文档频率与类别比例两个因素

5)WLLR(Weighted Log Likelihood Ration)

WLLR特征选择方法的定义如下:

计算公式如下:

6)WFO(Weighted Frequency and Odds)

最后一个介绍的算法,是由苏大李寿山老师提出的算法。通过以上的五种算法的分析,李寿山老师认为,"好"的特征应该有以下特点:

  • 好的特征应该有较高的文档频率
  • 好的特征应该有较高的文档类别比例

WFO的算法定义如下:

如果

否则:

不同的语料,一般来说文档词频与文档的类别比例起的作用应该是不一样的,WFO方法可以通过调整参数,找出一个较好的特征选择依据。

-----------------------------------------分割线---------------------------------------------

  介绍完理论部分,就要给出代码了(只给出公式,不给出代码的都是调戏良家的行为~)。文本挖掘之文本表示一文,利用了sklearn开源工具,自然先首先sklearn工具,可惜的是sklearn文本的特征选择方法仅提供了CHI一种。为此在sklearn框架下,尝试自己编写这些特征选择方法的代码,自己动手,丰衣足食。

笔者实现了三种特征选择方法:IG,MI和WLLR,看官如果对其他特征选择方法感兴趣,可以尝试实现一下~ 好了,啥也不说了,上代码,特征选择模块代码:

#!/usr/bin/env python
# coding=gbk import os
import sys import numpy as np def get_term_dict(doc_terms_list):
term_set_dict = {}
for doc_terms in doc_terms_list:
for term in doc_terms:
term_set_dict[term] = 1
term_set_list = sorted(term_set_dict.keys()) #term set 排序后,按照索引做出字典
term_set_dict = dict(zip(term_set_list, range(len(term_set_list))))
return term_set_dict def get_class_dict(doc_class_list):
class_set = sorted(list(set(doc_class_list)))
class_dict = dict(zip(class_set, range(len(class_set))))
return class_dict def stats_term_df(doc_terms_list, term_dict):
term_df_dict = {}.fromkeys(term_dict.keys(), 0)
for term in term_set:
for doc_terms in doc_terms_list:
if term in doc_terms_list:
term_df_dict[term] +=1
return term_df_dict def stats_class_df(doc_class_list, class_dict):
class_df_list = [0] * len(class_dict)
for doc_class in doc_class_list:
class_df_list[class_dict[doc_class]] += 1
return class_df_list def stats_term_class_df(doc_terms_list, doc_class_list, term_dict, class_dict):
term_class_df_mat = np.zeros((len(term_dict), len(class_dict)), np.float32)
for k in range(len(doc_class_list)):
class_index = class_dict[doc_class_list[k]]
doc_terms = doc_terms_list[k]
for term in set(doc_terms):
term_index = term_dict[term]
term_class_df_mat[term_index][class_index] +=1
return term_class_df_mat def feature_selection_mi(class_df_list, term_set, term_class_df_mat):
A = term_class_df_mat
B = np.array([(sum(x) - x).tolist() for x in A])
C = np.tile(class_df_list, (A.shape[0], 1)) - A
N = sum(class_df_list)
class_set_size = len(class_df_list) term_score_mat = np.log(((A+1.0)*N) / ((A+C) * (A+B+class_set_size)))
term_score_max_list = [max(x) for x in term_score_mat]
term_score_array = np.array(term_score_max_list)
sorted_term_score_index = term_score_array.argsort()[: : -1]
term_set_fs = [term_set[index] for index in sorted_term_score_index] return term_set_fs def feature_selection_ig(class_df_list, term_set, term_class_df_mat):
A = term_class_df_mat
B = np.array([(sum(x) - x).tolist() for x in A])
C = np.tile(class_df_list, (A.shape[0], 1)) - A
N = sum(class_df_list)
D = N - A - B - C
term_df_array = np.sum(A, axis = 1)
class_set_size = len(class_df_list) p_t = term_df_array / N
p_not_t = 1 - p_t
p_c_t_mat = (A + 1) / (A + B + class_set_size)
p_c_not_t_mat = (C+1) / (C + D + class_set_size)
p_c_t = np.sum(p_c_t_mat * np.log(p_c_t_mat), axis =1)
p_c_not_t = np.sum(p_c_not_t_mat * np.log(p_c_not_t_mat), axis =1) term_score_array = p_t * p_c_t + p_not_t * p_c_not_t
sorted_term_score_index = term_score_array.argsort()[: : -1]
term_set_fs = [term_set[index] for index in sorted_term_score_index] return term_set_fs def feature_selection_wllr(class_df_list, term_set, term_class_df_mat):
A = term_class_df_mat
B = np.array([(sum(x) - x).tolist() for x in A])
C_Total = np.tile(class_df_list, (A.shape[0], 1))
N = sum(class_df_list)
C_Total_Not = N - C_Total
term_set_size = len(term_set) p_t_c = (A + 1E-6) / (C_Total + 1E-6 * term_set_size)
p_t_not_c = (B + 1E-6) / (C_Total_Not + 1E-6 * term_set_size)
term_score_mat = p_t_c * np.log(p_t_c / p_t_not_c) term_score_max_list = [max(x) for x in term_score_mat]
term_score_array = np.array(term_score_max_list)
sorted_term_score_index = term_score_array.argsort()[: : -1]
term_set_fs = [term_set[index] for index in sorted_term_score_index] print term_set_fs[:10]
return term_set_fs def feature_selection(doc_terms_list, doc_class_list, fs_method):
class_dict = get_class_dict(doc_class_list)
term_dict = get_term_dict(doc_terms_list)
class_df_list = stats_class_df(doc_class_list, class_dict)
term_class_df_mat = stats_term_class_df(doc_terms_list, doc_class_list, term_dict, class_dict)
term_set = [term[0] for term in sorted(term_dict.items(), key = lambda x : x[1])]
term_set_fs = [] if fs_method == 'MI':
term_set_fs = feature_selection_mi(class_df_list, term_set, term_class_df_mat)
elif fs_method == 'IG':
term_set_fs = feature_selection_ig(class_df_list, term_set, term_class_df_mat)
elif fs_method == 'WLLR':
term_set_fs = feature_selection_wllr(class_df_list, term_set, term_class_df_mat) return term_set_fs

    在movie语料里面比较着三种特征选择方法,调用方法如下:

#!/usr/bin/env python
# coding=gbk import os
import sys import numpy as np
import matplotlib.pyplot as plt from sklearn.datasets import load_files
from sklearn.cross_validation import train_test_split
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB import feature_selection def text_classifly_twang(dataset_dir_name, fs_method, fs_num):
print 'Loading dataset, 80% for training, 20% for testing...'
movie_reviews = load_files(dataset_dir_name)
doc_str_list_train, doc_str_list_test, doc_class_list_train, doc_class_list_test = train_test_split(movie_reviews.data, movie_reviews.target, test_size = 0.2, random_state = 0) print 'Feature selection...'
print 'fs method:' + fs_method, 'fs num:' + str(fs_num)
vectorizer = CountVectorizer(binary = True)
word_tokenizer = vectorizer.build_tokenizer()
doc_terms_list_train = [word_tokenizer(doc_str) for doc_str in doc_str_list_train]
term_set_fs = feature_selection.feature_selection(doc_terms_list_train, doc_class_list_train, fs_method)[:fs_num] print 'Building VSM model...'
term_dict = dict(zip(term_set_fs, range(len(term_set_fs))))
vectorizer.fixed_vocabulary = True
vectorizer.vocabulary_ = term_dict
doc_train_vec = vectorizer.fit_transform(doc_str_list_train)
doc_test_vec= vectorizer.transform(doc_str_list_test) clf = MultinomialNB().fit(doc_train_vec, doc_class_list_train) #调用MultinomialNB分类器
doc_test_predicted = clf.predict(doc_test_vec) acc = np.mean(doc_test_predicted == doc_class_list_test)
print 'Accuracy: ', acc return acc if __name__ == '__main__':
dataset_dir_name = sys.argv[1]
fs_method_list = ['IG', 'MI', 'WLLR']
fs_num_list = range(25000, 35000, 1000)
acc_dict = {} for fs_method in fs_method_list:
acc_list = []
for fs_num in fs_num_list:
acc = text_classifly_twang(dataset_dir_name, fs_method, fs_num)
acc_list.append(acc)
acc_dict[fs_method] = acc_list
print 'fs method:', acc_dict[fs_method] for fs_method in fs_method_list:
plt.plot(fs_num_list, acc_dict[fs_method], '--^', label = fs_method)
plt.title('feature selection')
plt.xlabel('fs num')
plt.ylabel('accuracy')
plt.ylim((0.82, 0.86)) plt.legend( loc='upper left', numpoints = 1)
plt.show()

  输出的结果:

  从上面的图看出:分类的性能随着特征选择的数量的增加,呈现“凸”形趋势:1)在特征数量较少的情况下,不断增加特征的数量,有利于提高分类器的性能,呈现“上升”趋势;2)随着特征数量的不断增加,将会引入一些不重要的特征,甚至是噪声,因此,分类器的性能将会呈现“下降”的趋势。这张“凸”形趋势体现出了特征选择的重要性:选择出重要的特征,并降低噪声,提高算法的泛化能力。

参数文献:

    1.Y. Yang and J. Pedersen. 1997. A comparative study on feature selection in text categorization.

    2.Shoushan Li, Rui Xia, Chengqing Zong and Chu-Ren Huang.2009.A Framework of Feature Selection Methods for Text Categorization

    3.老板的课件

文本挖掘之特征选择(python 实现)的更多相关文章

  1. 使用Python的文本挖掘的特征选择/提取

    在文本挖掘与文本分类的有关问题中,文本最初始的数据是将文档表示成向量空间模型的一个矩阵,而这个矩阵所拥有的就是不同的词,常采用特征选择方法.原因是文本的特征一般都是单词(term),具有语义信息,使用 ...

  2. NLP︱句子级、词语级以及句子-词语之间相似性(相关名称:文档特征、词特征、词权重)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 关于相似性以及文档特征.词特征有太多种说法.弄 ...

  3. 转:解决Python中文编码问题

    Python 文本挖掘:解决Python中文编码问题 转于:http://rzcoding.blog.163.com/blog/static/2222810172013101785738166/   ...

  4. 【原】python中文文本挖掘资料集合

    这些网址是我在学习python中文文本挖掘时觉得比较好的网站,记录一下,后期也会不定期添加:   1.http://www.52nlp.cn/python-%E7%BD%91%E9%A1%B5%E7% ...

  5. < 独立项目 - 文本挖掘 > - 2016/11/13 第二更 - <Python环境准备>

    < 独立项目 -  文本挖掘 > 项目立项的相关背景介绍,TODO方向. 一.Ubuntu环境配置 主机系统:Windows 7 SP1  64位操作系统 | i5-4210 CPU | ...

  6. python进行机器学习(二)之特征选择

    毫无疑问,解决一个问题最重要的是恰当选取特征.甚至创造特征的能力,这叫做特征选取和特征工程.对于特征选取工作,我个人认为分为两个方面: 1)利用python中已有的算法进行特征选取. 2)人为分析各个 ...

  7. python利用决策树进行特征选择

    python利用决策树进行特征选择(注释部分为绘图功能),最后输出特征排序: import numpy as np import tflearn from tflearn.layers.core im ...

  8. 回归分析特征选择(包括Stepwise算法) python 实现

    # -*- coding: utf-8 -*-"""Created on Sat Aug 18 16:23:17 2018 @author: acadsoc"& ...

  9. Python数据挖掘-文本挖掘

    文本挖掘概要 搞什么的? 从大量文本数据中,抽取出有价值的知识,并且利用这些知识更好的组织信息的过程. 目的是什么? 把文本信息转化为人们可利用的知识. 举例来说,下面的图表利用文本挖掘技术对库克ip ...

随机推荐

  1. TCP keepalive overview

    2. TCP keepalive overview In order to understand what TCP keepalive (which we will just call keepali ...

  2. 获取设备唯一标识 uuid(采用第三方库SSKeychain)

    SSKeyChain 下载链接: http://pan.baidu.com/s/1booV3VD 密码: ivdi /** *  获取设备唯一标识 uuid */ +(NSString*) uuid ...

  3. MySQL一些常用的时间函数

    https://my.oschina.net/sallency/blog/470370

  4. jq的核心基础

    1.jq代码的风格    jq对象$().css();jQuery().css();  //获取jquery对象 示例$().css('background':'red').css('font-siz ...

  5. ios中常用数据类型相互转换

    ios中常用数据类型相互转换 //1. NSMutableArray和NSArray互转 // NSArray转为NSMutableArray NSMutableArray *arrM = [arr ...

  6. 第一个Json.Net Demo

    //序列化 private void btnShow_Click(object sender, EventArgs e) { DataTable dt = new DataTable(); DataC ...

  7. thttpd增加gzip压缩响应报文体功能,以减少传输数据量

    thttpd thttpd是一个非常小巧的轻量级web server,它非常非常简单,仅仅提供了HTTP/1.1和简单的CGI支持,在其官方网站上有一个与其他web server(如Apache, Z ...

  8. 利用selenium Server实现IE firefox 和 chrome兼容性测试

    本文的主题是基于Selenium Server,使用 Java 语言编写网页交互流程, 实现多浏览器(IE Firefox Chrome)兼容性测试,为使用纪要. Selenium Selenium是 ...

  9. mysql慢查日志分析工具 percona-toolkit

    备忘自: http://blog.csdn.net/seteor/article/details/24017913 1. 工具简介 pt-query-digest是用于分析mysql慢查询的一个工具, ...

  10. 12C RAC中的一个数据库实例自动crash并报ORA-27157、ORA-27300等错误

    rhel7.2上安装12C RAC数据库后,其中一个数据库实例经常会自动crash.查看alert日志发现以下错误信息: Errors in file /d12/app/oracle/diag/rdb ...