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标记项目。

规则应该在统计评估完成后使用,它们会进行一些微调,并且可以显着提高准确性。