15

我正在研究將長長的高棉語(柬埔寨語)拆分爲單個單詞(UTF-8)的解決方案。高棉語不會在單詞之間使用空格。這裏有一些解決方案,但它們遠遠不夠(herehere),而這些項目已經落後了。分詞高棉的可行解決方案?

這裏是紅色的採樣線需要被分割(它們可以比這個更長):

ចូរសរសើរដល់ទ្រង់ដែលទ្រង់បានប្រទានការទាំងអស់នោះមកដល់រូបអ្នកដោយព្រោះអង្គព្រះយេស៊ូវហើយដែលអ្នកមិនអាចរកការទាំងអស់នោះដោយសារការប្រព្រឹត្តរបស់អ្នកឡើយ。

創建拆分高棉話可行的解決方案的目標是雙重的:它會鼓勵那些誰使用高棉傳統的(非Unicode)的字體,在轉換爲Unicode(它有很多好處),它將使傳統的高棉字體被導入到Unicode中,以便與拼寫檢查器一起使用(而不是手動檢查和分割帶有大型文檔的文字可能需要很長時間的文字)。

我不需要100%的準確性,但速度很重要(尤其是因爲需要拆分成高棉語的線路可能會很長)。 我很樂意提供建議,但目前我有一個高分辨率的高棉語語料庫,它可以正確分割(使用非破壞性空間),並且我創建了一個單詞概率詞典文件(frequency.csv)用作詞典詞分離器。

我發現這個Python代碼here,它使用Viterbi algorithm,它應該運行得很快。

import re 
from itertools import groupby 

def viterbi_segment(text): 
    probs, lasts = [1.0], [0] 
    for i in range(1, len(text) + 1): 
     prob_k, k = max((probs[j] * word_prob(text[j:i]), j) 
         for j in range(max(0, i - max_word_length), i)) 
     probs.append(prob_k) 
     lasts.append(k) 
    words = [] 
    i = len(text) 
    while 0 < i: 
     words.append(text[lasts[i]:i]) 
     i = lasts[i] 
    words.reverse() 
    return words, probs[-1] 

def word_prob(word): return dictionary.get(word, 0)/total 
def words(text): return re.findall('[a-z]+', text.lower()) 
dictionary = dict((w, len(list(ws))) 
        for w, ws in groupby(sorted(words(open('big.txt').read())))) 
max_word_length = max(map(len, dictionary)) 
total = float(sum(dictionary.values())) 

我也使用源java代碼從該頁面的作者嘗試:Text segmentation: dictionary-based word splitting,但它運行而沒有任何用途的速度太慢(因爲我的話,概率詞典有10萬項...)。

這裏是從Detect most likely words from text without spaces/combined words Python中的另一種選擇:

WORD_FREQUENCIES = { 
    'file': 0.00123, 
    'files': 0.00124, 
    'save': 0.002, 
    'ave': 0.00001, 
    'as': 0.00555 
} 

def split_text(text, word_frequencies, cache): 
    if text in cache: 
     return cache[text] 
    if not text: 
     return 1, [] 
    best_freq, best_split = 0, [] 
    for i in xrange(1, len(text) + 1): 
     word, remainder = text[:i], text[i:] 
     freq = word_frequencies.get(word, None) 
     if freq: 
      remainder_freq, remainder = split_text(
        remainder, word_frequencies, cache) 
      freq *= remainder_freq 
      if freq > best_freq: 
       best_freq = freq 
       best_split = [word] + remainder 
    cache[text] = (best_freq, best_split) 
    return cache[text] 

print split_text('filesaveas', WORD_FREQUENCIES, {}) 

--> (1.3653e-08, ['file', 'save', 'as']) 

我是一個newbee當談到蟒蛇,我真正的新所有真正的編程(網站外),所以請多多包涵。有沒有人有任何他們認爲會運作良好的選擇?

回答

3

ICU庫(具有Python和Java綁定)具有可用於此的DictionaryBasedBreakIterator類。

+0

@Lennart謝謝 - 是的,我已經看過ICU library DictionaryBasedBreakIterator類 - 但是因爲我在編程經驗上非常有限,所以我無法對它做任何事情。我看到這裏有一些例子:http://source.icu-project.org/repos/icu/icu/trunk/source/samples/break/但是你知道任何Python和Java的例子,會讓我開始(有時我可以編輯一個腳本,如果足夠了)?還是有一些例子,我錯過了... – Nathan 2011-02-01 11:51:11

+0

@Nathan:是的,ICU的Python綁定沒有任何真正的文檔,這是一個恥辱。不,我不知道任何例子,對不起。如果你有一本字典,我可以試着看看能否找出答案。 – 2011-02-01 11:54:59

1

帶有示例filesaveas的python似乎在遞歸整個輸入字符串(for i in xrange(1, len(text) + 1)),沿途填充最好的結果到cache;在每個潛在的單詞中,它然後開始查看下一個單詞(這將反過來看這個單詞,等等),如果第二個單詞看起來不太好,它不會保存那個特定的一個。它感覺像O(N!)運行時,其中N是輸入字符串的長度。

超級聰明,但對於除簡單任務之外的任何事情都可能是可怕的。什麼是你得到的最長的高棉文字?我希望< 20個字符。

也許,如果您向該示例中的輸入提供20個字符,那麼您可以將運行時間降低到接近合理的水平。在前20個字符中輸入,抽出第一個字,然後輸入剩餘的輸入。如果你重新使用緩存,它可能會做一些愚蠢的事情,例如一路上存儲部分單詞。

在完全不同的方式上,連接兩個或更多合法高棉語詞彙形成了多少高棉語? (類似於'小刀'或'籃球')如果不是太多,創建一組字典,按字長分隔,從字映射到使用概率,這可能是有意義的。

說,最長的高棉語是14個字長;輸入14個字符輸入到len14字典中,存儲概率。將13個字符送入len13,存儲概率。以12個字符進行...一直到1到len1。然後選擇具有最高可能性的解釋,保存該單詞,去除多個字符,然後重試。

因此,對於像「我」與「圖像」這樣的輸入,它可能不會失敗,也許更長的輸入應該會自動誇大概率?

感謝有趣的問題;)我不知道這樣的語言,很酷。

1

我認爲這是一個好主意,因爲它是。

我建議你,當你有一些經驗的時候,你可以添加一些規則,這些規則可以是非常具體的,例如,取決於之前的單詞,取決於單詞之後,取決於周圍的單詞,取決於當前單詞前面的單詞,只是爲了列舉出最常見的單詞。您可以在文件data/contextualrulefile中的gposttl.sf.net項目中找到一組規則,這是一個pos標記項目。

規則應該在統計評估完成後使用,它們會進行一些微調,並且可以顯着提高準確性。