天天看點

Spark應用HanLP對中文語料進行文本挖掘--聚類

軟體:IDEA2014、Maven、HanLP、JDK;

用到的知識:HanLP、Spark TF-IDF、Spark kmeans、Spark mapPartition;

用到的資料集:

http://www.threedweb.cn/thread-1288-1-1.html

(不需要下載下傳,已經包含在工程裡面);

工程下載下傳:

https://github.com/fansy1990/hanlp-test  。

  1. 問題描述

        現在有一個中文文本資料集,這個資料集已經對其中的文本做了分類,如下:

Spark應用HanLP對中文語料進行文本挖掘--聚類

其中每個檔案夾中含有個數不等的檔案,比如環境有200個,藝術有248個;同時,每個檔案的内容基本上就是一些新聞報道或者中文描述,如下:

Spark應用HanLP對中文語料進行文本挖掘--聚類

現在需要做的就是,把這些文檔進行聚類,看其和原始給定的類别的重合度有多少,這樣也可以反過來驗證我們聚類算法的正确度。

  1. 解決思路:

      2.1 文本預處理:

 1.    由于檔案的編碼是GBK的,讀取到Spark中全部是亂碼,是以先使用Java把代碼轉為UTF8編碼;  

 2. 由于文本存在多個檔案中(大概2k多),使用Spark的wholeTextFile讀取速度太慢,是以考慮把這些檔案全部合并為一個檔案,這時又結合1.的轉變編碼,是以在轉變編碼的時候就直接把所有的資料存入同一個檔案中;

    其存儲的格式為: 每行:    檔案名.txtt檔案内容

   如:  41.txt 【 日  期 】199601....

這樣子的話,就可以通過.txtt 來對每行文本進行分割,得到其檔案名以及檔案内容,這裡每行其實就是一個檔案了。

2.2 分詞

   分詞直接采用HanLP的分詞來做,HanLP這裡選擇兩種:Standard和NLP(還有一種就是HighSpeed,但是這個木有使用者自定義詞典,是以前期考慮先用兩種),具體參考:

https://github.com/hankcs/HanLP

;

2.3 詞轉換為詞向量

  在Kmeans算法中,一個樣本需要使用數值類型,是以需要把文本轉為數值向量形式,這裡在Spark中有兩種方式。其一,是使用TF-IDF;其二,使用Word2Vec。這裡暫時使用了TF-IDF算法來進行,這個算法需要提供一個numFeatures,這個值越大其效果也越好,但是相應的計算時間也越長,後面也可以通過實驗驗證。

2.4 使用每個文檔的詞向量進行聚類模組化

在進行聚類模組化的時候,需要提供一個初始的聚類個數,這裡面設定為10,因為我們的資料是有10個分組的。但是在實際的情況下,一般這個值是需要通過實驗來驗證得到的。

2.5 對聚類後的結果進行評估

這裡面采用的思路是:

  1. 得到聚類模型後,對原始資料進行分類,得到原始檔案名和預測的分類id的二進制組(fileName,predictId);
  2. 針對(fileName,predictId),得到(fileNameFirstChar ,fileNameFirstChar.toInt - predictId)的值,這裡需要注意的是fileNameFirstChar其實就是代表這個檔案的原始所屬類别了。
  3. 這裡有一個一般假設,就是使用kmeans模型預測得到的結果大多數是正确的,是以fileNameFirstChar.toInt-predictId得到的衆數其實就是分類的正确的個數了(這裡可能比較難以了解,後面會有個小李子來說明這個問題);
  4. 得到每個實際類别的預測的正确率後就可以去平均預測率了。
  5. 改變numFeatuers的值,看下是否numFeatures設定的比較大,其正确率也會比較大?
  6. 具體步驟:

    3.1 開發環境--Maven

首先第一步,當然是開發環境了,因為用到了Spark和HanLP,是以需要在pom.xml中加入這兩個依賴:

Spark應用HanLP對中文語料進行文本挖掘--聚類

其版本為:portable-1.3.4.version>、 1.6.0-cdh5.7.3.version>。

3.2 檔案轉為UTF-8編碼及存儲到一個檔案

這部分内容可以直接參考:src/main/java/demo02_transform_encoding.TransformEncodingToOne 這裡的實作,因為是Java基本的操作,這裡就不加以分析了。

3.3 Scala調用HanLP進行中文分詞

Scala調用HanLP進行分詞和Java的是一樣的,同時,因為這裡有些詞語格式不正常,是以把這些特殊的詞語添加到自定義詞典中,其示例如下:

作者:fansy1990

來源:CSDN

原文:

https://blog.csdn.net/fansy1990/article/details/77577061

版權聲明:本文為部落客原創文章,轉載請附上博文連結!

Spark應用HanLP對中文語料進行文本挖掘--聚類

運作完成後,即可得到分詞的結果,如下:

