Каковы лучшие практики для обучения модели на большом наборе данных - PullRequest
2 голосов
/ 04 мая 2020

Мне нужно обучить модель на наборе данных, который требует больше памяти, чем мой GPU. Какова наилучшая практика подачи набора данных в модель?

Вот мои шаги:

  1. Прежде всего, я загружаю набор данных с помощью batch_size
BATCH_SIZE=32

builder = tfds.builder('mnist')
builder.download_and_prepare()
datasets  = builder.as_dataset(batch_size=BATCH_SIZE)
второй шаг я готовлю данные
for record in raw_train_ds.take(1):
    train_images, train_labels = record['image'],  record['label']
    print(train_images.shape)
    train_images  = train_images.numpy().astype(np.float32) / 255.0
    train_labels = tf.keras.utils.to_categorical(train_labels)
и затем я передаю данные в модель
history = model.fit(train_images,train_labels, epochs=NUM_EPOCHS, validation_split=0.2)

, но на шаге 2 я подготовил данные для первой партии и пропустил остальные партии, потому что model.fit выходит из l oop scope (который, как я понимаю, работает только для одной первой партии).
С другой стороны, я не могу удалить take (1) и переместить метод model.fit под цикл. Потому что да, в этом случае я буду обрабатывать все пакеты, но в то же время model.fill будет вызываться в конце каждой итерации, и в этом случае он также не будет работать должным образом

, поэтому как Я должен изменить свой код, чтобы иметь возможность правильно работать с большим набором данных, используя model.fit? не могли бы вы указать статью, какие-либо документы или просто посоветовать, как с этим бороться? спасибо

Обновление В моем посте ниже (подход 1) я описываю один подход о том, как решить проблему - есть ли другие лучшие подходы или это единственный способ, как решить эту проблему?

Ответы [ 2 ]

2 голосов
/ 04 мая 2020

Вы можете передать весь набор данных на fit для обучения. Как видно из документации , одно из возможных значений первого параметра:

  • A tf.data набор данных. Должен возвращать кортеж либо (inputs, targets), либо (inputs, targets, sample_weights).

Так что вам просто нужно преобразовать ваш набор данных в этот формат (кортеж с входом и целью) и передать его fit:

BATCH_SIZE=32

builder = tfds.builder('mnist')
builder.download_and_prepare()
datasets = builder.as_dataset(batch_size=BATCH_SIZE)
raw_train_ds = datasets['train']
train_dataset_fit = raw_train_ds.map(
    lambda x: (tf.cast.dtypes(x['image'], tf.float32) / 255.0, x['label']))
history = model.fit(train_dataset_fit, epochs=NUM_EPOCHS)

Одна из проблем заключается в том, что он не поддерживает параметр validation_split, но, как показано в , это руководство , tfds уже дает вам функциональность для разделения данных. Поэтому вам просто нужно получить набор тестовых данных, преобразовать его, как указано выше, и передать его как validation_data в fit.

1 голос
/ 05 мая 2020

Подход 1

Спасибо @jdehesa Я изменил свой код:

  1. загрузить набор данных - на самом деле, он не загружает данные в память до первого вызова 'next' из итератор набора данных. и даже тогда, я думаю, итератор загрузит часть данных (пакет) с размером, равным BATCH_SIZE
raw_train_ds, raw_validation_ds = builder.as_dataset(split=["train[:90%]", "train[10%:]"], batch_size=BATCH_SIZE)
собрал все необходимые преобразования в один метод
def prepare_data(x):
    train_images, train_labels = x['image'],  x['label']
# TODO: resize image
    train_images = tf.cast(train_images,tf.float32)/ 255.0 
    # train_labels = tf.keras.utils.to_categorical(train_labels,num_classes=NUM_CLASSES) 
    train_labels = tf.one_hot(train_labels,NUM_CLASSES) 
    return (train_images, train_labels)
применил эти преобразования к каждому элементу в пакете (наборе данных), используя метод td.data.Dataset.map
train_dataset_fit = raw_train_ds.map(prepare_data)
, а затем передал этот набор данных в model.fit - насколько я понимаю, model.fit будет перебирать все пакеты в наборе данных.
train_dataset_fit = raw_train_ds.map(prepare_data)
history = model.fit(train_dataset_fit, epochs=NUM_EPOCHS)
...