我的1-D时间序列长1e8(100,000,000个元素)。 Here是我在Dropbox上使用的数据的链接。 (该文件为382 MB。)
更新
基于memory_profiling,错误发生在行
中data[absolute(data-dc)< m*std(data)]=dc.
更具体地说,操作absolute(data-dc)
占用了所有内存。 Data
如上所述,dc
是常量。也许这是一个微妙的语法错误?
我想从中删除异常值和工件,并用中位数替换这些值。我尝试使用以下功能执行此操作。
from numpy import *
from sys import argv
from scipy.io import savemat
from scipy.stats import scoreatpercentile
def reject_outliers(data,dc,m=3):
data[data==0] = dc
data[bp.absolute(data-dc) < m*np.std(data)] = dc
return data
def butter_bandpass(lowcut,highcut,fs,order=8):
nyq = 0.5*fs
low = lowcut/nyq
high = highcut/nyq
b,a= butter(order, [low, high], btype='band')
return b,a
def butter_bandpass_filter(data,lowcut,highcut,fs,order=8):
b,a = butter_bandpass(lowcut,highcut,fs,order=order)
return lfilter(b,a,data)
OFFSET = 432
filename = argv[1]
outname = argv[2]
print 'Opening '+ filename
with open(filename,'rb') as stream:
stream.seek(OFFSET)
data=fromfile(stream,dtype='int16')
print 'Removing Artifacts, accounting for zero-filling'
dc = median(data)
data = reject_outliers(data,dc)
threshold = scoreatpercentile(absolute(data),85)
print 'Filtering and Detrending'
data = butter_bandpass_filter(data,300,7000,20000)
savemat(outname+'.mat',mdict={'data':data})
在一个文件上调用此文件会占用4 GB的RAM和3 GB的虚拟内存。我确定这是这个函数的第二行,因为我逐步完成了我编写的脚本,它总是挂在这一部分上。我甚至可以看到(在OS X上的Finder中)第二个可用的硬盘空间直线下降。
时间序列不足以解释它。 reject-outliers
的第二行有什么问题?
答案 0 :(得分:5)
我刚刚生成100,000,000个随机浮点数并执行了您描述的相同索引。整个内存使用量远低于千兆字节。你没有告诉我们你的代码还做了什么?尝试通过优秀的memory_profiler运行您的代码。
编辑:添加了memory_profiler的代码和输出:
from numpy.random import uniform
import numpy
@profile
def go(m=3):
data = uniform(size=100000000)
dc = numpy.median(data)
data[numpy.absolute(data-dc) < m*numpy.std(data)] = dc
return data
if __name__ == '__main__':
go()
输出:
Filename: example.py
Line # Mem usage Increment Line Contents
================================================
3 @profile
4 15.89 MB 0.00 MB def go(m=3):
5 778.84 MB 762.95 MB data = uniform(size=100000000)
6 778.91 MB 0.06 MB dc = numpy.median(data)
7 874.34 MB 95.44 MB data[numpy.absolute(data-dc) < m*numpy.std(data)] = dc
8 874.34 MB 0.00 MB return data
正如您所看到的,100M浮动不会占用太多内存。
答案 1 :(得分:4)
您的数据和已修改@mbatchkarov's code的结果:
$ python mbatchkarov.py
Filename: mbatchkarov.py
Line # Mem usage Increment Line Contents
================================================
5 @profile
6 15.74 MB 0.00 MB def go(m=3):
7 15.74 MB 0.00 MB header_size = 432
8 15.74 MB 0.00 MB with open('ch008.ddt', 'rb') as file:
9 15.75 MB 0.00 MB file.seek(header_size)
10 380.10 MB 364.36 MB data = np.fromfile(file, dtype=np.int16) # 2 bytes per item
11 380.20 MB 0.10 MB dc = np.median(data)
12
13 # data[np.absolute(data - dc) < m*np.std(data)] = dc
14 # `data - dc` => temporary array 8 bytes per item
15 744.56 MB 364.36 MB t = data.copy()
16 744.66 MB 0.09 MB t -= dc
17 744.66 MB 0.00 MB np.absolute(t, t)
18 926.86 MB 182.20 MB b = t < m*np.std(data) # boolean => 1 byte per item
19 926.87 MB 0.01 MB data[b] = dc
20 926.87 MB 0.00 MB return data
data - dc
需要几倍的内存:200M项目x每个项目8个字节,即data - dc
导致由于广播而创建一个或两个临时双数组。为避免这种情况,请在其中制作显式副本和子结构:
t = data.copy() # 200M items x 2 bytes per item
t -= dc
似乎memory_profiler
没有显示临时数组的内存。该程序的最大内存大约为3GB。
答案 2 :(得分:3)
Memory_profiler将执行给定行后的Python虚拟机的状态作为行的内存。因此,在一行中创建和销毁的数组不会出现在配置文件中。
以@ mbatchkarov为例,您可以将“data [numpy.absolute(data-dc)&lt; m * numpy.std(data)] = dc”这一行展开到较小的块中,以查看临时数组如何影响内存:
from numpy.random import uniform
import numpy
@profile
def go(m=3):
data = uniform(size=100000000)
dc = numpy.median(data)
t1 = data-dc
t2 = numpy.absolute(t1) < m*numpy.std(data)
data[t2] = dc
return data
if __name__ == '__main__':
go()
给出了
$ python -m memory_profiler t1.py
Filename: t1.py
Line # Mem usage Increment Line Contents
================================================
4 @profile
5 16.61 MB 0.00 MB def go(m=3):
6 779.56 MB 762.95 MB data = uniform(size=100000000)
7 779.62 MB 0.06 MB dc = numpy.median(data)
8 1542.57 MB 762.95 MB t1 = data-dc
9 1637.99 MB 95.42 MB t2 = numpy.absolute(t1) < m*numpy.std(data)
10 1638.00 MB 0.02 MB data[t2] = dc
11 1638.00 MB 0.00 MB return data
很明显,“data-dc”指令会复制您的内存布局。解决这个问题的方法是在原地进行减法,即用“data - = dc”代替“t1 = data - dc”:
$ python -m memory_profiler t1.py
Filename: t1.py
Line # Mem usage Increment Line Contents
================================================
4 @profile
5 16.61 MB 0.00 MB def go(m=3):
6 779.56 MB 762.95 MB data = uniform(size=100000000)
7 779.62 MB 0.06 MB dc = numpy.median(data)
8 779.63 MB 0.01 MB data -= dc
9 875.05 MB 95.42 MB t2 = numpy.absolute(data) < m*numpy.std(data)
10 875.07 MB 0.02 MB data[t2] = dc
11 875.07 MB 0.00 MB return data
正如您所看到的,“data - = dc”现在几乎不会增加内存。