這裏介紹一種分詞的方法--最大機率分詞,也叫1-gram分詞,由於它不考慮上下文關係,只考慮當前詞的機率。python
咱們須要有一個詞典,裏面記錄每一個詞的頻次,好比:app
基於這個詞典,咱們能夠將一句話用一個有向無環圖(DAG)的表示出來,好比ui
這個圖裏面,每一個節點是一個字,邊爲兩點構成詞的機率。分詞的問題,就是找出這個DAG裏面機率和最大的一條從開始到結束覆蓋全部字的路徑。好比,辣-》菜,五-》肉,蓋-》飯是一條路徑,辣-》辣,白-》菜,五-》花,肉-》肉,蓋-》飯也是一條路徑,如何找到最大的那條呢?spa
設\(\alpha_i\)爲DAG中以i節點開始以後的部分的最優路徑的累計機率,j爲i的鄰接點,那麼容易的出\(\alpha_i = max_jp(w(i,j))\alpha_{j+1}\),w(i,j)是句子中i開始j結束的詞。code
這是一個動態規劃問題,從最後一個字開始,基於之前的計算結果,逐步向前推移,直到第一個點,而後再從前日後獲得最優路徑。blog
python代碼以下:get
def build_DAG(sentence): DAG = {} #dict,key是每一個word的index,value是以這個字開始可以構成的詞list N = len(sentence) for k in xrange(N): tmp = [] i = k piece = sentence[k] while i < N and piece in dict.FREQ: if dict.FREQ[piece]: tmp.append(i) i += 1 piece = sentence[k:i + 1] if not tmp: tmp.append(k) DAG[k] = tmp return DAG
def calc_route(sentence, DAG, route): N = len(sentence) route[N] = (0, 0) logtotal = log(total_freq) for idx in xrange(N - 1, -1, -1): route[idx] = max((log(dict.FREQ.get(sentence[idx:x + 1]) or 1) - logtotal + route[x + 1][0], x) for x in DAG[idx])
def __cut_DAG(self, sentence): DAG = build_DAG(sentence) route = {} calc_route(DAG, route) x = 0 N = len(sentence) segs = [] while x < N: y = route[x][1] + 1 word = sentence[x,y] segs.append(word) x = y