0

次のような構造の、数字と単語シーケンスを含む行で構成される入力ファイルがあります。

\1-grams:
number   w1    number
number   w2    number
\2-grams:
number   w1 w2   number
number   w1 w3   number
number   w2 w3   number
\end\

一意の n グラムごとに両方の数値を簡単に取得できるように、単語シーケンス (いわゆる n グラム) を保存したいと考えています。私が今していることは、次のとおりです。

all = {}
ngrams = {}
for line in open(file):
    m = re.search('\\\([1-9])-grams:',line.strip()) # find nr of words in sequence
    if m != None:
        n = int(m.group(1))
        ngrams = {} # reinitialize dict for new n
    else:
        m = re.search('(-[0-9]+?[\.]?[0-9]+)\t([^\t]+)\t?(-[0-9]+\.[0-9]+)?',line.strip()) #find numbers and word sequence
        if m != None:
            ngrams[m.group(2)] = '{0}|{1}'.format(m.group(1), m.group(3))
        elif "\end\\" == line.strip():
            all[int(n)] = ngrams

このようにして、たとえばシーケンス s='w1 w2' の数字を簡単かつ迅速に見つけることができます。

all[2][s]

問題は、このストアド プロシージャがかなり遅いことです。特に、n グラムが多数 (> 100k) あり、アクセス速度を低下させずに同じ結果を達成するためのより高速な方法があるかどうか疑問に思っています。ここで次善の策を講じていますか? どこを改善できますか?

前もって感謝します、

ヨリス

4

3 に答える 3

6

正規表現の検索を少なくしてみます。

他にもいくつかのことを検討する価値があります。

  • すべてのデータを 1 つのディクショナリに格納すると、速度が向上する場合があります。おそらく直観に反して、余分なレイヤーを含むデータ階層は役に立ちません。

  • タプルを格納すると、呼び出しを避けることができます.format()

  • CPython では、関数内のコードはグローバル コードよりも高速です。

これは次のようになります。

def load(filename):
    ngrams = {}
    for line in open(filename):
        if line[0] == '\\':
            pass  # just ignore all these lines
        else:
            first, rest = line.split(None, 1)
            middle, last = rest.rsplit(None, 1)
            ngrams[middle] = first, last
    return ngrams

ngrams = load("ngrams.txt")

int(first), int(last)ではなく保管したいですfirst, last。これにより、アクセスが高速化されますが、ロード時間が遅くなります。したがって、それはあなたのワークロードに依存します。

私は johnthexii に同意しません。Python でこれを行うと、データ セットがメモリに収まる限り、SQLite でさえデータベースと対話するよりもはるかに高速になるはずです。(データベースを使用している場合は、ロードを 1 回行うだけでそれを繰り返す必要がないことを意味します。そのため、sqlite はまさに目的どおりになる可能性がありますが、:memory: データベースではそれができません。)

于 2013-06-27T14:47:53.313 に答える
3

コードの最適化について。

1) ループの前に正規表現をコンパイルします。re.compile のヘルプを参照してください。

2) 可能な限り正規表現を使用しないでください。たとえば、数字が前に付いた「-grams」文字列は、単純な文字列比較で確認できます

于 2013-06-27T14:51:07.730 に答える
0

個人的には、データベースに移動します (sqllite3 は python に組み込まれています) 。インデックスを使用すると、クエリが高速になります。Pythonはメモリ内の sqllite データベースもサポートしています

特別な名前 :memory: を指定して、RAM にデータベースを作成することもできます。

于 2013-06-27T14:40:09.310 に答える