coreseek之mmseg分詞和詞庫拓展
mmseg分詞
mmseg分詞演算法是基於統計模型的,所以演算法的規則也是來自對語料庫的分析和數學歸納,因為中文字元沒有明確的分界,會導致大量的字元分界歧義,而且,中文裡面,詞和短語也很難界定,因此,演算法除了要做統計和數學歸納之外,還要做歧義的解決。
在mmseg分詞中,有一個叫chunk的概念:
chunk,是一句話的分詞方式。包括一個詞條陣列和四個規則。
如:研究生命,有“研究/生命”和“研究生/命”兩種分詞方式,這就是兩個chunk。
一個chunk有四個屬性:長度、平均長度(長度/分詞數)、方差、單字自由度(各單詞條詞頻的對數之和)。
下面列出了chunk的4個屬性以及對應的規則:
屬性 |
含義 |
對應規則 |
長度 |
chuck中各個詞的長度之和 |
規則1:取最大匹配的chunk |
平均長度 |
長度/詞數 |
規則2:取平均詞長最大的chunk |
標準差的平方 |
同數學中的定義 |
規則3:取詞長標準差最小的chunk |
單字自由度 |
各單字詞詞頻的對數之和 |
規則4:取單字詞自由語素度之和最大的chunk |
做好分詞之後,會得到多種分詞方式,這時候就要使用一些過濾規則來完成歧義的解決,以得到最終的分詞方式。
歧義解決規則:
1、最大匹配 匹配最大長度的詞。如“國際化”,有“國際/化”、“國際化”兩種分詞方式,選擇後者。
2、最大平均詞長度 匹配平均詞最大的chunk。如“南京市長江大橋”,有“南京市/長江大橋”、“南京/市長/江大橋”三種分詞方式,前者平均詞長度是7/2=3.5,後者是7/3=2.3,故選擇前者的分詞方式。
3、最大方差 去方差最大的chunk。如“研究生命科學”,有“研究生/命/科學”、“研究/生命/科學“兩種分詞方式,而它們的詞長都一樣是2。所以需要繼續過濾,前者方差是0.82,後者方差是0。所以選擇第二種分詞方式。
4、最大單字自由度 選擇單個字出現最高頻率的chunk。比如”主要是因為“,有”主要/是/因為“,”主/要是/因為“兩種分詞方式,它們的詞長、方差都一樣,而”是“的詞頻較高,所以選擇第一種分詞方式。
如果經過上述四個規則的過濾,剩下的chunk仍然大於一,那這個演算法也無能為力了,只能自己寫擴充套件完成。
Chunk中的4個屬性只有在需要該屬性的值時才進行計算,而且只計算一次。
可以將規則理解為一個過濾器,過濾掉不符合要求的chunk。MMSeg分詞演算法中涉及了4個規則:
這4個規則符合漢語成詞的基本習慣。
詳細匹配過程如下:
1)先使用規則1(長度)來過濾chunks,
2)如果過濾後的結果chunk多於或等於2,則使用規則2繼續過濾,否則終止過濾過程。
3)如果使用規則2(平均長度)得到的過濾結果chunk多於或等於2,則使用規則3繼續過濾,否則終止過濾過程。
4)如果使用規則3(標準差的平方)得到的過濾結果chunk多於或等於2,則使用規則4繼續過濾,否則終止過濾過程。
5)如果使用規則 4(單字自由度)得到的過濾結果chunk多於或等於2,則丟擲一個表示歧義的異常,否則終止過濾過程。
最後通過一個例句--“研究生命起源"來簡述一下複雜最大匹配的分詞過程。
MMSeg分詞演算法會得到7個chunk,分別為:
編號 |
chunk |
長度 |
0 |
研_究_生 |
3 |
1 |
研_究_生命 |
4 |
2 |
研究_生_命 |
4 |
3 |
研究_生命_起 |
5 |
4 |
研究_生命_起源 |
6 |
5 |
研究生_命_起 |
5 |
6 |
研究生_命_起源 |
6 |
使用規則1過濾後得到2個chunk,如下:
編號 |
chunk |
長度 |
4 |
研究_生命_起源 |
6 |
6 |
研究生_命_起源 |
6 |
計算平均長度後為:
編號 |
chunk |
長度 |
平均長度 |
4 |
研究_生命_起源 |
6 |
2 |
6 |
研究生_命_起源 |
6 |
2 |
使用規則2過濾後得到2個chunk,如下:
編號 |
chunk |
長度 |
平均長度 |
4 |
研究_生命_起源 |
6 |
2 |
6 |
研究生_命_起源 |
6 |
2 |
計算標準差的平方後為:
編號 |
chunk |
長度 |
平均長度 |
標準差的平方 |
4 |
研究_生命_起源 |
6 |
2 |
0 |
6 |
研究生_命_起源 |
6 |
2 |
4/9 |
使用規則3過濾後得到1個chunk,如下:
編號 |
chunk |
長度 |
平均長度 |
標準差的平方 |
4 |
研究_生命_起源 |
6 |
2 |
0 |
匹配過程終止。最終取“研究”成詞,以相同的方法繼續處理“生命起源”。
詞庫擴充
由於coreseek帶的mmseg預設詞庫有10w多個字詞,搜尋出來的結果準確度不是很理想。花了半天找了下搜尋引擎相關的資料,現在記錄下一些提高搜尋精度的方法和步驟:
1. 基礎詞庫要足夠豐富,因為只有基礎詞庫豐富了,才能談權重設定。
2. 增加相關業務領域的詞彙,進一步提升詞庫量,如果不是做綜合搜尋,一般都只需要提高自身業務領域的詞彙。
3. 記錄與收集使用者搜尋,把搜尋記錄高的作為新增詞彙加入到詞庫中(前提是詞庫中不存在這個詞)。
如果要豐富基礎詞庫,詞庫可以去搜狗拼音官網下載。使用工具轉換為txt 明文格式文字。使用指令碼和工具統一處理成mmseg匯入格式(如:單詞\t1\r\nx:1\r\n)。
執行指令碼處理過程如下(WordsProcess.sh):
#"過濾英文字元和空格和回車鍵
filenum=`find ./data -type f -name *.txt|wc -l`
if [ $filenum == 0 ]
then
echo "no input file"
exit 0
fi
echo "input file num $filenum"
find ./data -type f -name "*.txt"|xargs sed -i "s/[A-Za-z' \r]//g"
#替換回車字元為換行字元 find./data -name "*.txt" |xargs sed -i 's/\r/\n/g'
#txt格式的檔案需要先轉換為 .in結尾的檔案
echo "change txt to in"
for file in $(find ./data -type f -name"*.txt")
do
echo"change $file"
tmpfile=`echo$file|cut -d . -f 2`
echo"tmpfile $tmpfile"
echo"mv $file ./${tmpfile}.in"
mv$file "./${tmpfile}.in"
done
#執行產生輸出檔案
find . -type f -name"*.out"|xargs -i rm {}
echo "execute coreseekTool.sh"
./coreseekTool.sh
echo "wait for coreseekTool to outputfiles"
sleep 10
#拷貝輸出檔案
test ./data/總體.out &&sudo cp ./data/總體.out /usr/local/mmseg3/etc/total.out && echo "cp./data/總體.out /usr/local/mmseg3/etc/total.out"
ls -l /usr/local/mmseg3/etc/total.out
#生成詞庫
sudo /usr/local/mmseg3/bin/mmseg -u/usr/local/mmseg3/etc/total.out && echo "sudo/usr/local/mmseg3/bin/mmseg -u /usr/local/mmseg3/etc/total.out"
ls -l /usr/local/mmseg3/etc/total.out.uni
#修改產生的二進位制詞庫名
echo "change wordlib name"
test /usr/local/mmseg3/etc/total.out.uni&& sudo cp /usr/local/mmseg3/etc/total.out.uni /usr/local/mmseg3/etc/uni.lib
ls -l /usr/local/mmseg3/etc/uni.lib
#重新生成索引
searchd_port=9312
running_im_pid=`sudo netstat -apn2>>/dev/null | grep -w $searchd_port | grep searchd | awk -F/'/^tcp/{print $1}' | awk '/LISTEN/{print $NF}'`
echo "running_im_pid:$running_im_pid"
if [ -z "$running_im_pid" ]
then
#如果searchd未啟動,執行索引:
echo "/usr/local/coreseek/bin/indexer -c/usr/local/coreseek/etc/sphinx.conf --all"
sudo /usr/local/coreseek/bin/indexer -c/usr/local/coreseek/etc/sphinx.conf --all
else
#如果searchd已啟動,執行索引:
echo "/usr/local/coreseek/bin/indexer -c/usr/local/coreseek/etc/sphinx.conf --all --rotate"
sudo /usr/local/coreseek/bin/indexer -c/usr/local/coreseek/etc/sphinx.conf --all --rotate
fi
sleep 1
echo "show indexs"
ls -l --color=tty/usr/local/coreseek/var/data/answer_main_index
ls -l --color=tty/usr/local/coreseek/var/data/answer_rotate_index
#測試
echo "testing search"
/usr/local/coreseek/bin/search -c/usr/local/coreseek/etc/sphinx.conf -p 吃飯
目前使用的搜狗官方的中文詞庫,轉換後的檔案如下: