3

与えられた入力コレクションの n グラムを遅延シーケンスとして返す関数を実装しました。

(defn gen-ngrams
  [n coll]
  (if (>= (count coll) n)
    (lazy-seq (cons (take n coll) (gen-ngrams n (rest coll))))))

より大きな入力コレクションでこの関数を呼び出すと、実行時間が直線的に増加することが予想されます。ただし、私が観察するタイミングはそれよりも悪いです。

user> (time (count (gen-ngrams 3 (take 1000 corpus))))
"Elapsed time: 59.426 msecs"
998
user> (time (count (gen-ngrams 3 (take 10000 corpus))))
"Elapsed time: 5863.971 msecs"
9998
user> (time (count (gen-ngrams 3 (take 20000 corpus))))
"Elapsed time: 23584.226 msecs"
19998
user> (time (count (gen-ngrams 3 (take 30000 corpus))))
"Elapsed time: 54905.999 msecs"
29998
user> (time (count (gen-ngrams 3 (take 40000 corpus))))
"Elapsed time: 100978.962 msecs"
39998

corpusCons文字列トークンの です。

この動作の原因と、パフォーマンスを改善するにはどうすればよいですか?

4

2 に答える 2

5

あなたの問題は、ngramsへの呼び出しごとにcollを反復している「(count coll)」にあると思います。

解決策は、組み込みのパーティション関数を使用することです。

user=> (time (count (gen-ngrams 3 (take 20000 corpus))))
"Elapsed time: 6212.894932 msecs"
19998
user=> (time (count (partition 3 1 (take 20000 corpus))))
"Elapsed time: 12.57996 msecs"
19998

実装に興味がある場合は、パーティションのソースを見てください http://clojuredocs.org/clojure_core/clojure.core/partition

于 2012-05-12T20:36:12.500 に答える
0

私は Clojure の専門家ではありませんが、cons 関数がこの問題を引き起こしていると思います。代わりにリストを使用してみてください:

(defn gen-ngrams
  [n coll]
  (if (>= (count coll) n)
    (lazy-seq (list (take n coll) (gen-ngrams n (rest coll))))))

cons は、リストよりも一般的な新しい seq を構築するため、遅くなると思います。

編集:そして、「コーパスが文字列トークンの短所である」場合は、それをリストにしてみてください...

于 2012-05-12T17:38:46.970 に答える