2014-03-14 132 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文件支持流媒體和閱讀塊。 –