質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

4回答

3077閲覧

cythonでfor文を速くしたい

kohekoh

総合スコア140

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

2クリップ

投稿2017/07/26 14:51

編集2017/07/27 07:21

以下のようなコードがあります

python

1import nltk 2 3def tfidf(word): 4 collection = nltk.TextCollection(word) #サイトにのっていた 5 doc = [] 6 cdef float a 7 cdef str term 8 for do in word: 9 wo=[] 10 for term in set(do): 11 a = collection.tf_idf(term, do) 12 if(a > 0): 13 wo.append([term,a]) #ここも上のサイトにのってる 14 #print(wo) 15 wo.sort(key=lambda x:x[1]) #keyに無名関数lambdaをいれてる woの1番目の要素(WO(1,2)だったら”2”)でソート 16 wo.reverse() 17 #print(wo) 18 slice1 = [i[0] for i in wo] #woの単語のみを抽出 19 lists = slice1[:20] #20番までにへらす 20 doc.append(list(lists)) #listsが文字列だから、リストに格納 21 del wo 22 23 return doc

wordは
[["aa"],["bb"],["af"],["df"],["fd"]]
のような文字列のリストです

現状このようなコードでcython化させているのですが
全然はやくなりません
そもそもほかの部分に冗長があったりするのかもしれませんが
型定義などで速くする方法はありますか?
この処理が遅くしているなどの指摘でもかまわないので
よろしくお願いします

修正依頼をうけて-----------------
処理時間の変化はやる時々でかわるのですが
それこそ誤差程度で、1秒以内で速くなったり、遅くなったりを
繰り返しています

退会済みユーザー👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/07/27 03:39

>現状このようなコードでcython化させているのですが 全然はやくなりません 私にはできませんが、cython化前後で時間がどれくらい変わったか(変わっていないか)の数字があると、わかる人には答えがわかるかもしれません。
guest

回答4

0

ベストアンサー

一度プロファイラーなどを使用して、現状のコードを解析してみることをお勧めします。

参考までに、私の環境で(Cython版)tfidf関数をcProfileで解析してみたところ、下記のような結果になっております。(5MByteくらいのデータを使用)

6307418 function calls in 10.835 seconds Ordered by: cumulative time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 10.835 10.835 {built-in method builtins.exec} 1 0.038 0.038 10.835 10.835 <string>:1(<module>) 1 0.298 0.298 10.797 10.797 {tfidf.tfidf} 674820 0.528 0.000 10.026 0.000 text.py:581(tf_idf) 674820 0.220 0.000 8.836 0.000 text.py:568(idf) 538 8.514 0.016 8.514 0.016 text.py:575(<listcomp>) 674820 0.255 0.000 0.662 0.000 text.py:564(tf) 1 0.001 0.001 0.472 0.472 text.py:556(__init__) 1 0.044 0.044 0.472 0.472 text.py:289(__init__) 674820 0.377 0.000 0.377 0.000 {method 'count' of 'list' objects} (略)

この結果を見る限りは、tfidf関数全体(tfidf.tfidf) でかかった時間(cumtime) 10.797秒に対して、nltkのtf_idf()内で費やした時間は 10.026秒となっており、この外部ライブラリでの処理時間がほぼ支配的になっております。

ですので、いくらCythonの型を最適化してtfidf関数内のループを速くしても、それほど効果がないきがします。

投稿2017/07/27 12:13

magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kohekoh

2017/07/27 12:19

ありがとうございます!
kohekoh

2017/07/27 12:32

処理を早くするには、やはりtfidfの部分を速くなるように自分で書き直すくらいしかないですかね?
guest

0

おそらく上のコードでの処理時間の大半を占めるのはnltkのtf-idfの計算の部分だと思います。(手元で確認はしていないので例え話ですが)全体の数%程度の負荷の処理を100倍早くしても全体の処理時間に対する改善は微々たるものですよね。

パフォーマンスチューニングで大切なのは闇雲な最適化ではなく計測です。ボトルネックになっている箇所を把握することができていますか?

例えば、あげられているような短いコード片に対してはline_profilerなどを使って見ると良いかもしれません。行単位でのプロファイルの結果が見れるのでおおよその見当はつくのではないかと思います。

そして、tf-idf自体の実装はそれほど複雑ではないので自分で早い実装を書いてみると良いと思います。

投稿2017/07/27 12:15

podhmo

総合スコア29

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kohekoh

2017/07/27 12:19

なるほど ありがとうございます!
guest

0

ちなみにですが、
gensimを用いてtfidfをしたら断然早くなりました
ありがとうございました

投稿2017/07/28 08:54

kohekoh

総合スコア140

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Pythonはやったことは無いんですが、興味本位で検索したら、以下のような記事がありました。

深入りしないCython入門

高速化においては型定義が結構重要なんですね。

なので、入力パラメータの型宣言と後は配列はNumPy 配列を使用すること位でしょうか。

投稿2017/07/27 02:42

sazi

総合スコア25184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

podhmo

2017/07/27 12:38

解決に役立たない
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問