2014-03-14 97 views
7

当保存到磁盘时,我尝试了多种方法来进行数据压缩numpy arrays有效压缩numpy阵列

这些一维数组含有在一定的采样率(可记录的声音用麦克风,或任何其它measurment与任何传感器)采样数据:所述数据是基本上连续(在数学意义上;当然采样后它现在是离散数据)。

我试着用HDF5(h5py):

f.create_dataset("myarray1", myarray, compression="gzip", compression_opts=9) 

但这是相当缓慢的,而压缩比不是我们能期待的最好。

我也试图与

numpy.savez_compressed() 

但再次它可能不是这样的数据(之前描述的)的最佳压缩算法。

对于numpy array有更好的压缩比,你会选择什么样的数据?

(我想这样的事情无损FLAC(最初设计用于音频),但有适用于numpy的数据,算法简单的方法?)

+0

从在源,'savez_compressed掠()'似乎使用DEFLATE(即'gzip')为好。请注意,压缩的有效性很大程度上取决于数据。有些数据不是很可压缩的... – delnan

+0

@delnan:我的数据是音频或类似的数据...音频的无损压缩可以达到近2:1的比率,这就是为什么我期望类似这样的包含音频数据的numpy数组。 – Basj

+0

那么,它也取决于压缩算法。有一个原因存在音频压缩专用算法,它们可能比DEFLATE更好地为您服务。我不知道如何运行FLAC等。尽管如此,我还是在写一个答案。 – delnan

回答

0

你可能想尝试blz。它可以非常有效地压缩二进制数据。

import blz 
# this stores the array in memory 
blz.barray(myarray) 
# this stores the array on disk 
blz.barray(myarray, rootdir='arrays') 

它或者在文件中或在存储器中压缩stores阵列。压缩基于blosc。 查看scipy video的一些情况。

+0

我不认为你提供的代码实际上写入任何东西到磁盘。你能扩展这个答案吗? – cxrodgers

+0

我增加了一些信息。 – SiggyF

1

什么构成最好的压缩(如果有的话)在很大程度上取决于数据的性质。如果确实需要无损压缩,多种测量数据几乎完全不可压缩。

pytables文档包含了很多有用的数据压缩指南。它还详细介绍了速度权衡等等;事实证明,较高的压缩级别通常是浪费时间。

http://pytables.github.io/usersguide/optimization.html

请注意,这可能是好,因为它会得到。对于整数测量来说,一个简单的拉链式压缩混合滤波器的组合通常效果相当好。该过滤器非常有效地利用了最高端字节通常为0的常见情况,并且仅包含在防范溢出中。

8
  1. 噪音是不可压缩的。因此,除非以某种方式丢弃它(有损压缩),否则无论压缩算法如何,您拥有的任何噪声数据部分都将以1:1的比例进入压缩数据。如果每个样本的24位有效位数(ENOB)等于16位,则剩余的24-16 = 8位噪声会将最大无损压缩比限制为3:1,即使您的(无噪声)数据完全是可压缩。非均匀噪声可压缩到不均匀的程度;你可能想看看噪声的有效熵,以确定它是多么可压缩。

  2. 压缩数据是基于模拟它(部分去除冗余,也有部分这样你就可以从噪声中分离出来,并丢弃噪声)。例如,如果您知道数据的带宽限制为10MHz,并且您的采样频率为200MHz,则可以执行FFT,将高频归零,并仅存储低频系数(在本例中为10:1压缩)。有一个叫做“压缩感知”的整个领域与此有关。

  3. 一个实用的建议,适用于多种合理连续的数据:去噪 - >带宽限制 - >增量压缩 - > gzip(或xz等)。去噪可能与带宽限制相同,或者像运行中值一样的非线性滤波器。带宽限制可以通过FIR/IIR来实现。 Delta压缩只是y [n] = x [n] - x [n-1]。

EDIT一个例证:

from pylab import * 
import numpy 
import numpy.random 
import os.path 
import subprocess 

# create 1M data points of a 24-bit sine wave with 8 bits of gaussian noise (ENOB=16) 
N = 1000000 
data = (sin(2 * pi * linspace(0,N,N)/100) * (1<<23) + \ 
    numpy.random.randn(N) * (1<<7)).astype(int32) 

numpy.save('data.npy', data) 
print os.path.getsize('data.npy') 
# 4000080 uncompressed size 

subprocess.call('xz -9 data.npy', shell=True) 
print os.path.getsize('data.npy.xz') 
# 1484192 compressed size 
# 11.87 bits per sample, ~8 bits of that is noise 

data_quantized = data/(1<<8) 
numpy.save('data_quantized.npy', data_quantized) 
subprocess.call('xz -9 data_quantized.npy', shell=True) 
print os.path.getsize('data_quantized.npy.xz') 
# 318380 
# still have 16 bits of signal, but only takes 2.55 bits per sample to store it 
+0

关于2:去除高于信号双倍带宽的频率分量就是应用奈奎斯特定理。这是一个明智的做法。压缩感测是一种甚至超越数据减少数据的方法,此外还利用了某些领域中数据的稀疏性和优化来从稀疏样本中恢复全部数据。我怀疑这对于将数据存储到磁盘是必需的或合意的。 – yanlend

1

首先,对于一般的数据集,所述shuffle=True参数create_dataset显着提高压缩与大致连续的数据集。它非常巧妙地重新排列要压缩的位,以便(对于连续数据)位缓慢变化,这意味着它们可以被更好地压缩。在我的经验中,它使压缩速度减慢了很多,但是根据我的经验,可以显着提高压缩比。这是损耗,让您真正做到为你把走出相同的数据。

如果你不关心的准确性这么多,你还可以使用scaleoffset参数,来限制的位数存储。但要小心,因为这听起来不像。具体地讲,它是一个绝对精度,而不是一个相对精度。例如,如果您通过scaleoffset=8,但您的数据点小于1e-8,则您只会得到零。当然,如果您已将数据最大化为1左右,并且认为您可以听到的差异小于百万分之一,那么您可以通过scaleoffset=6并在没有太多工作的情况下获得很好的压缩效果。

但对于音频而言,我希望你是对的在想使用FLAC,因为它的开发者已经把大量的思想,具有区分细节保存均衡压缩。你可以convert to WAV with scipythence to FLAC

5

我现在在做什么:

import gzip 
import numpy 

f = gzip.GzipFile("my_array.npy.gz", "w") 
numpy.save(file=f, arr=my_array) 
f.close() 
+0

并重新加载它: http://stackoverflow.com/questions/42849821/how-to-recover-a-numpy-array-from-npy-gz-file – jstaker7

0

的HDF5文件与压缩节省可以非常快速,高效:这一切都取决于压缩算法,以及你是否希望它同时节省快,或在读回来,或两者。自然而然地,就像上面解释的那样,数据本身。 GZIP往往位于两者之间,但压缩比很低。 BZIP2在双方都很慢,但比例更好。 BLOSC是我发现的两种算法中的一种,可以获得相当的压缩效果,并且在两端都很快速。 BLOSC的不足之处在于它并未在HDF5的所有实现中实现。因此你的程序可能不是可移植的。 您总是需要进行测试,以便根据您的需求选择最佳配置。

+0

和HDF5文件支持流媒体和阅读块。 –