1. 程式人生 > >n-gram統計 計算句子概率 SRILM安裝使用

n-gram統計 計算句子概率 SRILM安裝使用

不是非要寫一篇的,是這個網上太少了,而且貌似也沒有其他工具來做這項工作了。因此本文主要寫怎麼使用SRILM統計n-gram,並使用該工具得到的語言模型進行句子概率的計算。當然如果有更好的工具請大家一定要推薦一下。

1、安裝

安裝官方寫的很簡單,遇到問題,又很少有解答的,難道其他人都一次性安裝成功了嗎。

環境:unbuntu16.04 64bit

1.1 下載

1.2安裝依賴

  1.C/C++ compiler:編譯器gcc 3.4.3及以上版本
  2.GNU make:構建和管理工程的工具,解釋Makefile裡的指令,描述了整個工程所有檔案的編譯順序和編譯規則。這裡是為了控制 SRILM 的編譯和安裝
  3.GNU gawk:GNU所做的awk程式語言。對於文字資料的修改,對比,抽取等處理,使用c或passcal等不方便且費時,awk 能夠以很短的程式完成。這裡是處理SRILM裡的一些指令碼檔案
  4.GNU gzip:使用C語言編寫的一種解壓縮軟體。這裡是為了使 SRILM 能夠處理.Z和.GZ字尾的壓縮檔案
  5.bzip2:資料壓縮軟體,壓縮效率更高。這裡是使SRILM能處理.bz2字尾的壓縮檔案
  6.p7zip:資料壓縮軟體。這裡是使SRILM能處理7-Zip的壓縮檔案
  7.csh:Unix shell的一種 特別注意我就是這個沒有安裝,找了一下午問題。
檢視是否安裝以上依賴,簡單的辦法就是在命令列下輸入命令,比如“csh”,
最好要測試一下,因為貌似make報錯不顯示那個依賴沒有安裝。

csh

1.3 修改配置檔案

   主目錄下修改Makefile檔案
   1.找到:

     # SRILM = /home/speech/stolcke/project/srilm

     另起一行輸入 SRILM 的安裝路徑 SRILM = $(PWD)

    2.找到:
     通過 uname -m 命令可以看到我的機器架構是x86_64

     MACHINE_TYPE := (shell(SRILM)/sbin/machine-type)

     在其前加#註釋掉,並另起一行輸入:

     MACHINE_TYPE := i686-m64

    用編輯器修改 srilm/common/Makefile.machine.i686-m64

   1.找到:

     TCL_INCLUDE =

     TCL_LIBRARY =

     修改為

     TCL_INCLUDE =

     TCL_LIBRARY =

     NO_TCL = X  

    2.找到:

     GAWK = /usr/bin/awk

     修改為

     GAWK = /usr/bin/gawk

1.4.安裝SRILM並測試

    1.編譯 SRILM

     make World

    2.修改環境變數

     執行命令 export PATH=/home/moses/tools/srilm/bin/i686-m64:/home/moses/tools/srilm/bin:$PATH

    3.測試

     編譯通過不等於編譯成功,必須利用 SRILM 提供的測試模組進行測試,進入 SRILM 根目錄

     make test

2 SRILM使用

SRILM工具包的有兩個核心模組,一個是利用訓練資料構建語言模型,是ngram-count模組,另一個是對語言模型進評測(計算測試集困惑度),是ngram模組。

2.1. ngram-count

對於ngram-count模組,有很多的計數功能,可以單獨生成訓練語料的計數檔案,然後可以讀取計數檔案構建語言模型,也可以兩步一起做。

假設語料庫的名字是train.data,如下:

it ‘s just down the hall . I ‘ll bring you some now . if there is anything else you need , just let me know .
No worry about that . I ‘ll take it and you need not wrap it up .
Do you do alterations ?
the light was red .
we want to have a table near the window .
it ‘s over there , just in front of the tourist information .
I twisted it playing tennis . it felt Okay after the game but then it started turning black - and - blue . is it serious ?
please input your pin number .

1.計數功能——生成計數檔案

命令:

ngram-count -text train.data -order 3 -write train.data.count

其中text指向的後邊是輸入檔案, order 3是3元語法到意思,-write後跟到是輸出到計數檔案,如果不指定-order選項的話,預設是3元語法。

從rain.data.count得到的部分結果如下:

