用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值是怎樣計算的,當初沒有考慮時間複雜度,只想着怎麼實現了。。。就當參考吧。。。。
<span style="font-size:18px;">//第一個參數爲提取證詞後的文件路徑,第二個參數爲目的文件,第三個爲特徵詞集合,第四個爲VSM向量表示
	public void computeTFIDF(String path, String desFile, VSM v, HashMap<String,Double>  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<String> 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();
		}
		
	}</span>
     上面的源文件是的一篇文章的特徵詞集,目的文件的格式什麼呢?因爲我採用的分類器是SVM,所以用的是林志仁教授的LibSVM,所以目的文件的格式是LibSVM需要的數據格式。在下一篇文章中將會記錄LibSVM是怎麼樣使用的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章