有效压缩numpy数组

2024-05-14 09:44:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试了各种方法在保存到磁盘时进行数据压缩。

这些一维阵列包含一定采样率的采样数据(可以用麦克风录音,也可以用任何传感器进行任何其他测量):数据本质上是连续的(从数学意义上讲;当然,在采样之后,现在是离散的数据)。

我试过HDF5(h5py):

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

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

我也试过

numpy.savez_compressed()

但它可能再次不是此类数据的最佳压缩算法(如前所述)。

对于有这样的数据的numpy array,您会选择什么来获得更好的压缩比?

(我考虑过无损FLAC(最初是为音频设计的),但是有没有一种简单的方法可以将这种算法应用到numpy数据上?)


Tags: 数据方法numpycreate数学传感器dataset磁盘
3条回答

HDF5文件的压缩保存速度非常快,效率也很高:这取决于压缩算法,也取决于您是希望在保存时快速保存,还是在读回时快速保存,或者两者兼而有之。当然,正如上面所解释的,数据本身也是如此。 GZIP往往介于两者之间,但压缩比较低。BZIP2在两边都很慢,尽管有更好的比率。BLOSC是我发现的一种非常压缩的算法,而且两端都很快。BLOSC的缺点是它并没有在HDF5的所有实现中实现。因此,您的程序可能无法移植。 您总是需要进行测试,至少是一些测试,以选择最适合您需要的配置。

我现在做的是:

import gzip
import numpy

f = gzip.GzipFile("my_array.npy.gz", "w")
numpy.save(file=f, arr=my_array)
f.close()
  1. 噪音是不可压缩的。因此,不管压缩算法如何,您拥有的任何一部分数据都将以1:1的比例进入压缩数据,除非您以某种方式丢弃它(有损压缩)。如果每个样本有24位,有效位数(ENOB)等于16位,则剩余的24-16=8位噪声将限制最大无损压缩比为3:1,即使您的(无噪声)数据是完全可压缩的。非均匀噪声在其非均匀程度上是可压缩的;您可能希望查看噪声的有效熵以确定其可压缩程度。

  2. 压缩数据是建立在对其建模的基础上的(一部分是为了消除冗余,另一部分是为了可以从噪声中分离出来并丢弃噪声)。例如,如果知道数据的带宽限制为10MHz,并且采样频率为200MHz,则可以执行FFT,将高频归零,并仅存储低频系数(在本例中:10:1压缩)。与此相关的是一个叫做“压缩感知”的领域。

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

编辑插图:

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

相关问题 更多 >

    热门问题