1

私は現在Goを学んでおり、多くの進歩を遂げています。これを行う 1 つの方法は、過去のプロジェクトとプロトタイプを以前の言語から新しい言語に移植することです。

今は、少し前に Python でプロトタイプを作成した「言語検出器」で忙しくしています。このモジュールでは、ngram 頻度表を生成し、そこで特定のテキストと既知のコーパスとの差異を計算します。

これにより、指定された ngram テーブルの 2 つのベクトル表現のコサインを返すことで、どのコーパスが最も一致するかを効果的に判断できます。わーい。算数。

Go で書かれたプレーンな ASCII 文字で完全に動作するプロトタイプを持っていますが、Unicode マルチバイト サポートで動作するようにしたいと考えています。これは私が頭を悩ませているところです。

ここに私が扱っているものの簡単な例があります: http://play.golang.org/p/2bnAjZX3r0

すべてがすでに正常に機能しているため、テーブル生成ロジックのみを投稿しました。

スニペットを実行するとわかるように、最初のテキストは非常にうまく機能し、正確な表が作成されます。2 番目のテキストはドイツ語で、2 バイト文字がいくつか含まれています。私が ngram シーケンスを構築している方法と、これらの特定のルーンが 2 バイトで構成されているという事実により、最初のバイトが切り取られた 2 つの ngram が表示されます。

誰かがより効率的な解決策を投稿したり、少なくとも修正を案内してくれたりできますか? 私はこの問題を分析しすぎているとほぼ確信しています。

私はこのパッケージをオープン ソース化し、Martini を使用してサービスとして実装することを計画しています。これにより、人々が単純な言語計算に使用できる単純な API を提供します。

いつものように、ありがとう!

4

2 に答える 2

1

ルーンの循環バッファーを保持することで、割り当てを最小限に抑えることができます。また、マップから新しいキーを読み取るとゼロ値 (int の場合は 0) が返されることにも注意してください。これは、コード内の不明なキー チェックが冗長であることを意味します。

func Parse(text string, n int) map[string]int {
    chars := make([]rune, 2 * n)
    table := make(map[string]int)
    k := 0
    for _, chars[k] = range strings.Join(strings.Fields(text), " ") + " " {
        chars[n + k] = chars[k]
        k = (k + 1) % n
        table[string(chars[k:k+n])]++
    }
    return table
}
于 2013-12-26T14:04:41.737 に答える
1

私が正しく理解していればcharsParse関数で文字列の最後の文字を保持する必要がnあります。UTF-8 表現ではなく Unicode 文字に関心があるため、それを[]runeスライスとして管理し、ngram をテーブルに追加する準備ができたときにのみ文字列に変換する方が簡単だと思うかもしれません。このようにして、ロジック内で非 ASCII 文字を特殊なケースにする必要はありません。

上記を実行するサンプル プログラムの簡単な変更を次に示します: http://play.golang.org/p/QMYoSlaGSv

于 2013-12-26T06:43:50.277 に答える