Hallo allerseits!
Der Start des Kurses
„Python Web Developer“ steht vor der Tür. Wir teilen immer noch interessante Artikel und laden uns zu unseren offenen Lektionen ein, in denen Sie interessantes Material ansehen,
Lehrer kennenlernen und ihnen Fragen stellen können.
Lass uns gehen!
HDF5 ermöglicht die effiziente Speicherung großer DatenmengenWenn Sie mit großen Datenmengen arbeiten, egal ob experimentell oder simuliert, ist das Speichern in mehreren Textdateien nicht sehr effizient. Manchmal müssen Sie auf eine bestimmte Teilmenge von Daten zugreifen, und Sie möchten dies schnell tun. In diesen Situationen löst das HDF5-Format dank einer hochoptimierten integrierten Bibliothek beide Probleme. HDF5 ist in wissenschaftlichen Umgebungen weit verbreitet und verfügt über eine hervorragende Implementierung in Python, die für die sofortige Verwendung mit NumPy entwickelt wurde.
Das HDF5-Format unterstützt Dateien jeder Größe. Jede Datei verfügt über eine interne Struktur, mit der Sie nach einem bestimmten Datensatz suchen können. Dies kann als separate Datei mit einer eigenen hierarchischen Struktur sowie als eine Reihe von Ordnern und Unterordnern betrachtet werden. Standardmäßig werden Daten im Binärformat gespeichert und die Bibliothek ist mit verschiedenen Datentypen kompatibel. Eine der wichtigsten Optionen für das HDF5-Format besteht darin, dass Sie Metadaten an jedes Element der Struktur anhängen können, wodurch es sich ideal zum Erstellen von Offlinedateien eignet.

