Ceci est une version mise à jour de l'article précédent. Comment entraîner une grande quantité de données avec TFRecord & DataSet dans TensorFlow & Keras-Qiita
Une chose que je veux faire est "Je veux un moyen efficace d'entraîner d'énormes données qui ne tiennent pas dans la mémoire." C'est une méthode qui permet de traiter la lecture des données CPU et le calcul GPU en parallèle. Apprenez efficacement à partir des données enregistrées dans un format spécifique à l'aide de l'API DataSet.
Avec la sortie de TensorFlow 2, les noms des modules ont changé par rapport aux versions précédentes de l'article, et certains traitements sont devenus plus faciles à écrire. Dans cet article, je présenterai comment écrire dans TensorFlow 2, en me concentrant sur les différences par rapport au précédent. De plus, je changerai Keras pour utiliser celui inclus dans TensorFlow.
Cet article utilise Python 3.6.9 + TensorFlow 2.1.0 sous Linux (Ubuntu 18.04).
À partir de TensorFlow 1.15 / 2.1, les versions CPU et GPU du package pip ont été intégrées. Par conséquent, il y a des gens qui veulent l'essayer facilement avec le CPU et des gens qui veulent le transformer sérieusement avec le GPU.
pip3 install tensorflow==2.1.0
C'est acceptable. Veuillez noter que si vous souhaitez utiliser le GPU, vous devez configurer CUDA 10.1. GPU support | TensorFlow
Il existe un format de données unique (TFRecord) qui permet à TensorFlow de calculer efficacement. Créons un TFRecord à partir de données existantes à l'aide de l'API DataSet.
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"
# ===Lire les données MNIST===
#Par souci de simplicité, supposons que les mêmes données de vérification que les données d'évaluation sont utilisées pour les données de vérification pendant l'entraînement.
(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,)
#Pré-traitement
#Pixel[0, 1]Convertir en type float32
#De plus, pour l'enregistrement TFR, rendez le montant de la caractéristique unidimensionnel (la ligne correspond à l'enregistrement)
x_train = x_train.reshape((-1, 28*28)).astype("float32") / 255.0
x_test = x_test.reshape((-1, 28*28)).astype("float32") / 255.0
#L'étiquette est également de type float32
y_train = y_train.reshape((-1, 1)).astype("float32")
y_test = y_test.reshape((-1, 1)).astype("float32")
#Combinez des fonctionnalités et des étiquettes pour l'enregistrement TFR
data_train = np.c_[x_train, y_train]
data_test = np.c_[x_test, y_test]
#En fait, les données que vous souhaitez apprendre sont converties au même format et créées.
#Si toutes les données ne tiennent pas dans la mémoire, dans la phase d'écriture suivante
#Vous pouvez le faire petit à petit et répéter l'écriture.
#Écrire les données d'entraînement dans TFRecord
with tf.io.TFRecordWriter(filename_train) as writer:
for r in data_train:
ex = record2example(r)
writer.write(ex.SerializeToString())
#Écrire les données d'évaluation dans TFRecord
with tf.io.TFRecordWriter(filename_test) as writer:
for r in data_test:
ex = record2example(r)
writer.write(ex.SerializeToString())
C'est presque le même que la dernière fois, mais avec la mise à jour de la version de TensorFlow, le paquet tensorflow.python_io
a disparu, et les fonctions liées à TFRecord ont été ajoutées à tensorflow.io
.
De plus, depuis que j'ai changé pour utiliser Keras inclus dans TensorFlow, «import» a changé, mais la méthode de lecture du jeu de données MNIST lui-même n'a pas changé.
Si vous n'avez pas de bibliothèque pour le calcul GPU, vous obtiendrez un AVERTISSEMENT lié à CUDA (les libcublas sont introuvables, etc.), mais si vous voulez juste l'essayer légèrement sur le CPU, vous n'avez pas à vous en soucier.
Cela a un peu changé depuis la dernière fois. Commençons par le code, puis expliquons les différences.
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
#Paramètres d'apprentissage
batch_size = 32
epochs = 10
#Paramètre de fonctionnalité
num_classes = 10 #Type d'étiquette. 0-10 types de 9
feature_dim = 28*28 #La dimension de la quantité d'entités. Manipuler comme 1D pour plus de simplicité
#Nombre de données d'apprentissage / d'évaluation. Vérifiez à l'avance.
#Notez que lorsque vous utilisez plusieurs TFRecords, le nombre ci-dessous est la somme de tous les fichiers.
num_records_train = 60000
num_records_test = 10000
#Nombre de mini-lots par époque. Utilisé lors de l'apprentissage.
steps_per_epoch_train = (num_records_train-1) // batch_size + 1
steps_per_epoch_test = (num_records_test-1) // batch_size + 1
#Décoder 1 TFRecord
def parse_example(example):
features = tf.io.parse_single_example(
example,
features={
#Spécifiez le nombre de dimensions lors de la lecture de la liste
"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
# ===Préparer les données du fichier TFRecord pour l'apprentissage et l'évaluation===
dataset_train = tf.data.TFRecordDataset(["train.tfrecords"]) \
.map(parse_example) \
.shuffle(batch_size * 100) \
.batch(batch_size).repeat(-1)
#Lorsque vous utilisez plusieurs fichiers TFRecord ci-dessus, spécifiez une liste de noms de fichiers.
# 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)
# ===Définition du modèle===
#Cette fois, une seule couche intermédiaire de 512 dimensions est spécifiée.
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()
#Perte même si l'étiquette est une variable catégorielle="sparse_categorical_crossentropy"Peut apprendre avec
#Étiqueter un-Si chaud vectorisé, perte="categorical_crossentropy"devenir
model.compile(
loss="sparse_categorical_crossentropy",
optimizer=RMSprop(),
metrics=["accuracy"])
# ===Apprentissage===
#Enregistrez le modèle au milieu
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 () '' a changé pour pouvoir prendre un DataSet pour les données d'entraînement. tf.keras.Model | TensorFlow Core v2.1.0
x: Input data. It could be: (Omis) A tf.data dataset. Should return a tuple of either (inputs, targets) or (inputs, targets, sample_weights).
Auparavant, lors de l'apprentissage à partir d'un DataSet, vous deviez brancher des données dans la couche `ʻInput, il y avait donc une procédure fastidieuse de création de deux modèles avec des poids partagés, un pour la formation et un pour l'évaluation. Dans TensorFlow 2.x (Keras inclus dans), vous pouvez donner un DataSet à
Model.fit () '', vous n'avez donc besoin que d'un seul modèle. Vous n'avez plus besoin de créer votre propre itérateur avec `` make_one_shot_iterator () ''. Tu l'as fait!
De plus, il était désormais possible de donner un DataSet pour évaluation à l'argument validation_data '' de
tensorflow.keras.Model.fit () ''. Par conséquent, il n'est plus nécessaire de créer un callback pour l'évaluation par vous-même (bien que la barre de progression au moment de l'évaluation n'apparaisse pas ... C'est une histoire pour écrire une boucle d'apprentissage par vous-même).
En chargeant plusieurs fichiers en parallèle, vous pourrez peut-être augmenter le taux d'utilisation du GPU (= accélérer l'apprentissage).
Divisez et écrivez les données d'entraînement de la même manière que la dernière fois. La seule différence par rapport à la dernière fois est que tf.python_io
a changé en tf.io
.
data2tfrecord.py (partie)
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())
Pendant l'apprentissage, la création de `` dataset_train '' change comme suit.
train.py (partie)
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)
La fonction équivalente à tf.contrib.data.parallel_interleave () '' (plus tard
tf.data.experimental.parallel_interleave () '') dans l'article précédent a été officiellement incorporée en tant que méthode de DataSet. C'est donc un peu plus facile à écrire. Cependant, il se comporte comme sloppy = False
, il semble donc que vous deviez spécifier des options avec with_options () '' pour que cela fonctionne comme
sloppy = True``.
tf.data.experimental.parallel_interleave | TensorFlow Core v2.1.0
Il y a des changements, mais c'est généralement plus facile à écrire, donc je sentais que je n'avais pas à avoir peur. Vous pouvez vous attendre à ce que les performances de base s'améliorent (est-ce vrai?), Et explorons beaucoup de données avec TensorFlow 2!
Recommended Posts