中文分詞算法 之 詞典機制性能優化與測試

在以前的兩篇博文中文分詞算法 之 基於詞典的正向最大匹配算法中文分詞算法 之 基於詞典的逆向最大匹配算法中,咱們對分詞實現詞典實現都作了優化,本文對詞典實現作進一步優化,並和以前的多個實現作一個對比,使用的詞典下載地址,使用的測試文本下載地址java

 

優化TrieV3的關鍵在於把虛擬根節點(/)的子節點(詞表首字母)提高爲多個相互獨立的根節點,並對這些根節點創建索引。優化的依據是根節點(詞表首字母)的數量龐大,索引查找的速度遠遠超過二分查找git

 

下面看看進一步優化後的TrieV4和以前的TrieV3的對比:github



    /**
     * 獲取字符對應的根節點
     * 若是節點不存在
     * 則增長根節點後返回新增的節點
     * @param character 字符
     * @return 字符對應的根節點
     */
    private TrieNode getRootNodeIfNotExistThenCreate(char character){
        TrieNode trieNode = getRootNode(character);
        if(trieNode == null){
            trieNode = new TrieNode(character);
            addRootNode(trieNode);
        }
        return trieNode;
    }
    /**
     * 新增一個根節點
     * @param rootNode 根節點
     */
    private void addRootNode(TrieNode rootNode){
        //計算節點的存儲索引
        int index = rootNode.getCharacter()%INDEX_LENGTH;
        //檢查索引是否和其餘節點衝突
        TrieNode existTrieNode = ROOT_NODES_INDEX[index];
        if(existTrieNode != null){
            //有衝突,將衝突節點附加到當前節點以後
            rootNode.setSibling(existTrieNode);
        }
        //新增的節點老是在最前
        ROOT_NODES_INDEX[index] = rootNode;
    }
    /**
     * 獲取字符對應的根節點
     * 若是不存在,則返回NULL
     * @param character 字符
     * @return 字符對應的根節點
     */
    private TrieNode getRootNode(char character){
        //計算節點的存儲索引
        int index = character%INDEX_LENGTH;
        TrieNode trieNode = ROOT_NODES_INDEX[index];
        while(trieNode != null && character != trieNode.getCharacter()){
            //若是節點和其餘節點衝突,則須要鏈式查找
            trieNode = trieNode.getSibling();
        }
        return trieNode;
    }

 

 不一樣的字符可能會映射到同一個數組索引(映射衝突),因此須要給TrieNode增長一個引用sibling,當衝突發生的時候,可利用該引用將多個衝突元素連接起來,這樣,在一個數組索引中就能存儲多個TrieNode。若是衝突大量發生,不但會浪費已經分配的數組空間,並且會引發查找性能的降低,好在這裏根節點的每一個字符都不同,衝突發生的狀況很是少。咱們看看詞數目爲427451的詞典文件的衝突狀況:算法

 

衝突次數爲:1 的元素個數:2746
衝突次數爲:2 的元素個數:1
衝突次數:2748
總槽數:12000
用槽數:9024
使用率:75.2%
剩槽數:2976

 

 

 



 


 

將詞典文件和測試文本解壓到當前目錄下,使用下面的命令進行測試須要注意的是,這裏的-Xmx參數指定的值是相應的詞典實現所須要的最小的堆空間,若是再小就沒法完成分詞數組

 

nohup java -Ddic.class=org.apdplat.word.dictionary.impl.TrieV4 -Xmx40m  -cp target/word-1.0.jar org.apdplat.word.SegFile &
nohup java -Ddic.class=org.apdplat.word.dictionary.impl.TrieV3 -Xmx40m  -cp target/word-1.0.jar org.apdplat.word.SegFile &
nohup java -Ddic.class=org.apdplat.word.dictionary.impl.TrieV2 -Xmx40m  -cp target/word-1.0.jar org.apdplat.word.SegFile &
nohup java -Ddic.class=org.apdplat.word.dictionary.impl.TrieV1 -Xmx120m  -cp target/word-1.0.jar org.apdplat.word.SegFile &
nohup java -Ddic.class=org.apdplat.word.dictionary.impl.Trie -Xmx200m  -cp target/word-1.0.jar org.apdplat.word.SegFile &
nohup java -Ddic.class=org.apdplat.word.dictionary.impl.HashSet -Xmx50m  -cp target/word-1.0.jar org.apdplat.word.SegFile &

 

測試結果以下:性能



 



 



 


 

 

代碼託管於GITHUB測試

 

參考資料:優化

一、中文分詞十年回顧spa

二、中文信息處理中的分詞問題code

三、漢語自動分詞詞典機制的實驗研究

四、由字構詞_中文分詞新方法

五、漢語自動分詞研究評述

 

NUTCH/HADOOP視頻教程

相關文章
相關標籤/搜索