15

私は、クメール語 (カンボジア語) の長い行を個々の単語 (UTF-8) に分割するソリューションに取り組んでいます。クメール語では単語間にスペースを使用しません。そこにはいくつかの解決策がありますが、それらは十分ではなく (ここここ)、それらのプロジェクトは途中で失敗しました。

分割する必要があるクメール語のサンプル行を次に示します (これよりも長くなる可能性があります)。

ចូរសរសើរដល់ទ្រង់ដល់ទ្រង់ដែលបានប្រទានប្រទានការនោះទាំងអស់អ្នកដោយដោយព្រោះអង្គហើយហើយអ្នកមិនអាចមិនអាចការ

クメール語の単語を分割する実行可能なソリューションを作成するという目標は 2 つあります。クメール語の従来の (非 Unicode) フォントを使用していたユーザーが Unicode に変換することを奨励し (多くの利点があります)、従来のクメール語フォントをインポートできるようにすることです。 Unicode に変換して、スペル チェックですばやく使用できるようにします (大きなドキュメントでは非常に長い時間がかかる手動で単語を調べて分割するのではなく)。

100% の精度は必要ありませんが、速度は重要です (特に、クメール語に分割する必要がある行はかなり長くなる可能性があるため)。私は提案を受け入れますが、現在、正しく分割された (改行なしのスペースで) クメール語の大きなコーパスがあり、単語確率辞書ファイル (frequency.csv) を作成して、ワードスプリッター。

Viterbi アルゴリズムを使用するこのpython コードを見つけました。おそらく高速に実行されます。

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 コードを使用してみました:テキスト セグメンテーション: 辞書ベースの単語分割ですが、速度が遅すぎて役に立ちませんでした (私の単語確率辞書には 10 万以上の用語があるため...)。

そして、スペース/結合された単語を含まないテキストから最も可能性の高い単語を検出するからの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'])

私はPythonに関しては初心者であり、(Webサイト以外の)すべての実際のプログラミングに本当に慣れていないので、ご容赦ください。うまくいくと思うオプションを持っている人はいますか?

4

3 に答える 3

3

ICU ライブラリ ( Pythonおよび Java バインディングを含む) には、これに使用できるDictionaryBasedBreakIteratorクラスがあります。

于 2011-02-01T11:25:39.673 に答える
1

このままでいいと思います。

経験があれば、非常に具体的なルールを追加することをお勧めします。たとえば、前の単語に応じて、後の単語に応じて、周囲の単語に応じて、現在の単語の前の一連の単語に応じて、などです。最も頻繁なものを列挙するだけです。ファイル data/contextualrulefile で、pos タグ付けプロジェクトである gposttl.sf.net プロジェクトの一連のルールを見つけることができます。

ルールは、統計の評価が終了した後に使用する必要があります。ルールは微調整を行い、精度を大幅に向上させることができます。

于 2011-02-02T21:16:41.767 に答える
1

python with examplefilesaveasは、入力文字列全体 ( ) を再帰的に処理しているように見え、途中for i in xrange(1, len(text) + 1)で最良の結果を詰め込んでいます。cache可能性のある単語ごとに、次の単語の検索開始し(の単語も同様に検索します)、2 番目の単語が適切に表示されない場合は、その特定の単語を保存しません。 . O(N!) ランタイムのように感じます。N は入力文字列の長さです。

非常に賢いですが、単純なタスク以外ではおそらくひどいものです。あなたが持っている最も長いクメール語は何ですか? 20文字未満でお願いします。

おそらく、その例に一度に 20 文字ずつ入力すると、ランタイムを妥当な値に近づけることができます。最初の 20 文字をフィードし、最初の単語を読み込んでから、残りの入力をフィードします。キャッシュを再利用すると、途中で部分的な単語を保存するなど、ばかげたことが行われる可能性があります。

まったく別の見方をすれば、2 つ以上の合法的なクメール語を連結して形成されるクメール語はいくつあるでしょうか? ('penknife' や 'basketball' に似ています) あまり多くない場合は、単語の長さで区切られた一連の辞書を作成し、単語から使用確率にマッピングするのが理にかなっているかもしれません。

たとえば、最長のクメール語は 14 文字の長さです。14 文字の入力をlen14辞書にフィードし、確率を格納します。に 13 文字をフィードしlen13、確率を格納します。12 文字を入力してください... 1 までlen1. 次に、最も確率の高い解釈を選択し、単語を保存し、その数の文字を削除して、もう一度試してください。

したがって、「I」と「Image」のような入力でひどく失敗することはありません。長い入力では、確率が自動的に膨らむはずですか?

楽しい質問をありがとう ;) 私はこのような言語を知りませんでした。

于 2011-02-01T11:42:34.380 に答える