用TFIDF给特征词赋权值

0  背景

     
      在上一篇的用CHI检验的文章中我们已经获得了特征词,这些特征词在某一篇文章中出现的频率是不一样的,也可以说词与词的重要性是不一样的。为了标示特征词语的重要程度,就必须赋权重。在本篇文章中,我们使用的方法是TFIDF。

1   VSM向量空间模型

       
      哎?不是讲TFIDF吗,怎么会有VSM向量空间模型呢。是这样,在经过CHI提取到特征词后,然后再用TFIDF给特征词赋权值以后,这样就会组成一个向量:(term1,权重值;term2,权重值;........;termn,权重值),n为特征词的数量。这样的向量就是VSM。每篇文章都可以表示为这样的向量。
      比如说吧,对所有的训练样本经过CHI检验后,提取到的特征词有(“篮球”,“范冰冰”,“航空母舰”,“NBA”,“股票”,“综艺”,“娱乐圈”)这些词,当然真实的特征词肯定是成千上万的,在这里只是简单地举一个例子。当有一篇文章时,比如内容是“范冰冰是娱乐圈的人,范冰冰真的很红!”,那根据上面的特征词向量,那么只用“范冰冰”和“娱乐圈”两个词就可以表示这篇文章了。
      其实我还少说一个东西,那就是特征词的权重值。还是上面的这个例子,“范冰冰”出现了两次,“娱乐圈”出现了1词,直观上肯定是“范冰冰”更重要一些,也就是权值更大一些。所以,为了表示一篇文章,只有特征词是不够的,还需要特征词有权重值。So。。。让我们开始TFIDF吧!

2   TFIDF应用到文本分类

       TFIDF的核心思想是,一篇文章中的某个词出现的频率很高,而在其它文章中出现的频率相对很低,那么就说明这个词具有很好的区分能力,应该给其赋以较高的权重值。

      对于某一篇文章来说,某个词term的TFIDF值为:

                                 

       上面公式中TF的意义是:term在本篇文章中的重要性。只有term的词频是不足以表征term在本篇的重要性的,比如term在一篇总词数为100词的文章中出现3词,在另一篇总词数为500词的文章中出现3词,term肯定在前篇文章中更加重要。

       IDF的公式的意义是:包含term的文章是不是比较集中,即包含term的文章是不是相对比较少。IDF越大,就是包含term的文章数比较集中,就说明具备分类的能力比较强。

       在CHI检验提取特征词的时候,总文档数和包含每一个词的文档数都可以统计出来。所以在TFIDF计算的过程,我们就只可以统计TF相关的值了。多说一句,其实是只有在训练集训练分类模型的时候,才会用到特征词提取的方法,在测试集的时候并不会用到CHI,因为特征词都已经提取出来了。在给测试集分类的时候,我们只使用TFIDF计算权重值就好了。

       补充部分: 本篇文章中的总词数是原始文章的总词数呢?还是特征词提取之后的总词数?我分别对这两种情况进行了实验,发现使用原始文章的总词数准确率会更高一些。我觉得是因为原始文章的总词数更能表现文章的真实性,即没有一点降维,但是使用特征词的总词数也就是使用了经过降维处理后的文章,真实性肯定会有所下降。但是,我只是实验了我的程序,可能还不具太大的参考性。读者可以自行实验。

       

3  程序附录

      下面的代码是一篇文章的TFIDF值是怎样计算的,当初没有考虑时间复杂度,只想着怎么实现了。。。就当参考吧。。。。
//第一个参数为提取证词后的文件路径,第二个参数为目的文件,第三个为特征词集合,第四个为VSM向量表示
	public void computeTFIDF(String path, String desFile, VSM v, HashMap  afterCHI){
		String artTmp="";
		//读出这篇文章
		File file = new File(path);
		String str = "";
		//System.out.println(path);
		try {
			FileInputStream in = new FileInputStream(file);
			int size = in.available();
			byte[] buffer = new byte[size];
			in.read(buffer);
			in.close();
			str = new String(buffer, "UTF-8");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String[] strline = str.split(" ");
		//totalNum = strline.length-1;
		totalNum = Integer.parseInt(strline[strline.length-1]);
		//统计这篇文章中的特征词频
		for (int i = 0; i < strline.length-1; i++) {
			if(v.vsm.contains(strline[i])){
				vsmOne.put(strline[i], vsmOne.get(strline[i])+1);
			}
		}
		//计算这篇文章的每个特征词的TFIDF值
		Iterator it = v.vsm.iterator();
		while(it.hasNext()){
			String tmp = it.next();
			vsmOne.put(tmp, (vsmOne.get(tmp)/totalNum)*afterCHI.get(tmp));
		}
		
		//把这篇文章的计算出的IFIDF写入文件
		try {
			 FileWriter fw=new FileWriter(desFile,true);
			 String[] absuPath = path.split("\\\\");
			 
			 if(absuPath[absuPath.length-2].equals("C000008")){       //C000008为一个类别
				 artTmp = toString(1);
			 }
			 if(absuPath[absuPath.length-2].equals("C000009")){
				 artTmp = toString(2);
			 }
			 if(absuPath[absuPath.length-2].equals("C000010")){
				 artTmp = toString(3);
			 }
			 if(absuPath[absuPath.length-2].equals("C000011")){
				 artTmp = toString(4);
			 }
			 if(absuPath[absuPath.length-2].equals("C000012")){
				 artTmp = toString(5);
			 }
			 if(absuPath[absuPath.length-2].equals("C000013")){
				 artTmp = toString(6);
			 }
			 if(absuPath[absuPath.length-2].equals("C000014")){
				 artTmp = toString(7);
			 }
			 if(absuPath[absuPath.length-2].equals("C000015")){
				 artTmp = toString(8);
			 }
			 if(absuPath[absuPath.length-2].equals("C000016")){
				 artTmp = toString(9);
			 }
			 
			 fw.write(artTmp);
			 fw.flush();
			 fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
      上面的源文件是的一篇文章的特征词集,目的文件的格式什么呢?因为我采用的分类器是SVM,所以用的是林志仁教授的LibSVM,所以目的文件的格式是LibSVM需要的数据格式。在下一篇文章中将会记录LibSVM是怎么样使用的。

你可能感兴趣的:(文本分类)