webentwicklung-frage-antwort-db.com.de

Eingabe von .npy-Dateien (Numpy-Dateien) in die Tensorflow-Datenpipeline

Tensorflow scheint ein Reader für ".npy" -Dateien zu fehlen. Wie kann ich meine Datendateien in die neue Tensorflow.data.Dataset-Pipeline einlesen? Meine Daten passen nicht in den Arbeitsspeicher.

Jedes Objekt wird in einer separaten ".npy" -Datei gespeichert. Jede Datei enthält 2 verschiedene ndarrays als Merkmale und einen Skalar als Bezeichnung.

4
Sluggish Crow

Passen Ihre Daten in den Speicher? Wenn ja, können Sie den Anweisungen im Abschnitt Consuming NumPy Arrays der Dokumentation folgen:

NumPy-Arrays konsumieren

Wenn alle Eingabedaten in den Speicher passen, können Sie am einfachsten ein Dataset daraus erstellen, indem Sie sie in tf.Tensor-Objekte konvertieren und Dataset.from_tensor_slices () verwenden.

# Load the training data into two NumPy arrays, for example using `np.load()`.
with np.load("/var/data/training_data.npy") as data:
  features = data["features"]
  labels = data["labels"]

# Assume that each row of `features` corresponds to the same row as `labels`.
assert features.shape[0] == labels.shape[0]

dataset = tf.data.Dataset.from_tensor_slices((features, labels))

Falls die Datei nicht in den Arbeitsspeicher passt, scheint der einzige empfohlene Ansatz zu sein, zuerst die npy-Daten in ein TFRecord-Format zu konvertieren und dann das TFRecord-Dateiformat zu verwenden, das gestreamt werden kann, ohne vollständig in den Arbeitsspeicher geladen zu werden .

Hier ist ein Beitrag mit einigen Anweisungen.

FWIW, es scheint mir verrückt zu sein, dass TFRecord nicht direkt mit einem Verzeichnisnamen oder Dateinamen von npy-Dateien instanziiert werden kann, aber es scheint eine Einschränkung des reinen Tensorflows zu sein.

Wenn Sie die einzelne große npy-Datei in kleinere Dateien aufteilen können, die jeweils ungefähr einen Stapel für das Training darstellen, können Sie in Keras einen benutzerdefinierten Datengenerator schreiben, der nur die Daten liefert, die für den aktuellen Stapel benötigt werden.

Wenn Ihre Datenmenge nicht in den Arbeitsspeicher passt, ist das Arbeiten mit einer einzigen großen npy-Datei sehr schwierig, und Sie sollten die Daten vorzugsweise zuerst als TFRecord- oder als mehrere npy-Dateien neu formatieren und dann andere Methoden verwenden .

3
ely

Sie können dies mit tf.py_func tun, siehe das Beispiel here ..__ Die Parser-Funktion dekodiert einfach den Dateinamen von Bytes zu String und ruft np.load auf.

Update: so etwas:

def read_npy_file(item):
    data = np.load(item.decode())
    return data.astype(np.float32)

file_list = ['/foo/bar.npy', '/foo/baz.npy']

dataset = tf.data.Dataset.from_tensor_slices(file_list)

dataset = dataset.map(
        lambda item: Tuple(tf.py_func(read_npy_file, [item], [tf.float32,])))
5
George

Es ist tatsächlich möglich, NPY-Dateien direkt mit TensorFlow anstelle von TFRecords zu lesen. Die Schlüsselstücke sind tf.data.FixedLengthRecordDataset und tf.decode_raw , zusammen mit einem Blick in die Dokumentation des NPY-Formats . Nehmen wir zur Vereinfachung an, dass eine Float32-NPY-Datei mit einem Array mit der Form (N, K) angegeben ist, und Sie kennen die Anzahl der Features K sowie die Tatsache, dass es sich um ein Float32-Array handelt. Eine NPY-Datei ist nur eine binäre Datei mit einem kleinen Header und gefolgt von den Rohdaten des Arrays (Objektarrays unterscheiden sich, aber wir betrachten jetzt Zahlen). Kurz gesagt, Sie können die Größe dieses Headers mit einer Funktion wie dieser ermitteln:

def npy_header_offset(npy_path):
    with open(str(npy_path), 'rb') as f:
        if f.read(6) != b'\x93NUMPY':
            raise ValueError('Invalid NPY file.')
        version_major, version_minor = f.read(2)
        if version_major == 1:
            header_len_size = 2
        Elif version_major == 2:
            header_len_size = 4
        else:
            raise ValueError('Unknown NPY file version {}.{}.'.format(version_major, version_minor))
        header_len = sum(b << (8 * i) for i, b in enumerate(f.read(header_len_size)))
        header = f.read(header_len)
        if not header.endswith(b'\n'):
            raise ValueError('Invalid NPY file.')
        return f.tell()

Damit können Sie einen Datensatz wie folgt erstellen:

import tensorflow as tf

npy_file = 'my_file.npy'
num_features = ...
dtype = tf.float32
header_offset = npy_header_offset(npy_file)
dataset = tf.data.FixedLengthRecordDataset([npy_file], num_features * dtype.size, header_bytes=header_offset)

Jedes Element dieses Datensatzes enthält eine lange Bytefolge, die ein einzelnes Beispiel darstellt. Sie können es jetzt dekodieren, um ein aktuelles Array zu erhalten:

dataset = dataset.map(lambda s: tf.decode_raw(s, dtype))

Die Elemente haben jedoch eine unbestimmte Form, da TensorFlow die Länge der Saiten nicht verfolgt. Sie können die Form einfach erzwingen, da Sie die Anzahl der Features kennen:

dataset = dataset.map(lambda s: tf.reshape(tf.decode_raw(s, dtype), (num_features,)))

In ähnlicher Weise können Sie diesen Schritt nach dem Stapeln ausführen oder ihn beliebig kombinieren.

Die Einschränkung ist, dass Sie die Anzahl der Funktionen im Voraus kennen mussten. Es ist jedoch möglich, es aus dem NumPy-Header zu extrahieren, nur ein bisschen schmerzhaft und auf jeden Fall sehr schwer aus TensorFlow heraus, so dass die Dateinamen vorher bekannt sein müssten. Eine weitere Einschränkung besteht darin, dass Sie bei der Lösung in diesem Fall entweder nur eine Datei pro Datensatz oder Dateien mit derselben Headergröße verwenden müssen. Wenn Sie jedoch wissen, dass alle Arrays die gleiche Größe haben, sollte dies tatsächlich der Fall sein.

Wenn man diese Art von Ansatz in Betracht zieht, ist es vielleicht besser, eine reine Binärdatei ohne Header zu haben und entweder die Anzahl der Features hart zu codieren oder sie aus einer anderen Quelle zu lesen ...

2
jdehesa