In Python kann mit dem h5py-Paket eine Schnittstelle mit dem HDF5-Format erstellt werden. Eine der interessantesten Funktionen dieses Pakets ist, dass Daten nur bei Bedarf aus einer Datei gelesen werden. Stellen Sie sich vor, Sie haben ein sehr großes Array, das nicht in Ihren verfügbaren RAM passt. Sie können beispielsweise ein Array auf einem Computer mit anderen Spezifikationen generieren, als Sie es für die Datenanalyse verwenden. Im HDF5-Format können Sie auswählen, welche Elemente des Arrays mit einer Syntax gelesen werden sollen, die NumPy entspricht. Dann können Sie mit Daten arbeiten, die auf der Festplatte und nicht im RAM gespeichert sind, ohne den vorhandenen Code wesentlich zu ändern.
In diesem Artikel wird erläutert, wie Sie mit h5py Daten von Ihrer Festplatte speichern und abrufen können. Wir werden verschiedene Möglichkeiten zum Speichern von Daten und zur Optimierung des Leseprozesses diskutieren. Alle Beispiele in diesem Artikel sind auch in unserem
Github-Repository verfügbar.
InstallationDas HDF5-Format wird von der
HDF-Gruppe unterstützt und basiert auf Open Source-Standards. Dies bedeutet, dass Ihre Daten immer verfügbar sind, auch wenn die Gruppe verschwindet. Python-Unterstützung wird durch das
h5py- Paket bereitgestellt, das über pip installiert werden kann. Denken Sie daran, dass Sie die
virtuelle Umgebung zum Testen verwenden müssen:
pip install h5py
Dieser Befehl installiert auch NumPy, wenn es sich nicht in Ihrer Umgebung befindet.
Wenn Sie nach einem grafischen Tool suchen, mit dem Sie den Inhalt Ihrer HDF5-Dateien untersuchen können, können Sie den
HDF5-Viewer installieren. Es ist in Java geschrieben und sollte daher auf fast jedem Computer funktionieren.
Grundlegende Datenspeicherung und LesenFahren wir mit der Verwendung der HDF5-Bibliothek fort. Wir werden eine neue Datei erstellen und ein zufälliges NumPy-Array darin speichern.
import h5py import numpy as np arr = np.random.randn(1000) with h5py.File('random.hdf5', 'w') as f: dset = f.create_dataset("default", data=arr)
Die ersten Zeilen sind ziemlich einfach: Wir importieren die Pakete h5py und NumPy und erstellen ein Array mit zufälligen Werten. Wir öffnen die Datei random.hdf5 mit der Schreibberechtigung w. Wenn also eine Datei mit demselben Namen bereits vorhanden ist, wird sie überschrieben. Wenn Sie die Datei speichern und dennoch schreiben möchten, können Sie sie mit dem Attribut a anstelle von w öffnen. Wir erstellen ein Dataset namens default und legen die Daten als zufälliges Array fest, das zuvor erstellt wurde. Datensätze sind die Verwalter unserer Daten, hauptsächlich Bausteine des HDF5-Formats.
Eine Notiz
Wenn Sie mit der with-Anweisung nicht vertraut sind, sollte ich beachten, dass dies eine bequeme Möglichkeit ist, Dateien zu öffnen und zu schließen. Auch wenn innerhalb von ein Fehler auftritt, wird die Datei geschlossen. Wenn Sie aus irgendeinem Grund nicht
with
, vergessen Sie niemals, den Befehl
f.close()
am Ende hinzuzufügen. Die
with
Anweisung funktioniert mit allen Dateien, nicht nur mit HDF-Dateien.
Wir können die Daten fast genauso lesen wie die NumPy-Datei:
with h5py.File('random.hdf5', 'r') as f: data = f['default'] print(min(data)) print(max(data)) print(data[:15])
Wir öffnen die Datei mit dem Leseattribut r und stellen die Daten wieder her, indem wir direkt auf den als Standard bezeichneten Datensatz zugreifen. Wenn Sie die Datei öffnen und nicht wissen, welche Datensätze verfügbar sind, können Sie sie abrufen:
for key in f.keys(): print(key)
Nachdem Sie das gewünschte Dataset gelesen haben, können Sie es so verwenden, als ob Sie ein beliebiges NumPy-Array verwenden würden. Sie können beispielsweise die Maximal- und Minimalwerte ermitteln oder die ersten 15 Werte des Arrays auswählen. Diese einfachen Beispiele verbergen jedoch viele Dinge, die unter der Haube passieren, und sie müssen diskutiert werden, um das volle Potenzial von HDF5 zu verstehen.
Im obigen Beispiel können Sie die Daten als Array verwenden. Sie können beispielsweise auf das dritte Element verweisen, indem Sie Daten [2] eingeben, oder Sie können einen Bereich von Datenwerten [1: 3] abrufen. Bitte beachten Sie: Daten sind kein Array, sondern ein Datensatz. Sie können es sehen, indem Sie
print(type(data))
eingeben. Datensätze funktionieren ganz anders als Arrays, da ihre Informationen auf der Festplatte gespeichert sind und nicht in den Arbeitsspeicher geladen werden, wenn wir sie nicht verwenden. Der folgende Code funktioniert beispielsweise nicht:
f = h5py.File('random.hdf5', 'r') data = f['default'] f.close() print(data[1])
Der auftretende Fehler ist etwas umständlich, aber die letzte Zeile ist sehr nützlich:
ValueError: Not a dataset (not a dataset)
Der Fehler bedeutet, dass wir versuchen, auf ein Dataset zuzugreifen, auf das wir keinen Zugriff mehr haben. Dies ist etwas verwirrend, aber es passiert, weil wir die Datei geschlossen haben und daher nicht mehr auf den zweiten Wert in den Daten zugreifen dürfen. Wenn wir variablen Daten f ['default'] zugewiesen haben, lesen wir die Daten tatsächlich nicht aus der Datei, sondern generieren einen Zeiger darauf, wo sich die Daten auf der Festplatte befinden. Auf der anderen Seite funktioniert dieser Code:
f = h5py.File('random.hdf5', 'r') data = f['default'][:] f.close() print(data[10])
Bitte beachten Sie, dass der einzige Unterschied darin besteht, dass wir nach dem Lesen des Datensatzes [:] hinzugefügt haben. Viele andere Handbücher befassen sich mit solchen Beispielen, ohne das volle Potenzial des HDF5-Formats mit dem h5py-Paket zu demonstrieren. Aufgrund der Beispiele, die wir bisher untersucht haben, fragen Sie sich möglicherweise: Warum HDF5 verwenden, wenn das Speichern von NumPy-Dateien dieselbe Funktionalität bietet? Lassen Sie uns in die Funktionen des HDF5-Formats eintauchen.
Selektives Lesen aus HDF5-DateienBisher haben wir festgestellt, dass wir beim Lesen eines Datensatzes noch keine Daten von der Festplatte lesen, sondern einen Link zu einer bestimmten Stelle auf der Festplatte erstellen. Wir können sehen, was passiert, wenn wir beispielsweise die ersten 10 Elemente eines Datensatzes explizit lesen:
with h5py.File('random.hdf5', 'r') as f: data_set = f['default'] data = data_set[:10] print(data[1]) print(data_set[1])
Wir teilen den Code in verschiedene Zeilen auf, um ihn expliziter zu gestalten. Sie können jedoch in Ihren Projekten synthetischer sein. In den obigen Zeilen lesen wir zuerst die Datei und dann den Standarddatensatz. Wir ordnen die ersten 10 Elemente des Datensatzes der Datenvariablen zu. Nach dem Schließen der Datei (wenn sie endet) können wir auf die in Daten gespeicherten Werte zugreifen, aber data_set gibt einen Fehler aus. Beachten Sie, dass wir nur dann von der Festplatte lesen, wenn wir explizit auf die ersten 10 Elemente eines Datensatzes zugreifen. Wenn Sie sich die Typen data und data_set ansehen, werden Sie feststellen, dass sie sich wirklich unterscheiden. Das erste ist ein NumPy-Array und das zweite ist ein h5py-DataSet.
Das gleiche Verhalten ist in komplexeren Szenarien relevant. Erstellen wir eine neue Datei, diesmal mit zwei Datensätzen, und wählen wir die Elemente eines davon basierend auf den Elementen des anderen aus. Beginnen wir mit dem Erstellen einer neuen Datei und dem Speichern von Daten. Dieser Teil ist der einfachste:
import h5py import numpy as np arr1 = np.random.randn(10000) arr2 = np.random.randn(10000) with h5py.File('complex_read.hdf5', 'w') as f: f.create_dataset('array_1', data=arr1) f.create_dataset('array_2', data=arr2)
Wir haben zwei Datensätze namens array_1 und array_2, von denen jeder ein zufälliges NumPy-Array enthält. Wir möchten array_2-Werte lesen, die Elementen entsprechen, bei denen array_1-Werte positiv sind. Wir können versuchen, so etwas zu tun:
with h5py.File('complex_read.hdf5', 'r') as f: d1 = f['array_1'] d2 = f['array_2'] data = d2[d1>0]
aber das wird nicht funktionieren. d1 ist ein Datensatz und kann nicht mit einer ganzen Zahl verglichen werden. Die einzige Möglichkeit besteht darin, die Daten tatsächlich von der Festplatte zu lesen und dann zu vergleichen. Deshalb bekommen wir so etwas:
with h5py.File('complex_read.hdf5', 'r') as f: d1 = f['array_1'] d2 = f['array_2'] data = d2[d1[:]>0]
Der erste Datensatz d1 wird vollständig in den Speicher geladen, wenn wir d1 [:] ausführen, aber aus dem zweiten Datensatz d2 nehmen wir nur einige Elemente. Wenn der d1-Datensatz zu groß wäre, um vollständig in den Speicher geladen zu werden, könnten wir in einer Schleife arbeiten.
with h5py.File('complex_read.hdf5', 'r') as f: d1 = f['array_1'] d2 = f['array_2'] data = [] for i in range(len(d1)): if d1[i] > 0: data.append(d2[i]) print('The length of data with a for loop: {}'.format(len(data)))
Natürlich gibt es Probleme mit der Effizienz des objektweisen Lesens und Hinzufügens von Elementen zur Liste, aber dies ist ein sehr gutes Beispiel für einen der größten Vorteile der Verwendung von HDF5 gegenüber Text- oder NumPy-Dateien. Innerhalb der Schleife laden wir nur ein Element in den Speicher. In unserem Beispiel ist jedes Element einfach eine Zahl, aber es kann alles sein: von Text über Bild bis Video.
Wie immer müssen Sie je nach Anwendung entscheiden, ob Sie das gesamte Array in den Speicher lesen möchten oder nicht. Manchmal führen Sie Simulationen auf einem bestimmten Computer mit viel Arbeitsspeicher aus, haben jedoch nicht dieselben Eigenschaften auf Ihrem Laptop und sind gezwungen, Teile Ihrer Daten zu lesen. Denken Sie daran, dass das Lesen von der Festplatte relativ langsam ist, insbesondere wenn Sie die Festplatte anstelle von SDD-Festplatten verwenden, oder sogar länger, wenn Sie von einem Netzwerklaufwerk lesen.
Schreiben Sie selektiv in HDF5-DateienIn den obigen Beispielen haben wir dem Datensatz Daten hinzugefügt, sobald es erstellt wurde. Für viele Anwendungen müssen Sie jedoch Daten während der Generierung speichern. Mit HDF5 können Sie Daten auf die gleiche Weise speichern, wie Sie sie gelesen haben. Lassen Sie uns sehen, wie Sie ein leeres Dataset erstellen und einige Daten hinzufügen.
arr = np.random.randn(100) with h5py.File('random.hdf5', 'w') as f: dset = f.create_dataset("default", (1000,)) dset[10:20] = arr[50:60]
Die ersten beiden Zeilen sind bis auf
create_dataset
dieselben wie zuvor. Wir fügen beim Erstellen keine Daten hinzu, sondern erstellen lediglich einen leeren Datensatz, der bis zu 1000 Elemente enthalten kann. Mit der gleichen Logik wie zuvor schreiben wir beim Lesen bestimmter Elemente aus einem Datensatz nur dann auf die Festplatte, wenn wir bestimmten Elementen der Variablen dset Werte zuweisen. Im obigen Beispiel weisen wir nur einer Teilmenge des Arrays Werte mit Indizes von 10 bis 19 zu.
WarnungEs ist nicht ganz richtig, was Sie auf die Festplatte schreiben, wenn Sie einem Datensatz Werte zuweisen. Der genaue Zeitpunkt hängt von mehreren Faktoren ab, einschließlich des Status des Betriebssystems. Wenn das Programm zu früh geschlossen wird, kann es vorkommen, dass nicht alles aufgezeichnet wird. Es ist sehr wichtig, immer die Methode
close()
verwenden. Wenn Sie schrittweise schreiben, können Sie auch
flush()
, um die Eingabe zu erzwingen. Die Verwendung mit verhindert viele Schreibprobleme.
Wenn Sie die Datei lesen und die ersten 20 Werte des Datensatzes drucken, werden Sie feststellen, dass sie alle Nullen sind, mit Ausnahme der Indizes 10 bis 19. Es gibt einen häufigen Fehler, der zu spürbaren Kopfschmerzen führen kann. Der folgende Code speichert nichts auf der Festplatte:
arr = np.random.randn(1000) with h5py.File('random.hdf5', 'w') as f: dset = f.create_dataset("default", (1000,)) dset = arr
Dieser Fehler verursacht immer viele Probleme, da Sie nicht verstehen werden, dass Sie nichts geschrieben haben, bis Sie versuchen, das Ergebnis zu lesen. Das Problem hierbei ist, dass Sie nicht angeben, wo Sie die Daten speichern möchten, sondern nur die Variable dset mit einem NumPy-Array überschreiben. Da Datensatz und Array gleich lang sind, sollten Sie dset [:] = arr verwenden. Dieser Fehler tritt häufiger auf als Sie denken, und da er technisch nicht falsch ist, werden auf dem Terminal keine Fehler angezeigt, und Ihre Daten sind Nullen.
Bisher haben wir immer mit eindimensionalen Arrays gearbeitet, aber wir sind nicht auf diese beschränkt. Angenommen, wir möchten ein 2D-Array verwenden, können wir einfach Folgendes tun:
dset = f.create_dataset('default', (500, 1024))
Dadurch können wir Daten in einem 500x1024-Array speichern. Um ein Dataset zu verwenden, können wir dieselbe Syntax wie zuvor verwenden, jedoch die zweite Dimension berücksichtigen:
dset[1,2] = 1 dset[200:500, 500:1024] = 123
Geben Sie Datentypen an, um den Speicherplatz zu optimierenBisher haben wir nur die Spitze des Eisbergs untersucht, was HDF5 zu bieten hat. Zusätzlich zur Länge der Daten, die Sie behalten möchten, können Sie den Datentyp angeben, um den Speicherplatz zu optimieren.
Die h5py-Dokumentation enthält eine Liste aller unterstützten Typen, hier zeigen wir nur einige davon. Gleichzeitig werden wir mit mehreren Datensätzen in einer Datei arbeiten.
with h5py.File('several_datasets.hdf5', 'w') as f: dset_int_1 = f.create_dataset('integers', (10, ), dtype='i1') dset_int_8 = f.create_dataset('integers8', (10, ), dtype='i8') dset_complex = f.create_dataset('complex', (10, ), dtype='c16') dset_int_1[0] = 1200 dset_int_8[0] = 1200.1 dset_complex[0] = 3 + 4j
Im obigen Beispiel haben wir drei verschiedene Datensätze erstellt, von denen jeder einen anderen Typ hat. Ganzzahlen von 1 Byte, Ganzzahlen von 8 Bytes und komplexe Zahlen von 16 Bytes. Wir speichern nur eine Nummer, auch wenn unsere Datensätze bis zu 10 Elemente enthalten können. Sie können die Werte lesen und sehen, was tatsächlich gespeichert wurde. Hierbei ist zu beachten, dass eine Ganzzahl von 1 Byte auf 127 (anstelle von 1200) und eine Ganzzahl von 8 Byte auf 1200 (anstelle von 1200,1) gerundet werden sollte.
Wenn Sie jemals in Sprachen wie C oder Fortran programmiert haben, wissen Sie wahrscheinlich, was verschiedene Datentypen bedeuten. Wenn Sie jedoch immer mit Python gearbeitet haben, sind möglicherweise keine Probleme aufgetreten, ohne den Datentyp, mit dem Sie arbeiten, explizit angegeben zu haben. Es ist wichtig zu beachten, dass die Anzahl der Bytes angibt, wie viele verschiedene Zahlen Sie speichern können. Wenn Sie 1 Byte verwenden, haben Sie 8 Bits und können daher 2 ^ 8 verschiedene Zahlen speichern. Im obigen Beispiel sind die Ganzzahlen sowohl positiv als auch negativ und 0. Wenn Sie Ganzzahlen von 1 Byte verwenden, können Sie Werte von -128 bis 127 speichern, insgesamt sind dies 2 ^ 8 mögliche Zahlen. Dies entspricht der Verwendung von 8 Bytes, jedoch mit einem breiten Zahlenbereich.
Der ausgewählte Datentyp wirkt sich auf die Größe aus. Lassen Sie uns zunächst anhand eines einfachen Beispiels sehen, wie dies funktioniert. Erstellen wir drei Dateien mit jeweils einem Datensatz für 100.000 Elemente, jedoch mit unterschiedlichen Datentypen. Wir werden die gleichen Daten in ihnen speichern und dann ihre Größen vergleichen. Wir erstellen ein zufälliges Array für die Zuordnung zu jedem Datensatz, um den Speicher zu füllen. Denken Sie daran, dass die Daten in das im Datensatz angegebene Format konvertiert werden.
arr = np.random.randn(100000) f = h5py.File('integer_1.hdf5', 'w') d = f.create_dataset('dataset', (100000,), dtype='i1') d[:] = arr f.close() f = h5py.File('integer_8.hdf5', 'w') d = f.create_dataset('dataset', (100000,), dtype='i8') d[:] = arr f.close() f = h5py.File('float.hdf5', 'w') d = f.create_dataset('dataset', (100000,), dtype='f16') d[:] = arr f.close()
Wenn Sie die Größe jeder Datei überprüfen, erhalten Sie Folgendes:
Datei | Größe (b) |
---|
Ganzzahl_1 | 102144 |
Ganzzahl_9 | 802144 |
float | 1602144 |
Die Beziehung zwischen Größe und Datentyp ist klar. Wenn Sie von Ganzzahlen von 1 Byte auf bis zu 8 Byte wechseln, erhöht sich die Dateigröße um das 8-fache. Wenn Sie auf 16 Byte wechseln, wird etwa 16-mal mehr Speicherplatz benötigt. Speicherplatz ist jedoch nicht der einzige wichtige Faktor, den Sie berücksichtigen müssen. Sie müssen auch die Zeit berücksichtigen, die zum Schreiben von Daten auf die Festplatte erforderlich ist. Je mehr Sie schreiben müssen, desto länger wird es dauern. Abhängig von Ihrer Anwendung kann es entscheidend sein, das Lesen und Schreiben von Daten zu optimieren.
Bitte beachten Sie: Wenn Sie den falschen Datentyp verwenden, können auch Informationen verloren gehen. Wenn Sie beispielsweise Ganzzahlen von 8 Byte haben und diese als Ganzzahlen von 1 Byte speichern, werden ihre Werte abgeschnitten. Bei der Arbeit im Labor stehen häufig Geräte zur Verfügung, die unterschiedliche Datentypen erstellen. Einige DAQ-Karten haben 16 Bit, einige Kameras arbeiten mit 8 Bit, einige können mit 24 Bit arbeiten. Es ist wichtig, auf Datentypen zu achten, aber dies ist auch etwas, das Python-Entwickler möglicherweise nicht berücksichtigen, da Sie dies nicht müssen Typ deklarieren.
Es ist auch interessant, sich daran zu erinnern, dass das Standard-NumPy-Array mit 8 Bytes (64 Bit) pro Element float ist. Dies kann ein Problem sein, wenn Sie beispielsweise ein Array mit Nullen initialisieren, um Daten zu speichern, die nur 2 Byte betragen sollten. Der Typ des Arrays selbst ändert sich nicht. Wenn Sie die Daten beim Erstellen des Datensatzes speichern (Hinzufügen von Daten = my_array), lautet das Standardformat "f8". Hierbei handelt es sich um ein Array, jedoch nicht um echte Daten.
Das Nachdenken über Datentypen geschieht nicht regelmäßig, wenn Sie in einfachen Anwendungen mit Python arbeiten. Sie sollten sich jedoch bewusst sein, dass Datentypen vorhanden sind und welche Auswirkungen sie auf Ihre Ergebnisse haben können. Möglicherweise verfügen Sie über große Festplatten und interessieren sich nicht wirklich für die Speicherung von Dateien. Wenn Sie sich jedoch für die Geschwindigkeit interessieren, mit der Sie speichern, gibt es keine andere Möglichkeit, als jeden Aspekt Ihres Codes, einschließlich der Datentypen, zu optimieren.
DatenkomprimierungBeim Speichern von Daten können Sie die Komprimierung mit verschiedenen Algorithmen auswählen. Das h5py-Paket unterstützt mehrere Komprimierungsfilter wie GZIP, LZF und SZIP. Bei Verwendung eines der Komprimierungsfilter werden die Daten auf dem Weg zur Festplatte verarbeitet und beim Lesen entpackt. Daher gibt es keine besonderen Änderungen im Code. Wir können dasselbe Experiment wiederholen, indem wir verschiedene Datentypen speichern, aber einen Komprimierungsfilter verwenden. Unser Code sieht folgendermaßen aus:
import h5py import numpy as np arr = np.random.randn(100000) with h5py.File('integer_1_compr.hdf5', 'w') as f: d = f.create_dataset('dataset', (100000,), dtype='i1', compression="gzip", compression_opts=9) d[:] = arr with h5py.File('integer_8_compr.hdf5', 'w') as f: d = f.create_dataset('dataset', (100000,), dtype='i8', compression="gzip", compression_opts=9) d[:] = arr with h5py.File('float_compr.hdf5', 'w') as f: d = f.create_dataset('dataset', (100000,), dtype='f16', compression="gzip", compression_opts=9) d[:] = arr
Wir haben uns für gzip entschieden, da es auf allen Plattformen unterstützt wird. Die Optionen compress_opts geben die Komprimierungsstufe an. Je höher die Ebene, desto weniger Speicherplatz benötigen die Daten, aber desto länger sollte der Prozessor arbeiten. Die Standardkomprimierungsstufe ist 4. Wir können die Unterschiede in unseren Dateien basierend auf der Komprimierungsstufe sehen:
Typ | Keine Komprimierung | Komprimierung 9 | Komprimierung 4 |
---|
Ganzzahl_1 | 102144 | 28016 | 30463 |
Ganzzahl_8 | 802144 | 43329 | 57971 |
float | 1602144 | 1469580 | 1469868 |
Der Effekt der Komprimierung auf ganze Datenfelder ist viel deutlicher als auf Gleitkomma-Datasets. Ich überlasse es Ihnen herauszufinden, warum die Komprimierung in den ersten beiden Fällen so gut funktioniert hat, aber nicht in den letzten. Als Hinweis: Sie sollten überprüfen, welche Daten Sie tatsächlich speichern.
Das Lesen komprimierter Daten ändert nichts an dem oben beschriebenen Code. Die HDF5-Kernbibliothek kümmert sich um das Extrahieren von Daten aus komprimierten Datensätzen unter Verwendung des entsprechenden Algorithmus. Wenn Sie die Komprimierung zum Speichern implementieren, müssen Sie daher den Code, den Sie zum Lesen verwenden, nicht ändern.
Die Datenkomprimierung ist ein zusätzliches Tool, das Sie zusammen mit allen anderen Aspekten der Datenverarbeitung berücksichtigen sollten. Sie müssen die zusätzliche Prozessorzeit und das effektive Komprimierungsverhältnis berücksichtigen, um die Vorteile der Datenkomprimierung in Ihrer eigenen Anwendung bewerten zu können. Die Tatsache, dass es für nachgeschalteten Code transparent ist, macht es unglaublich einfach, die beste Lösung zu testen und zu finden.
Ändern Sie die Größe von DatensätzenWenn Sie an einem Experiment arbeiten, ist es manchmal unmöglich herauszufinden, wie groß Ihre Daten sein werden. Stellen Sie sich vor, Sie nehmen einen Film auf, vielleicht stoppen Sie ihn nach einer Sekunde, vielleicht nach einer Stunde. Glücklicherweise können Sie mit HDF5 die Größe von Datensätzen im Handumdrehen mit geringem Rechenaufwand ändern. Die Länge des Datensatzes kann bis zur maximalen Größe überschritten werden. Diese maximale Größe wird beim Erstellen des Datasets mit dem Schlüsselwort maxshape angegeben:
import h5py import numpy as np with h5py.File('resize_dataset.hdf5', 'w') as f: d = f.create_dataset('dataset', (100, ), maxshape=(500, )) d[:100] = np.random.randn(100) d.resize((200,)) d[100:200] = np.random.randn(100) with h5py.File('resize_dataset.hdf5', 'r') as f: dset = f['dataset'] print(dset[99]) print(dset[199])
Zunächst erstellen Sie ein Dataset zum Speichern von 100 Werten und legen die maximale Größe auf 500 Werte fest. Nachdem Sie den ersten Wertestapel gespeichert haben, können Sie den Datensatz erweitern, um die nächsten 100 zu speichern. Sie können den Vorgang wiederholen, bis Sie einen Datensatz mit 500 Werten erhalten. , N- . , , .
, , . , - ( , , ):
with h5py.File('resize_dataset.hdf5', 'a') as f: dset = f['dataset'] dset.resize((300,)) dset[:200] = 0 dset[200:300] = np.random.randn(100) with h5py.File('resize_dataset.hdf5', 'r') as f: dset = f['dataset'] print(dset[99]) print(dset[199]) print(dset[299])
, , 200 200 299. , , .
, , , . 2D-, , — , 2D-. 3- HDF-, . , :
with h5py.File('movie_dataset.hdf5', 'w') as f: d = f.create_dataset('dataset', (1024, 1024, 1), maxshape=(1024, 1024, None )) d[:,:,0] = first_frame d.resize((1024,1024,2)) d[:,:,1] = second_frame
1024x1024 , . , , . maxshape None.
(Chunks), . (chunk) , .. . , , . , :
dset = f.create_dataset("chunked", (1000, 1000), chunks=(100, 100))
, dset [0: 100,0: 100] . dset [200: 300, 200: 300], dset [100: 200, 400: 500] . . h5py, :
(Chunking) . 10 KiB 1 MiB, . , , .
(auto-chunking), . , maxshape. :
dset = f.create_dataset("autochunk", (1000, 1000), chunks=True)
(Groups). HDF5, , . (groups), , . , :
import numpy as np import h5py arr = np.random.randn(1000) with h5py.File('groups.hdf5', 'w') as f: g = f.create_group('Base_Group') gg = g.create_group('Sub_Group') d = g.create_dataset('default', data=arr) dd = gg.create_dataset('default', data=arr)
Base_Group , Sub_Group. default . , , :
with h5py.File('groups.hdf5', 'r') as f: d = f['Base_Group/default'] dd = f['Base_Group/Sub_Group/default'] print(d[1]) print(dd[1])
, : Base_Group/default Base_Group/Sub_Group/default. , , , , . — keys():
with h5py.File('groups.hdf5', 'r') as f: for k in f.keys(): print(k)
, , for-. , . visit(), :
def get_all(name): print(name) with h5py.File('groups.hdf5', 'r') as f: f.visit(get_all)
,
get_all
, , name. visit,
get_all.
visit , , None, . , , Sub_Group,
get_all
:
def get_all(name): if 'Sub_Group' in name: return name with h5py.File('groups.hdf5', 'r') as f: g = f.visit(get_all) print(g)
visit , , None, , get_all. Sub_Group, get_all , Sub_Group . , g , , :
with h5py.File('groups.hdf5', 'r') as f: g_name = f.visit(get_all) group = f[g_name]
. — , visititems, : name object. :
def get_objects(name, obj): if 'Sub_Group' in name: return obj with h5py.File('groups.hdf5', 'r') as f: group = f.visititems(get_objects) data = group['default'] print('First data element: {}'.format(data[0]))
visititems , , , . , , . . , , .
HDF5, HDF5, , . , , , , , , .. . , , 200x300x250. , , , , — , .
HDF5 -. .
import time import numpy as np import h5py import os arr = np.random.randn(1000) with h5py.File('groups.hdf5', 'w') as f: g = f.create_group('Base_Group') d = g.create_dataset('default', data=arr) g.attrs['Date'] = time.time() g.attrs['User'] = 'Me' d.attrs['OS'] = os.name for k in g.attrs.keys(): print('{} => {}'.format(k, g.attrs[k])) for j in d.attrs.keys(): print('{} => {}'.format(j, d.attrs[j]))
, attrs . , , . , . , , , update:
with h5py.File('groups.hdf5', 'w') as f: g = f.create_group('Base_Group') d = g.create_dataset('default', data=arr) metadata = {'Date': time.time(), 'User': 'Me', 'OS': os.name,} f.attrs.update(metadata) for m in f.attrs.keys(): print('{} => {}'.format(m, f.attrs[m]))
, , hdf5, . , . hdf5, . Python -. JSON, , , , pickle.
import json with h5py.File('groups_dict.hdf5', 'w') as f: g = f.create_group('Base_Group') d = g.create_dataset('default', data=arr) metadata = {'Date': time.time(), 'User': 'Me', 'OS': os.name,} m = g.create_dataset('metadata', data=json.dumps(metadata))
, . , . , json.dumps, . , HDF5. , json.loads:
Python
with h5py.File('groups_dict.hdf5', 'r') as f: metadata = json.loads(f['Base_Group/metadata'][()]) for k in metadata: print('{} => {}'.format(k, metadata[k]))
json , . YAML, XML .. , , , attr , , .
HDF5, . , , , . HDF , , , , , . , HDF .
HDF5 . , , . , . . SQL,
HDFql , SQL HDF5.
. , , - , , . , . , , .
HDF5 — , . , , , , . HDF5 — , , .
DAS ENDE
,
.