Spark應用HanLP對中文語料進行文本挖掘--聚類

考慮到使用友善,這裡把分詞封裝成一個函數:

Spark應用HanLP對中文語料進行文本挖掘--聚類

輸入即是一個中文的文本,輸出就是分詞的結果,同時去掉了一些常用的停用詞。

3.4 求TF-IDF

在Spark裡面求TF-IDF,可以直接調用Spark内置的算法子產品即可,同時在Spark的該算法子產品中還對求得的結果進行了次元變換(可以了解為特征選擇或“降維”,當然這裡的降維可能是提升次元)。代碼如下:

Spark應用HanLP對中文語料進行文本挖掘--聚類

變量docs是一個DataFrame[fileName, sentence_words] ,經過HashingTF後,變成了變量 featurizedData ,同樣是一個DataFrame[fileName,sentence_words, rawFeatures]。這裡通過setInputCol以及SetOutputCol可以設定輸入以及輸出列名(列名是針對DataFrame來說的,不知道的可以看下DataFrame的API)。

接着,經過IDF模型,得到變量 rescaledData ,其DataFrame[fileName,sentence_words, rawFeatures, features] 。

執行結果為:

Spark應用HanLP對中文語料進行文本挖掘--聚類

3.5 建立KMeans模型

直接參考官網給定例子即可:

Spark應用HanLP對中文語料進行文本挖掘--聚類

這裡有計算cost值的,但是這個值評估不是很準确,比如我numFeature設定為2000的話,那麼這個值就很大,但是其實其正确率會比較大的。

3.6 模型評估

這裡的模型評估直接使用一個小李子來說明:比如,現在有這樣的資料:

Spark應用HanLP對中文語料進行文本挖掘--聚類

其中,1開頭,2開頭和4開頭的屬于同一類文檔,後面的0,3,2,1等,代表這個文檔被模型分類的結果,那麼可以很容易的看出針對1開頭的文檔,

其分類正确的有4個,其中("123.txt",3)以及(“126.txt”,1)是分類錯誤的結果,這是因為,在這個類别中預測的結果中0是最多的,是以0是和1開頭的文檔對應起來的,這也就是前面的假設。

  1. 把同一類文檔分到同一個partition中;
    Spark應用HanLP對中文語料進行文本挖掘--聚類

這裡的file_index,是對不同類的文檔進行編号,這個編号就對應每個partition,看MyPartitioner的實作:

Spark應用HanLP對中文語料進行文本挖掘--聚類
  1. 針對每個partition進行整合操作:

    在整合每個partition之前,我們先看下我們自定義的MyPartitioner是否在正常工作,可以列印下結果:

Spark應用HanLP對中文語料進行文本挖掘--聚類

運作如下:

Spark應用HanLP對中文語料進行文本挖掘--聚類

其中第一列代表每個partition的id,第二列是資料,發現其資料确實是按照預期進行處理的;接着可以針對每個partition進行資料整合:

Spark應用HanLP對中文語料進行文本挖掘--聚類

在整合之前先執行一個map操作,把資料變成((fileNameFirstChar, fileNameFirstChar.toInt - predictId), 1),其中fileNameFirstChar代表檔案的第一個字元,其實也就是檔案的所屬實際類别,後面的fileNameFirstChar.toInt-predictId 其實就是判斷預測的結果是否對了,這個值的衆數就是預測對的;最後一個值代碼前面的這個鍵值對出現的次數,其實就是統計屬于某個類别的實際檔案個數以及預測對的檔案個數,分别對應上面的total和total_right變量;輸出結果為:

(4,6,3)

(1,6,4)

(2,6,4)

發現其列印的結果是正确的,第一列代表檔案名開頭,第二個代表屬于這個檔案的個數,第三列代表預測正确的個數

這裡需要注意的是,這裡因為文本的實際類别和檔案名是一緻的,是以才可以這樣處理,如果實際資料的話,那麼mapPartitions函數需要更改。

  1. 針對資料結果進行統計:

    最後隻需要進行簡單的計算即可:

Spark應用HanLP對中文語料進行文本挖掘--聚類

輸出結果為:

Spark應用HanLP對中文語料進行文本挖掘--聚類
  1. 實驗

    設定不同的numFeature,比如使用200和2000,其對比結果為:

Spark應用HanLP對中文語料進行文本挖掘--聚類

是以設定numFeatures值越大,其準确率也越高,不過計算也比較複雜。

  1. 總結
  2. HanLP的使用相對比較簡單,這裡隻使用了分詞及停用詞,感謝開源;
  3. Spark裡面的TF-IDF以及Word2Vector使用比較簡單,不過使用這個需要先分詞;
  4. 這裡是在IDEA裡面運作的,如果使用Spark-submit的送出方式,那麼需要把hanpl的jar包加入,這個有待驗證;

文章來源于fansy1990的部落格

繼續閱讀