2014-03-14 12 views
7

Ich habe verschiedene Methoden versucht, um Datenkomprimierung durchzuführen, wenn auf Festplatte einige numpy arrays gespeichert werden.Numerische Arrays effizient komprimieren

Dieser 1D-Arrays enthält Daten bei einer bestimmten Abtastrate abgetastet (kann Ton mit einem Mikrofon aufgenommen werden, oder jede anderen Messung mit jedem Sensor): die Daten im wesentlichen kontinuierlichen (im mathematischen Sinne, natürlich nach der Probenahme es ist jetzt diskrete Daten).

Ich habe versucht, mit HDF5 (h5py):

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

aber das ist ziemlich langsam, und das Verdichtungsverhältnis ist nicht das Beste, was wir erwarten können.

Ich habe auch versucht mit

numpy.savez_compressed() 

aber wieder kann es nicht der beste Komprimierungsalgorithmus für solche Daten sein (zuvor beschrieben).

Was würden Sie für eine bessere Kompressionsrate auf einem numpy array mit solchen Daten wählen?

(dachte ich über Dinge wie lossless FLAC (ursprünglich für Audio ausgelegt), aber gibt es eine einfache Möglichkeit, einen solchen Algorithmus auf numpy Daten anzuwenden?)

+0

Von einem Blick auf die Quelle scheint 'savez_compressed()' auch DEFLATE (d. H. 'Gzip') zu verwenden. Beachten Sie, dass die Effektivität der Komprimierung sehr stark von den Daten abhängt. Einige Daten sind einfach nicht sehr komprimierbar ... – delnan

+0

@delnan: meine Daten sind Audio oder ähnliche Art von Daten ...Verlustfreie Kompression auf Audio kann ein Verhältnis von fast 2: 1 erreichen, deshalb habe ich so etwas für mein Array mit Audiodaten erwartet. – Basj

+0

Nun, es hängt auch vom Kompressionsalgorithmus ab. Es gibt einen Grund dedizierte Algorithmen für die Audiokomprimierung, sie dienen Ihnen wahrscheinlich besser als DEFLATE. Ich weiß nicht, wie man FLAC et al. auf numpigen Daten, oder ich würde jetzt eine Antwort schreiben. – delnan

Antwort

0

Sie könnten blz versuchen. Es kann Binärdaten sehr effizient komprimieren.

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

Es stores Arrays entweder auf Datei oder im Speicher komprimiert. Die Komprimierung basiert auf blosc. Siehe die scipy video für ein wenig Kontext.

+0

Ich glaube nicht, dass der Code, den Sie eigentlich alles auf der Festplatte zur Verfügung gestellt schreibt. Können Sie diese Antwort erweitern? – cxrodgers

+0

Ich habe ein bisschen mehr Info hinzugefügt. – SiggyF

1

Die beste Komprimierung (falls vorhanden) hängt stark von der Art der Daten ab. Viele Arten von Messdaten sind praktisch vollständig inkompressibel, wenn eine verlustfreie Komprimierung tatsächlich erforderlich ist.

Die Pytables-Dokumentation enthält viele nützliche Richtlinien zur Datenkomprimierung. Es beschreibt auch Speed-Kompromisse und so weiter; höhere Kompressionsraten sind normalerweise eine Zeitverschwendung, wie sich herausstellt.

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

Beachten Sie, dass dies wahrscheinlich so gut ist, wie es bekommen wird. Bei Integer-Messungen funktioniert eine Kombination aus einem Shuffle-Filter mit einer einfachen Zip-Komprimierung normalerweise ziemlich gut. Dieser Filter nutzt sehr effizient die übliche Situation, in der das Byte mit dem höchsten Ende normalerweise 0 ist und nur zum Schutz vor Überlauf enthalten ist.