please 1
please input 1
please input your 1
<s> 8
<s> it 2
<s> it 's 2
<s> the 1
<s> the light 1
<s> we 1
<s> we want 1
…...
up 1
up . 1
up . </s> 1
Do 1
Do you 1
Do you do 1

這裡的分別表示句子的開始和結束,計數檔案的格式是:

a_z c(a_z)

a_z:a表示n元語法的第一個詞,z表示最後一個詞,_表示在a和z之間的0個或多個詞
c(a_z):表示a_z在訓練語料中的計數

2.從計數檔案構建語言模型

命令:

ngram-count -read train.data.count -order 3 -lm train.lm

其中引數-read指向輸入檔案,此處為 train.data.count ;-order與上同;-lm指向訓練好的語言模型輸出檔案,此處為train.lm,此命令為後面可以接具體的打折演算法,和後退或插值相結合,比如後面接-interpolate -kndiscount,其中-interpolate為插值平滑,-kndiscount為 modifiedKneser-Ney 打折法,如果不指定的話,預設使用Good-Turing打折和Katz退避演算法,這裡使用預設。

train.lm檔案部分結果如下:

\data\
ngram 1=75
ngram 2=106
ngram 3=2

\1-grams:
-1.770852 ‘ll -0.03208452
-1.770852 ‘s -0.02453138
-1.770852 , -0.4659371
-1.770852 - -0.02832437
-1.030489 . -0.5141692

……

\2-grams:
-1.361728 ‘ll bring
-1.361728 ‘ll take
-1.361728 ‘s just
-1.361728 ‘s over
-0.1760913 , just
-1.361728 - and
-1.361728 - blue

……
\3-grams:
-0.1760913 . I ‘ll
-0.1760913 it ‘s

其中檔案格式:
log10(f(a_z)) a_z log10(bow(a_z))

注:f(a_z)是條件概率即P(z|a_),bow(a_z)是回退權重

第一列表示以10為底對數的條件概率P(z|a_),第二列是n元詞,第三列是以10為底的對數回退權重(它為未看見的n+1元詞貢獻概率)

3.直接結合上面兩步

一般的直接利用訓練語料構建語言模型,即結合上面兩部,命令如下:

ngram-count -text train.data -lm train.lm

這裡沒寫-order,預設是3,沒指定打折演算法,預設使用Good-Turing打折和Katz退避演算法

2.2. n-gram模組測試集困惑度

假設測試集為test.data,如下:

we want to have a table near the window .
read a list of sentence .

先用如下命令:

ngram -ppl test.data -order 3 -lm train.lm

引數-ppl有兩個主要任務,一是計算句子對數概率(log10P(T),其 中P(T)為所有句子的概率乘積)二是計算測試集困惑度,有兩個指標ppl, 和ppl1

在終端上得到輸出結果:
file test.data: 2 sentences, 16 words, 3 OOVs
0 zeroprobs, logprob= -17.9098 ppl= 15.6309 ppl1= 23.8603

輸出資訊的第一行:2個句子,16單詞,3個未登入詞;
輸出資訊的第二行:無零概率,logP(T)=-17.9098,ppl= 15.6309 ppl1= 23.8603
其中ppl和ppl1分別計算如下(這裡參考自http://www.52nlp.cn/language-model-training-tools-srilm-details):

ppl=10^{-{logP(T)}/{Sen+Word}};ppl1=10^{-{logP(T)}/Word}
其中Sen和Word分別代表句子和單詞數。

在原來命令基礎上如果想要得到更詳細的輸出資訊,可以加選項-debug 0-4,-debug 0對應這裡的預設情況。比如用ngram -ppl test.data -order 3 -lm train.lm -debug 1,終端上得到輸出資訊如下:
reading 75 1-grams
reading 106 2-grams
reading 2 3-grams
we want to have a table near the window .
1 sentences, 10 words, 0 OOVs
0 zeroprobs, logprob= -12.4723 ppl= 13.6096 ppl1= 17.6697

read a list of sentence .
1 sentences, 6 words, 3 OOVs
0 zeroprobs, logprob= -5.43749 ppl= 22.8757 ppl1= 64.9379

file test.data: 2 sentences, 16 words, 3 OOVs
0 zeroprobs, logprob= -17.9098 ppl= 15.6309 ppl1= 23.8603