分裂高棉语的可行解决方案?

时间:2011-02-01 10:48:51

标签: python nlp word-boundary text-segmentation southeast-asian-languages

我正在研究将高棉语(柬埔寨语)的长行分成单个单词(UTF-8)的解决方案。高棉语不会在单词之间使用空格。有一些解决方案,但它们远远不够(herehere),而且这些项目已被淘汰。

以下是需要拆分的高棉样本行(它们可能比这更长):

  

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

创建分裂高棉语单词的可行解决方案的目标有两个:它会鼓励那些使用高棉遗留(非Unicode)字体的人转换为Unicode(这有很多好处),并且它将启用传统的高棉字体要导入到Unicode中以便快速使用拼写检查器(而不是手动浏览和拆分带有大文档的单词,这可能需要很长时间)。

我不需要100%的准确度,但速度很重要(特别是因为需要分成高棉语的行可能很长)。 我愿意接受建议,但目前我有一大堆高棉语单词正确分割(有一个不间断的空格),我创建了一个单词概率词典文件(frequency.csv)作为字典用于分词器。

我发现这个使用here的python代码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()))

我也尝试过使用本页作者的源代码:Text segmentation: dictionary-based word splitting但它运行得太慢而无法使用(因为我的单词概率词典有超过100k的术语......)。

这是py Detect most likely words from text without spaces / combined words中的另一个选项:

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'])

对于python我是一个新手,我对所有真正的编程(网站之外)都是新手,所以请耐心等待。有没有人有任何他们认为会有效的选择?

3 个答案:

答案 0 :(得分:3)

ICU库(具有Python和Java绑定)具有可用于此的DictionaryBasedBreakIterator类。

答案 1 :(得分:1)

示例filesaveas的python似乎会递归整个输入字符串(for i in xrange(1, len(text) + 1)),并在此过程中将最佳结果填入cache;在每个潜在的单词中,然后开始查看下一个单词(后面会依次查看单词,依此类推),如果第二个单词没有看起来很好,它不会保存那个特定的。它感觉就像O(N!)运行时一样,其中N是输入字符串的长度。

超级聪明,但除了简单的任务外,其他任何事情都可能很糟糕。你有多长的高棉词是什么?我希望&lt; 20个字符。

也许如果你一次向该示例中输入20个字符的输入,则可以将运行时间保持在接近合理的范围内。输入前20个字符,取出第一个字,然后输入剩余的输入。如果您重新使用缓存,它可能会做一些愚蠢的事情,就像在途中存储部分单词一样。

在完全不同的方面,通过连接两个或更多合法的高棉语,形成了多少高棉语? (类似于'小刀'或'篮球')如果不是太多,创建一组词典可能是有意义的,按词的长度分隔,从单词到使用概率的映射。

说,最长的高棉语是14个字符长;将14个字符的输入输入len14字典,存储概率。将{13}字符输入len13,存储概率。输入12个字符...一直到1 len1。然后选择具有最高概率的解释,保存单词,剥去那么多字符,然后再试一次。

因此,对于像“我”和“图像”这样的输入,它不会失败,可能更长的输入会自动夸大概率吗?

感谢有趣的问题;)我不知道这样的任何语言,非常酷。

答案 2 :(得分:1)

我认为这是个好主意。

我建议你,当你有一些经验时,你会添加一些规则,这些规则可能非常具体,例如,取决于之前的单词,取决于单词之后,取决于周围的单词,取决于单词序列在当前的词之前,只是列举最频繁的词。您可以在gposttl.sf.net项目中找到一组规则,这是一个pos标记项目,位于文件data / contextualrulefile中。

统计评估完成后应使用规则,进行微调,可以显着提高准确性。