8
  1. Lärm ist inkompressibel. Daher wird jeder Teil der Daten, die Sie als Rauschen haben, unabhängig vom Komprimierungsalgorithmus in die komprimierten Daten 1: 1 übernommen, es sei denn, Sie löschen sie irgendwie (verlustreiche Komprimierung). Wenn Sie 24 Bits pro Abtastung mit einer effektiven Anzahl von Bits (ENOB) gleich 16 Bits haben, begrenzen die verbleibenden 24-16 = 8 Rauschbits Ihr maximales verlustfreies Komprimierungsverhältnis auf 3: 1, selbst wenn Ihre (geräuschlosen) Daten vorliegen ist perfekt komprimierbar. Ungleichmäßiges Rauschen ist in dem Ausmaß komprimierbar, in dem es nicht gleichförmig ist; Sie wollen wahrscheinlich die effektive Entropie des Rauschens betrachten, um festzustellen, wie komprimierbar es ist.

  2. Komprimieren von Daten basiert auf dem Modellieren (teilweise, um Redundanz zu entfernen, aber auch teilweise, so dass Sie sich von Rauschen trennen und das Rauschen verwerfen können). Wenn Sie beispielsweise wissen, dass Ihre Daten auf 10 MHz begrenzt sind und Sie mit 200 MHz abtasten, können Sie eine FFT durchführen, die hohen Frequenzen auf Null setzen und die Koeffizienten nur für die niedrigen Frequenzen speichern (in diesem Beispiel: 10: 1) Kompression). Es gibt ein ganzes Feld namens "compressive sensing", das damit zusammenhängt.

  3. Ein praktischer Vorschlag, passend für viele Arten von einigermaßen kontinuierlichen Daten: Rauschen -> Bandbreitenlimit -> Delta-Komprimierung -> gzip (oder xz, etc). Der Denoise-Wert kann dem Bandbreitenlimit oder einem nichtlinearen Filter wie einem laufenden Median entsprechen. Bandbreitenbegrenzung kann mit FIR/IIR implementiert werden. Die Delta-Kompression ist nur y [n] = x [n] - x [n-1].

EDIT Ein Beispiel:

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

Zu 2 .: Das Entfernen von Frequenzkomponenten oberhalb der doppelten Bandbreite des Signals erfolgt nur durch Anwendung des Nyquist-Theorems. Dies ist eine vernünftige Sache zu tun. Compressed Sensing sind Methoden, um die Daten sogar darüber hinaus zu reduzieren, die zusätzlich Sparsity der Daten in einer Domäne und Optimierung verwendet, um die vollständigen Daten aus den Sparse-Samples wiederherzustellen. Ich bezweifle, dass dies zum Speichern von Daten auf der Festplatte erforderlich oder wünschenswert ist. – yanlend

1

Zunächst für die allgemeine Datensätzen, die shuffle=True Argument create_dataset dramatisch verbessert Kompression mit grob kontinuierlichen Datensätzen. Sie ordnet die zu komprimierenden Bits sehr geschickt an, so dass (für kontinuierliche Daten) die Bits sich langsam ändern, was bedeutet, dass sie besser komprimiert werden können. Es verlangsamt die Komprimierung nach meiner Erfahrung ein wenig, kann aber die Kompressionsraten meiner Erfahrung nach wesentlich verbessern. Es ist nicht verlustbehaftete, so dass Sie wirklich die gleichen Daten zu tun bekommen, wie Sie in.

Wenn Sie nicht über die Genauigkeit egal so viel, Sie auch das scaleoffset Argument verwenden können, um die Anzahl der Bits zu begrenzen gelagert. Sei aber vorsichtig, denn so könnte es nicht klingen. Insbesondere ist es eine absolute Präzision, anstatt eine relative Präzision. Übergeben Sie beispielsweise scaleoffset=8, aber Ihre Datenpunkte sind kleiner als 1e-8, erhalten Sie nur Nullen. Natürlich, wenn Sie die Daten bis zu einem Maximum von 1 skaliert haben und nicht glauben, dass Sie Unterschiede kleiner als ein Teil in einer Million hören können, können Sie scaleoffset=6 passieren und eine großartige Komprimierung ohne viel Arbeit erreichen.

Aber speziell für Audio, erwarte ich, dass Sie Recht haben, FLAC zu verwenden, weil seine Entwickler große Mengen an Gedanken, Ausgleich von Kompression mit Erhaltung von unterscheidbaren Details gesetzt haben. Sie können convert to WAV with scipy und thence to FLAC.

5

Was ich jetzt tun:

import gzip 
import numpy 

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

Und wieder zu laden: http://stackoverflow.com/questions/42849821/how-to-recover-a-numpy-array-from-npy-gz-file – jstaker7

0

Die HDF5 Datei mit Komprimierung Speicher kann sehr schnell und effizient sein: es hängt alles von dem Komprimierungsalgorithmus, und ob Sie es schnell sein, beim Speichern oder während Lesen Sie es zurück oder beides. Und natürlich auf die Daten selbst, wie es oben erläutert wurde. GZIP neigt dazu, irgendwo dazwischen zu sein, aber mit niedriger Kompressionsrate. BZIP2 ist auf beiden Seiten langsam, aber mit einem besseren Verhältnis. BLOSC ist einer der Algorithmen, von denen ich herausgefunden habe, dass sie ziemlich komprimiert und auf beiden Seiten schnell sind. Der Nachteil von BLOSC ist, dass es nicht in allen Implementierungen von HDF5 implementiert ist. Daher ist Ihr Programm möglicherweise nicht tragbar. Sie müssen immer mindestens einige Tests durchführen, um die beste Konfiguration für Ihre Bedürfnisse auszuwählen.

+0

Und HDF5-Dateien unterstützen Streaming und Einlesen Stücke. –