当保存到磁盘时,我尝试了各种方法进行数据压缩一些numpy arrays
。
这些一维阵列包含一定采样率的采样数据(可以使用麦克风录制声音,或使用任何传感器进行任何其他测量):数据基本上是连续的(在数学意义上;当然,采样后它现在是离散数据) 。
我尝试使用HDF5
(h5py):
f.create_dataset("myarray1", myarray, compression="gzip", compression_opts=9)
但这很慢,压缩比不是我们所能期望的最好。
我也尝试过
numpy.savez_compressed()
但是再一次,它可能不是这种数据的最佳压缩算法(如前所述)。
你有什么选择在numpy array
上获得更好的压缩率,有这样的数据?
(我考虑过无损FLAC(最初是为音频而设计),但是有一种简单的方法可以在numpy数据上应用这样的算法吗?)
编辑插图:
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
我现在应该做什么:
import gzip
import numpy
f = gzip.GzipFile("my_array.npy.gz", "w")
numpy.save(file=f, arr=my_array)
f.close()
什么构成最佳压缩(如果有的话)高度取决于数据的性质。如果确实需要无损压缩,则多种测量数据几乎完全不可压缩。
pytables文档包含许多有关数据压缩的有用指南。它还详细说明了速度权衡等等;事实证明,更高的压缩水平通常是浪费时间。
http://pytables.github.io/usersguide/optimization.html
请注意,这可能与它将获得的一样好。对于整数测量,具有简单zip压缩类型的shuffle过滤器的组合通常可以很好地工作。该过滤器非常有效地利用了最高端字节通常为0的常见情况,并且仅包括防止溢出。
首先,对于一般数据集,shuffle=True
的create_dataset
参数通过大致连续的数据集显着改善压缩。它非常巧妙地重新排列要压缩的位,以便(对于连续数据)位变化缓慢,这意味着它们可以被更好地压缩。根据我的经验,它可以减慢压缩速度,但在我的经验中可以显着提高压缩率。这不是有损的,所以你确实得到了与你输入相同的数据。
如果您不太关心准确性,您还可以使用scaleoffset
参数来限制存储的位数。但要小心,因为这听起来不像。特别是,它是绝对精度,而不是相对精度。例如,如果您传递scaleoffset=8
,但是您的数据点小于1e-8
,那么您将获得零。当然,如果您将数据缩放到大约1,并且不认为您可以听到小于百万分之一的差异,您可以通过scaleoffset=6
并获得很好的压缩而无需太多工作。
但对于音频而言,我希望你是正确的想要使用FLAC,因为它的开发人员已经投入了大量的思想,平衡压缩与保存可区分的细节。你可以convert to WAV with scipy和thence to FLAC。
使用压缩保存的HDF5文件可以非常快速和高效:这一切都取决于压缩算法,以及您是希望在保存时还是在读取时快速,或两者兼而有之。当然,正如上面所解释的那样,数据本身也是如此。 GZIP往往介于两者之间,但压缩率较低。 BZIP2两侧都很慢,但比例较高。 BLOSC是我发现的压缩程序之一,并且两端都很快。 BLOSC的缺点是它并未在HDF5的所有实现中实现。因此,您的程序可能无法移植。您始终需要进行至少一些测试,以根据需要选择最佳配置。
你可能想尝试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。