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

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

新規登録して質問してみよう
ただいま回答率
85.50%
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Python

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

Q&A

3回答

1429閲覧

Pythonで解析を行う際のメモリエラーの回避方法

tsuji__

総合スコア11

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Python

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

0グッド

0クリップ

投稿2021/04/07 07:14

#問題点
現在、Pythonでmatファイルを読み込み、FFT解析を行いウォーターフォール線図の作成にトライしているのですが、FFTの処理時にメモリエラーになっているらしく、その対処法が知りたいです。
#コード
初めのコードがメインのコードになります。
下部が別のコードからインポートしたanarysissunction.py及びmakegraph.pyになります。

Python

1import numpy as np 2import scipy.io 3import matplotlib.pyplot as plt 4import makegraph as mg 5import analysisfunction as af 6from scipy import signal 7from scipy import fftpack 8Fs=8192 9N=1024 10overlap=50 11#flattop_window = signal.flattop(N) # フラットトップ窓 12hanning_window = np.hanning(N) # ハン窓 13#rec_window=signal.boxcar(N)#レクタンギュラ窓 14matdata = scipy.io.loadmat('SweepSignalFs8192.mat') 15wavedata=matdata['Data'] 16mg.one_graph('SweepSiganl',30,10,np.arange(0,77,1/8192),'Time[s]',wavedata[0:630784],'Real[m/s^2]',30,40,'SweepSignal_output') 17fmax,Line,dt,df,t,freq=af.FFTparameter(Fs,N) 18F_ave,N_ave=af.ov_FFT(wavedata,Fs,N,overlap,hanning_window)

Python

1#analysisfunction.py 2def FFTparameter(Fs,N): 3 fmax=int(Fs/2.56)#最大周波数 4 Line=int(N/2.56)#ライン数 5 dt=1/Fs#サンプリング間隔 6 df=fmax/Line 7 t=np.arange(0,N*dt,dt)#時間軸 8 freq=np.arange(0,Line*df,df)#周波数軸 9 return fmax,Line,dt,df,t,freq 10def ov_FFT(data,samplerate,Fs,overlap,window): 11 Ts = len(data) / samplerate 12 Fc = Fs / samplerate 13 x_ol = Fs * (1 - (overlap/100)) 14 N_ave = int((Ts - (Fc * (overlap/100))) / (Fc * (1-(overlap/100)))) 15 array = [] 16 for i in range(N_ave): 17 ps = int(x_ol * i) 18 array.append(data[ps:ps+Fs:1]) 19 array_window=array*window 20 F = fftpack.fft(array_window) 21 Famp=np.abs(F) 22 F_total=np.sum(Famp,axis=0) 23 F_average=F_total / Fs*2 24 F_average=F_average/N_ave 25 acf=1/(sum(window)/Fs) 26 F_average=acf*F_average 27 return F_average, N_ave

Python

1#makegraph.py 2def one_graph(title,width,height,x,xlabel,y,ylabel,labelfont,fz,savetitle): 3 fig = plt.figure(figsize=(width, height)) 4 fig.suptitle(title,fontsize=fz) 5 ax=fig.add_subplot(111) 6 plt.plot(x,y) 7 plt.xlabel(xlabel,fontsize=labelfont) 8 plt.xticks(fontsize=labelfont) 9 plt.ylabel(ylabel,fontsize=labelfont) 10 plt.yticks(np.arange(-0.4,0.6,0.2),fontsize=labelfont) 11 plt.savefig(savetitle) 12 return 0

#入力ファイルについて
今回用いたファイルはSweepSignalFs8192.matになります。このファイルには以下のデータが格納されています。matファイルデータ
ここで、Dataは(630784,1)の配列なので、一旦wavedataに置き換えてから処理しています。

#matfile内のData(一部) 0.00668657 0.0122638 0.0117161 0.0131935 0.0134903 0.0143503 0.0146439 0.015117 0.015357 0.0156636 ...

#現状のエラーについて
以下のようなエラーが発生しています。

Python

