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

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

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

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

Q&A

解決済

1回答

239閲覧

pythonのfor文処理を高速化したい

watagasi_

総合スコア13

Python

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

0グッド

0クリップ

投稿2018/10/02 05:47

編集2018/10/02 11:13

前提・実現したいこと

Pythonで以下のような処理を行いたいのですが、for文中の処理が非常に遅く高速化したいです。
forを用いない表記や配列の参照を少なくする方法などありますでしょうか。

Python3

1import numpy as np 2import scipy.io.wavfile 3from numpy.random import * 4 5sampling_rate = 44110 6wave_form = randint(0,2,3600000) 7th_min = - int(0.09*sampling_rate) 8th_max = int(0.09*sampling_rate) 9diff_th = th_max - th_min 10wave_form_len = len(wave_form) 11recording_arr = np.zeros(wave_form_len) 12 13for th in range(wave_form_len): 14 15 if(th_min<0): 16 if (np.sum(wave_form[:th_max]) / th_max) * 100 <= 80: 17 recording_arr[th] = 1 18 19 if(th_min>=0)and(th_max<wave_form_len): 20 if (np.sum(wave_form[th_min:th_max])/diff_th)*100 <=80: 21 recording_arr[th] = 1 22 23 if(th_max>=wave_form_len): 24 if (np.sum(wave_form[th_min:])/(wave_form_len -th_min)*100 <=80: 25 recording_arr[th] = 1 26 27 th_min += 1 28 th_max += 1

追記
頂いたご指摘を全て合わせて以下のように実装したところ、正常に動作した上で30秒ほどかかっていた動作が15秒にまで改善されました。
本来扱いたいwave_formの長さは1億ほどなので、もう少し高速化したいとは思いますが、なにか方法はありますでしょうか。

Python3

1import numpy as np 2from numpy.random import * 3 4sampling_rate = 44110 5wave_form = randint(0,2,3600000) 6th_min = - int(0.09*sampling_rate) 7th_max = int(0.09*sampling_rate) 8diff_th = th_max - th_min 9wave_form_len = len(wave_form) 10recording_arr = np.zeros(wave_form_len) 11waveform_sum = np.sum(waveform[:th_max-1]) 12 13for th in range(wave_form_len): 14 15 if(th_min<0): 16 waveform_sum += wave_form[th_max] 17 if (waveform_sum / th_max) * 100 <= 80: 18 recording_arr[th] = 1 19 20 if(th_min>=0)and(th_max<wave_form_len ): 21 waveform_sum += wave_form[th_max] 22 waveform_sum -= wave_form[th_min] 23 if (waveform_sum /diff_th)*100 <=80: 24 recording_arr[th] = 1 25 26 if(th_max>=wave_form_len ): 27 waveform_sum -= wave_form[th_min] 28 if (waveform_sum /(wave_form_len -th_min))*100 <=80: 29 recording_arr[th] = 1 30 31 th_max += 1 32 th_min += 1

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

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

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

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

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

magichan

2018/10/02 10:28

2点ほど確認があります。
magichan

2018/10/02 10:28

th_max > len(wave_form) 時の計算ですが、 (np.sum(wave_form[th_min:])/wave_form_len -th_min ではなくて (np.sum(wave_form[th_min:])/(wave_form_len -th_min) の間違いではないですか?
watagasi_

2018/10/02 10:34

ご指摘ありがとうございます。その通りです。修正させていただきます
magichan

2018/10/02 10:38

もう一点は、th_min > 0 かつ tmax > len(wave_form) 時は2つ目と3つ目の条件文がTrueとなり動作しておりますが、3つ目のみが動作するのが正しい動作ではありませんか?
watagasi_

2018/10/02 10:42

これは失念していました…ありがとうございます!こちらも修正させていただきます。
guest

回答1

0

ベストアンサー

ざっとみた限りですが、sumを無駄に繰り返し実行し過ぎじゃないでしょうか。
単純にth_min, th_maxを+1しながらループを回しているようですから、

waveform_sum += wave_form[th_max] ... if (waveform_sum / th_max) * 100 <= 80: ...

といった感じで、ループの中で一つづつ足していくようにすればいいのではないかと思いました。

投稿2018/10/02 06:40

KojiDoi

総合スコア13671

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

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

watagasi_

2018/10/02 07:22

その方式だとインデックスがth_maxまでの累積値を求めることになりますが、「配列中の一定範囲の合計値」を、範囲をずらしながら毎回取得したいのでこのようなコードになっています
KojiDoi

2018/10/02 07:36

それなら、範囲から外れた要素だけ引き算すればいいのでは?
opyon

2018/10/02 07:47

元データが無いので回答が付かないのだと思いますよ。 現状だとエスパーして想像するしか無いですから。
watagasi_

2018/10/02 08:11

回答有り難うございます。ご指摘の通り以下のように訂正し実行してみたところ、しばらくfor文の処理が実行されたあと「Process finished with exit code -1073741819 (0xC0000005)」という文が表示され、このコード以降のプログラムが実行されずに終了しました。 wave_formはランダムな0と1で構成された長さ3,600,000の配列です import numpy as np import scipy.io.wavfile sampling_rate, wave_form = scipy.io.wavfile.read(filename) th_min = - int(0.09*sampling_rate) th_max = int(0.09*sampling_rate) diff_th = th_max - th_min wave_form_len = len(wave_form) recording_arr = np.zeros(wave_form_len) waveform_sum = np.sum(waveform[:th_max-1]) for th in range(wave_form_len): if(th_min<0): waveform_sum += wave_form[th_max] if (waveform_sum / th_max) * 100 <= 80: recording_arr[th] = 1 if(th_min>=0): waveform_sum += wave_form[th_max] waveform_sum -= wave_form[th_min] if (waveform_sum /diff_th)*100 <=80: recording_arr[th] = 1 if(th_max>=len(wave_form)): waveform_sum -= wave_form[th_min] if (waveform_sum /wave_form_len -th_min)*100 <=80: recording_arr[th] = 1 th_min += 1 th_max += 1
opyon

2018/10/02 08:16

>wave_formはランダムな0と1で構成された長さ3,600,000の配列です 見る人が分かりやすいように少しでいいので具体例を書いたほうがいいと思いますよ。 ここではなく質問に追記で。
opyon

2018/10/02 08:38

まだsampling_rateが不明ですね。出力結果の例もあると良いかと。 憶測ですが回答してくれる方はコードと元データをコピペするなりして動かして正しい結果が出るかチェックするはずです。 元データ、コード、出力結果が揃っていないと想像で作るの面倒でスルーされていることもあるかと。
watagasi_

2018/10/02 10:55 編集

頂いたご指摘を全て合わせて以下のように実装したところ、正常に動作した上で30秒ほどかかっていた動作が15秒にまで改善されました。 本来扱いたいwave_formの長さは1億ほどなので、もう少し高速化したいとは思いますが、なにか方法はありますでしょうか。 import numpy as np from numpy.random import * sampling_rate = 44110 wave_form = randint(0,2,3600000) th_min = - int(0.09*sampling_rate) th_max = int(0.09*sampling_rate) diff_th = th_max - th_min wave_form_len = len(wave_form) recording_arr = np.zeros(wave_form_len) waveform_sum = np.sum(waveform[:th_max-1]) for th in range(wave_form_len): if(th_min<0): waveform_sum += wave_form[th_max] if (waveform_sum / th_max) * 100 <= 80: recording_arr[th] = 1 if(th_min>=0)and(th_max<wave_form_len ): waveform_sum += wave_form[th_max] waveform_sum -= wave_form[th_min] if (waveform_sum /diff_th)*100 <=80: recording_arr[th] = 1 if(th_max>=wave_form_len ): waveform_sum -= wave_form[th_min] if (waveform_sum /(wave_form_len -th_min))*100 <=80: recording_arr[th] = 1 th_min += 1 th_max += 1
opyon

2018/10/02 11:01 編集

コメントにコード全文貼り付けるのはやめましょう。 Pythonは特にインデントに意味があるので読みづらいです。 質問本文を編集してください。(2回目)。 1億あるなら最初から書くべきです。 後出しで要件や条件言われると「え?まだあるの?」ってなりますよ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問