特征选择(feature selection)是从训练集合出现的词项中选出一部分子集的过程。
在文本分类过程也仅仅使用这个子集作为特征。
特征选择有两个主要目的:
第一,通过减少有效的词汇空间来提高分类器训练和应用的效率。这对于除NB 之外其他的训练开销较大的分类器来说尤为重要。
第二,特征选择能够去除噪音特征,从而提高分类的精度。
噪音特征(noise feature)指的是那些加入文本表示之后反而会增加新数据上的分类错误率的特征。假定某个罕见词项(如arachnocentric )对某个类别(如China)不提供任何信息,但是在训练集中所有的arachnocentric恰好都出现在China 类中,那么通过学习后可能会产生一个分类器,它会将包含arachnocentric的测试文档误分到China 类中去。这种由于训练集的偶然性导出的不正确的泛化结果称为过学习(overfitting)。
我们可以把特征选择看成将复杂分类器替换成简单分类器的过程,其中复杂分类器使用全部特征,而简单分类器只使用部分特征。
一个常用的特征选择方法是计算词项t和类别c的 *MI(expected mutual information,期望互
信息)*①作为A(t,c)。MI度量的是词项的存在与否给类别c的正确判断所带来的信息量。MI的形
式化定义如下:
例如:
这里使用的是Reuters-RCV1 语料,为了简化,我们只选择了sport类和auto类,为了使运算时间不太久,其中每个类中只存放300个文件。
语料下载网址
我们下载其中的20news-bydate.tar
代码为:
package test5;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
public class MutualInformation {
public static void getToken(String filePath,ArrayList<String> C,Map<String,String> trainingSet,ArrayList<String> vocabulary)throws IOException{
try{
File file=new File(filePath);
String fileName=filePath.substring(filePath.lastIndexOf("\\")+1); //得到文件夹名称
File[] fileList=file.listFiles(); //获得文档集下的所有文档
for(int i=0;i<fileList.length;i++){
InputStream is=new FileInputStream(fileList[i]);
BufferedReader bufr=new BufferedReader(new InputStreamReader(is));
String temp=null;
String docStr=""; //用来存放文档中的内容
while((temp=bufr.readLine())!=null){
docStr+=temp;
String[] words=temp.split("\\s+|:|\\;|\\.|\"|\'|,|_+|!|\\||\\*+|~|\\(|-|\\)|/|\\?+"
+ "|>|<|\\[|\\]|=+|\\d+|^+|\\{|\\}+|\\+|@|$"); //分割字符串
for(String word:words){
if(!C.contains(word)){
C.add(word); //将单词放入类别list中,不能重复
}
if(!vocabulary.contains(word)){
vocabulary.add(word); //存放所有token
}
}
}
trainingSet.put(docStr,fileName); //将文档中的内容和类别放入trainingSet中
bufr.close();
is.close(); //关闭io流
}
}catch(IOException E){
System.out.println("error in read file");
}
}
public static List<String> MI(Map<String,String> doc,ArrayList<String> Class,String str){ //互信息去噪
Map<String,Double> utilityIndex=new HashMap<String,Double>(); //用来存放互信息得分
double N=doc.size(); //得到文档 数目
for(String word:Class){
double N11=0,N10=0,N01=0,N00=0;
for(Entry<String,