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

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

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

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

Q&A

解決済

3回答

1929閲覧

pythonでfor文の中でfor文を回すときの最適な方法について

kohekoh

総合スコア140

Python

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

0グッド

0クリップ

投稿2017/07/04 15:51

pythonについてです

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

python

1collection = nltk.TextCollection(word) 2uniqterms = list(set(collection)) 3for do in word: 4 wo=[] 5 for term in uniqterms: 6 if(collection.tf_idf(term, do) > 0): 7 wo.append([term,collection.tf_idf(term, do)])

このときfor文の中でfor文が回っているので
O(n^2)になるはずです

自分が実行したいデータでは、wordとuniqtermsが非常に大きいので
処理時間が膨大になってしまいます

どうにかこの処理を軽くできませんか?
コードの書き方とか、ライブラリとかがあれば教えていただきたいです

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

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

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

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

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

mattn

2017/07/04 16:10

collection.tf_idf が 1 以上を返す条件次第なのでループは変えられないと思います。先に絶対にありえないペアを取り除いておくとループが回る回数を減らす事は出来ます。
kohekoh

2017/07/04 23:55

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

回答3

0

python

1from itertools import product 2from functools import lru_cache 3 4collection = nltk.TextCollection(word) 5uniqterms = list(set(collection)) 6 7@lru_cache(maxsize=len(uniqterms)) 8def costy_eval(term, do): 9 return term, collection.tf_idf(term, do) 10 11wo = [*filter( 12 lambda *args: args[1] > 0, 13 map(costy_eval, *zip(*product(uniqterms, word))) 14)] 15 16''' 17- 2重ループの代わりにproductとmap、ifの代わりにlambdaとfilterを使用 18- collection.tf_idfの呼び出し回数が減らせるかもしれないのでlru_cacheをかます 19- listへのappend呼び出し回数を減らすためにイテレータから直接listを生成 20- woの順序を問わないのであればconcurrent.futuresで並列化する手もあり 21- 追記:costy_evalの引数が2個なのでproductにzipを追加。mapの使い方を間違えてました。 22- 追記2:アスタリスクを二つ足したのでもう速くなさそうなコードになりました。 23'''

投稿2017/07/04 18:06

編集2017/07/05 11:34
YouheiSakurai

総合スコア6142

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

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

kohekoh

2017/07/05 03:31

これを入力すると wo= … のところで unhashable type :'list' のエラーがでてしまいます なぜでしょうか
YouheiSakurai

2017/07/05 05:19

uniqtermsとwordはどんなデータですか?
YouheiSakurai

2017/07/05 05:50

多分termかdoがlistだからlru_cacheでキャッシュできないんだと思いました。lru_cacheを外してみてください。
kohekoh

2017/07/05 09:36

外しました そのあと、実行すると また同じやつがでてきてしまいました ちなみに、map(costy_eval, product(uniqterms, word) の部分のcosty_evalは引数を入力して実行でいいんですよね そのまま実行したら、引数ないですよっていわれたので
kohekoh

2017/07/05 12:31

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

0

遅いなら並列化すればいいじゃん。

雨の中、Cを書かずにPythonで並列計算をする人間がいてもいい。自由とはそういうものだ。

今時のCPUマルチコアだけど、普通に書くと、一つのCPUしか使わないから、全力じゃないですよ。

投稿2017/07/04 17:15

編集2017/07/04 17:19
kiichi54321

総合スコア1984

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

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

kohekoh

2017/07/05 03:31

ありがとうございます 参考にさせていただきます
guest

0

ベストアンサー

TF= 文書(doc)における単語の出現頻度なので、0以外を抽出したいだけなら文書(doc)に存在する単語のみ計算すればよいです。(TF-IDF = TF * IDFにて文書に存在しない単語のTFは0になる)
2重ループはそのまま残りますが、計算量は減ります。

import nltk docs = [ ['明日','の','天気','は','晴れ'], ['今日','の','天気','は','曇'], ['昨日','の','天気','は','晴れ']] collection = nltk.TextCollection(docs) # 文書群に存在する全単語が含まれる print(set(collection)) print( '全探索') uniqTerms = list(set(collection)) for doc in docs: print( "====================") for term in uniqTerms: print( "%s : %f" % (term, collection.tf_idf(term, doc))) print( '文書に存在する単語のみ探索') for doc in docs: print( "====================") # 1文書に存在する単語のみ計算。存在しない場合は常に0なので。 for term in set(doc): print( "%s : %f" % (term, collection.tf_idf(term, doc)))

さらに、全文書に必ず存在する単語、すなわち、IDFが0になる単語、上記例での「の」「天気」「は」を2番目のtermループから外しておくと、上記の例よりもさらに計算量を減らすことができます。

参考:nltk.TextCollection.tf_idf の使い方

投稿2017/07/05 07:32

can110

総合スコア38266

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

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

kohekoh

2017/07/05 10:46

参考にさせていただきます  ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問