Dies ist eine aktualisierte Version des vorherigen Artikels. So trainieren Sie eine große Datenmenge mit TFRecord & DataSet in TensorFlow & Keras-Qiita
Eine Sache, die ich tun möchte, ist: "Ich möchte eine effiziente Methode zum Trainieren großer Datenmengen, die nicht in den Speicher passen." Mit dieser Methode können das Lesen von CPU-Daten und die GPU-Berechnung parallel verarbeitet werden. Lernen Sie mithilfe der DataSet-API effizient aus Daten, die in einem bestimmten Format gespeichert sind.
Mit der Veröffentlichung von TensorFlow 2 haben sich die Modulnamen im Vergleich zu früheren Versionen des Artikels geändert, und einige Verarbeitungen sind einfacher zu schreiben. In diesem Artikel werde ich vorstellen, wie man in TensorFlow 2 schreibt, wobei ich mich auf die Unterschiede zum vorherigen konzentriere. Außerdem werde ich Keras so ändern, dass es das in TensorFlow enthaltene verwendet.
Dieser Artikel verwendet Python 3.6.9 + TensorFlow 2.1.0 unter Linux (Ubuntu 18.04).
Ab TensorFlow 1.15 / 2.1 wurden die CPU- und GPU-Versionen des Pip-Pakets integriert. Daher gibt es Leute, die es einfach mit der CPU ausprobieren wollen, und Leute, die es ernsthaft mit der GPU machen wollen.
pip3 install tensorflow==2.1.0
Das ist in Ordnung. Bitte beachten Sie, dass Sie CUDA 10.1 einrichten müssen, wenn Sie eine GPU verwenden möchten. GPU support | TensorFlow
Es gibt ein einzigartiges Datenformat (TFRecord), mit dem TensorFlow effizient berechnen kann. Erstellen wir einen TFRecord aus vorhandenen Daten mithilfe der DataSet-API.
data2tfrecord.py
#!/usr/bin/env python3
import numpy as np
import tensorflow as tf
from tensorflow.keras.datasets import mnist
def feature_float_list(l):
return tf.train.Feature(float_list=tf.train.FloatList(value=l))
def record2example(r):
return tf.train.Example(features=tf.train.Features(feature={
"x": feature_float_list(r[0:-1]),
"y": feature_float_list([r[-1]])
}))
filename_train = "train.tfrecords"
filename_test = "test.tfrecords"
# ===MNIST-Daten lesen===
#Nehmen wir der Einfachheit halber an, dass während des Trainings dieselben Verifizierungsdaten wie die Bewertungsdaten für die Verifizierungsdaten verwendet werden.
(x_train, y_train), (x_test, y_test) = mnist.load_data()
print("x_train : ", x_train.shape) # x_train : (60000, 28, 28)
print("y_train : ", y_train.shape) # y_train : (60000,)
print("x_test : ", x_test.shape) # x_test : (10000, 28, 28)
print("y_test : ", y_test.shape) # y_test : (10000,)
#Vorverarbeitung
#Pixel[0, 1]In den Typ float32 konvertieren
#Machen Sie für TFRecording außerdem den Merkmalsbetrag eindimensional (Zeile entspricht dem Datensatz).
x_train = x_train.reshape((-1, 28*28)).astype("float32") / 255.0
x_test = x_test.reshape((-1, 28*28)).astype("float32") / 255.0
#Machen Sie das Label float32 Typ
y_train = y_train.reshape((-1, 1)).astype("float32")
y_test = y_test.reshape((-1, 1)).astype("float32")
#Kombinieren Sie Funktionen und Beschriftungen für TFRecording
data_train = np.c_[x_train, y_train]
data_test = np.c_[x_test, y_test]
#Tatsächlich werden die Daten, die Sie lernen möchten, in dasselbe Format konvertiert und erstellt.
#Wenn nicht alle Daten in den Speicher passen, in der folgenden Schreibphase
#Sie können es nach und nach machen und das Schreiben wiederholen.
#Schreiben Sie Trainingsdaten in TFRecord
with tf.io.TFRecordWriter(filename_train) as writer:
for r in data_train:
ex = record2example(r)
writer.write(ex.SerializeToString())
#Schreiben Sie Bewertungsdaten in TFRecord
with tf.io.TFRecordWriter(filename_test) as writer:
for r in data_test:
ex = record2example(r)
writer.write(ex.SerializeToString())
Es ist fast das gleiche wie beim letzten Mal, aber mit dem Versions-Upgrade von TensorFlow ist das Paket tensorflow.python_io
verschwunden und die mit TFRecord verbundenen Funktionen wurden zu tensorflow.io
hinzugefügt.
Seit ich die Verwendung von Keras in TensorFlow geändert habe, hat sich auch "import" geändert, aber die Methode zum Lesen des MNIST-Datasets selbst hat sich nicht geändert.
Wenn Sie keine Bibliothek für die GPU-Berechnung haben, erhalten Sie eine WARNUNG in Bezug auf CUDA (libcublas kann nicht gefunden werden usw.), aber wenn Sie es nur leicht auf der CPU versuchen möchten, müssen Sie sich darüber keine Sorgen machen.
Es hat sich seit dem letzten Mal ein wenig verändert. Beginnen wir mit dem Code und erklären dann die Unterschiede.
train.py
#!/usr/bin/env python3
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.callbacks import ModelCheckpoint
from tensorflow.keras.models import Model
#Lerneinstellungen
batch_size = 32
epochs = 10
#Funktionseinstellung
num_classes = 10 #Etikettentyp. 0-10 Arten von 9
feature_dim = 28*28 #Die Dimension der Merkmalsmenge. Der Einfachheit halber als 1D handhaben
#Anzahl der Lern- / Bewertungsdaten. Überprüfen Sie im Voraus.
#Beachten Sie, dass bei Verwendung mehrerer TFRecords die folgende Zahl die Summe aller Dateien ist.
num_records_train = 60000
num_records_test = 10000
#Anzahl der Mini-Batches pro Epoche. Wird beim Lernen verwendet.
steps_per_epoch_train = (num_records_train-1) // batch_size + 1
steps_per_epoch_test = (num_records_test-1) // batch_size + 1
#Dekodiere 1 TFRecord
def parse_example(example):
features = tf.io.parse_single_example(
example,
features={
#Geben Sie beim Lesen der Liste die Anzahl der Dimensionen an
"x": tf.io.FixedLenFeature([feature_dim], dtype=tf.float32),
"y": tf.io.FixedLenFeature([], dtype=tf.float32)
})
x = features["x"]
y = features["y"]
return x, y
# ===Bereiten Sie TFRecord-Dateidaten für das Lernen und Auswerten vor===
dataset_train = tf.data.TFRecordDataset(["train.tfrecords"]) \
.map(parse_example) \
.shuffle(batch_size * 100) \
.batch(batch_size).repeat(-1)
#Wenn Sie oben mehrere TFRecord-Dateien verwenden, geben Sie eine Liste der Dateinamen an.
# dataset_train = tf.data.TFRecordDataset(["train.tfrecords.{}".format(i) for i in range(10)]) \
dataset_test = tf.data.TFRecordDataset(["test.tfrecords"]) \
.map(parse_example) \
.batch(batch_size)
# ===Modelldefinition===
#Diesmal ist nur eine 512-dimensionale Zwischenschicht angegeben.
layer_input = Input(shape=(feature_dim,))
fc1 = Dense(512, activation="relu")(layer_input)
layer_output = Dense(num_classes, activation="softmax")(fc1)
model = Model(layer_input, layer_output)
model.summary()
#Verlust, selbst wenn das Label eine kategoriale Variable ist="sparse_categorical_crossentropy"Kann mit lernen
#Beschriften Sie eins-Wenn heiß vektorisiert, Verlust="categorical_crossentropy"werden
model.compile(
loss="sparse_categorical_crossentropy",
optimizer=RMSprop(),
metrics=["accuracy"])
# ===Lernen===
#Speichern Sie das Modell in der Mitte
cp_cb = ModelCheckpoint(
filepath="weights.{epoch:02d}-{loss:.4f}-{val_loss:.4f}.hdf5",
monitor="val_loss",
verbose=1,
save_best_only=True,
mode="auto")
model.fit(
x=dataset_train,
epochs=epochs,
verbose=1,
steps_per_epoch=steps_per_epoch_train,
validation_data=dataset_test,
validation_steps=steps_per_epoch_test,
callbacks=[cp_cb])
tensorflow.keras.Model.fit ()
wurde geändert, um ein DataSet für Trainingsdaten verwenden zu können.
tf.keras.Model | TensorFlow Core v2.1.0
x: Input data. It could be: (Weggelassen) A tf.data dataset. Should return a tuple of either (inputs, targets) or (inputs, targets, sample_weights).
Zuvor mussten Sie beim Lernen aus einem DataSet Daten in die Ebene "Eingabe" einfügen. Daher war es mühsam, zwei Modelle mit gemeinsamen Gewichten zu erstellen, eines für das Training und eines für die Auswertung. In TensorFlow 2.x (Keras enthalten in) können Sie Model.fit ()
ein DataSet zuweisen, sodass Sie nur ein Modell benötigen. Sie müssen keinen eigenen Iterator mehr mit make_one_shot_iterator ()
erstellen. Du hast es geschafft!
Außerdem war es jetzt möglich, dem Argument validation_data
von tensorflow.keras.Model.fit ()
ein DataSet zur Auswertung zu geben. Daher ist es nicht mehr erforderlich, einen Rückruf für die Bewertung selbst zu erstellen (obwohl der Fortschrittsbalken zum Zeitpunkt der Bewertung nicht angezeigt wird ... Es ist eine Geschichte, selbst eine Lernschleife zu schreiben).
Durch gleichzeitiges Laden mehrerer Dateien können Sie möglicherweise die GPU-Nutzungsrate erhöhen (= schnelleres Lernen).
Teilen und schreiben Sie die Trainingsdaten wie beim letzten Mal. Der einzige Unterschied zum letzten Mal besteht darin, dass "tf.python_io" in "tf.io" geändert wurde.
data2tfrecord.py (Teil)
for i in range(10):
with tf.io.TFRecordWriter(filename_train + "." + str(i)) as writer:
for r in data_train[i::10]:
ex = record2example(r)
writer.write(ex.SerializeToString())
Während des Lernens ändert sich das Erstellen von dataset_train
wie folgt.
train.py (Teil)
dataset_train = tf.data.Dataset.from_tensor_slices(["train.tfrecords.{}".format(i) for i in range(10)]) \
.interleave(
lambda filename: tf.data.TFRecordDataset(filename).map(parse_example, num_parallel_calls=1),
cycle_length=10) \
.shuffle(batch_size * 100) \
.batch(batch_size) \
.prefetch(1) \
.repeat(-1)
Die Funktion "tf.contrib.data.parallel_interleave ()" (später "tf.data.experimental.parallel_interleave ()") im vorherigen Artikel wurde offiziell als Methode von DataSet integriert. Es ist also etwas einfacher zu schreiben. Es verhält sich jedoch wie "sloppy = False". Es scheint also, dass Sie Optionen mit "with_options ()" angeben müssen, um das Verhalten zu erhalten, das "sloppy = True" entspricht. tf.data.experimental.parallel_interleave | TensorFlow Core v2.1.0
Es gibt einige Änderungen, aber es ist im Allgemeinen einfacher zu schreiben, so dass ich das Gefühl hatte, keine Angst haben zu müssen. Sie können erwarten, dass sich die Kernleistung verbessert (stimmt das?), Und lassen Sie uns mit TensorFlow 2 viele Daten untersuchen!
Recommended Posts