1unfile('Documents/Python Scripts/waterfalll線図/SweepSignal_test.py') 2Reloaded modules: makegraph, analysisfunction 3Traceback (most recent call last): 4 5 File "Documents\Python Scripts\waterfalll線図\SweepSignal_test.py", line 24, in <module> 6 F_ave,N_ave=af.ov_FFT(wavedata,Fs,N,overlap,hanning_window) 7 8 File "Documents\Python Scripts\waterfalll線図\analysisfunction.py", line 82, in ov_FFT 9 F = fftpack.fft(array_window) 10 11 File "Documents\Anaconda3\lib\site-packages\scipy\fftpack\basic.py", line 87, in fft 12 return _pocketfft.fft(x, n, axis, None, overwrite_x) 13 14 File "Documents\Anaconda3\lib\site-packages\scipy\fft\_pocketfft\basic.py", line 31, in c2c 15 return pfft.c2c(tmp, (axis,), forward, norm, out, workers) 16 17MemoryError: Unable to allocate 2.38 GiB for an array with shape (38, 2048, 2048) and data type complex128

#試したこと
サンプリング数Nを様々な数に変更してみましたが、エラー分の2.38 GiBの所が変わるだけで改善できませんでした。デバッグやタスクマネージャーを使って確認すると、FFT演算で確かにメモリを大幅に消費していることが明白なので、この部分のメモリ消費を改善していきたいと考えています。

その他必要なデータがございましたら可能な限り提供しますので、誰かわかる方がいらっしゃいましたらご協力宜しくお願い致します。

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

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

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

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

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

jbpb0

2021/04/07 13:40 編集

「ov_FFT()」内のforループでは、「array.append(data[ps:ps+Fs:1])」で毎回dataの一部がarrayに追加されていくので、ループが進むほどarrayのサイズが大きくなっていきます そのarrayにループの毎回FFTを行なっていますが、ループの前回からちょっとだけデータが足された状態のarrayの全体を毎回FFTするのは、意図が分かりません 下記のどちらかでいいと思うのですが ・forループではarrayへのappendだけして、ループが終わってarrayに必要なデータが全部入ってから、一回だけFFTを行う ・forループでarrayへのappendはせず、ループで毎回data[ps:ps+Fs:1]*windowにFFTを行い、np.abs(FFT結果)をFampにappendする ただし、前者ではメモリー使用量は減りません FFTが一回で済むので、計算時間は減りますが 後者は、一回のFFTの対象データのサイズが小さくなるので、メモリーエラー対策になるかもしれません (ならないかもしれません) 計算時間は、こちらも減ります
jbpb0

2021/04/07 13:49 編集

もう一つ > Dataは(630784,1)の配列 だと、array*windowの結果が3次元になってしまい、メモリーが足りなくなります Dataの次元を減らして(630784,)にする必要があると思います numpy.arrayならnp.squeeze()ですが、Dataがlistなら、これで行けるかな?? wavedata=np.array(matdata['Data']).squeeze()
tsuji__

2021/04/08 02:58

おっしゃる通りwavedataの次元を減らしてみるとメモリエラーが出ることなく実行することが出来ました! 動作も正常に動作しているので、後は3次元グラフに描画するところまで進みました! ありがとうございました!
jbpb0

2021/04/08 03:14

メモリーエラーの原因は、私の二つ目のコメントに書いた次元ですね 私の一つ目のコメントに書いた内容は、おそらくやらなくても結果は変わりませんが、forルーム内で不要なFFT演算をたくさんしているので、直した方がいいですよ たぶん、 array_window=array*window F = fftpack.fft(array_window) Famp=np.abs(F) を、forループの外に出せばいいと思う
tsuji__

2021/04/08 07:20

上記の部分をforループから出しても結果が変わらず、処理速度も安定していることが確認出来ました!
guest

回答3

0

Dataは(630784,1)の配列

だと、array*windowの結果が3次元になってしまいます
Dataの次元を減らして(630784,)にする必要があると思います

投稿2021/04/08 04:35

jbpb0

総合スコア7651

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

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

0

VMを使っていないでこのエラーが出るのなら、メモリを増設しましょう。

VMを使っていて、このエラーが出るのなら、メモリ割当てを増やしましょう。

投稿2021/04/07 07:52

ppaul

総合スコア24666

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

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

0

投稿2021/04/07 07:51

jeanbiego

総合スコア3966

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問