tf.data.Dataset: el argumento `batch_size` no debe especificarse para el tipo de entrada dado

10

Estoy usando Talos y Google colab TPU para ejecutar el ajuste de hiperparámetro de un modelo Keras . Tenga en cuenta que estoy usando Tensorflow 1.15.0 y Keras 2.2.4-tf.

import os
import tensorflow as tf
import talos as ta
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from sklearn.model_selection import train_test_split

def iris_model(x_train, y_train, x_val, y_val, params):

    # Specify a distributed strategy to use TPU
    resolver = tf.contrib.cluster_resolver.TPUClusterResolver(tpu='grpc://' + os.environ['COLAB_TPU_ADDR'])
    tf.contrib.distribute.initialize_tpu_system(resolver)
    strategy = tf.contrib.distribute.TPUStrategy(resolver)

    # Use the strategy to create and compile a Keras model
    with strategy.scope():
      model = Sequential()
      model.add(Dense(32, input_shape=(4,), activation=tf.nn.relu, name="relu"))
      model.add(Dense(3, activation=tf.nn.softmax, name="softmax"))
      model.compile(optimizer=Adam(learning_rate=0.1), loss=params['losses'])

    # Convert data type to use TPU
    x_train = x_train.astype('float32')
    x_val = x_val.astype('float32')

    dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
    dataset = dataset.cache()
    dataset = dataset.shuffle(1000, reshuffle_each_iteration=True).repeat()
    dataset = dataset.batch(params['batch_size'], drop_remainder=True)

    # Fit the Keras model on the dataset
    out = model.fit(dataset, batch_size=params['batch_size'], epochs=params['epochs'], validation_data=[x_val, y_val], verbose=0, steps_per_epoch=2)

    return out, model

# Load dataset
X, y = ta.templates.datasets.iris()

# Train and test set
x_train, x_val, y_train, y_val = train_test_split(X, y, test_size=0.30, shuffle=False)

# Create a hyperparameter distributions 
p = {'losses': ['logcosh'], 'batch_size': [128, 256, 384, 512, 1024], 'epochs': [10, 20]}

# Use Talos to scan the best hyperparameters of the Keras model
scan_object = ta.Scan(x_train, y_train, params=p, model=iris_model, experiment_name='test', x_val=x_val, y_val=y_val, fraction_limit=0.1)

Después de convertir el conjunto de trenes a un conjunto de datos tf.data.Dataset, obtengo el siguiente error al ajustar el modelo con out = model.fit:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-c812209b95d0> in <module>()
      8 
      9 # Use Talos to scan the best hyperparameters of the Keras model
---> 10 scan_object = ta.Scan(x_train, y_train, params=p, model=iris_model, experiment_name='test', x_val=x_val, y_val=y_val, fraction_limit=0.1)

8 frames
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/engine/training.py in _validate_or_infer_batch_size(self, batch_size, steps, x)
   1813             'The `batch_size` argument must not be specified for the given '
   1814             'input type. Received input: {}, batch_size: {}'.format(
-> 1815                 x, batch_size))
   1816       return
   1817 

ValueError: The `batch_size` argument must not be specified for the given input type. Received input: <DatasetV1Adapter shapes: ((512, 4), (512, 3)), types: (tf.float32, tf.float32)>, batch_size: 512

Entonces, si sigo esas instrucciones y no configuro el argumento de tamaño de lote en model.fit. Me sale otro error en:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-c812209b95d0> in <module>()
      8 
      9 # Use Talos to scan the best hyperparameters of the Keras model
---> 10 scan_object = ta.Scan(x_train, y_train, params=p, model=iris_model, experiment_name='test', x_val=x_val, y_val=y_val, fraction_limit=0.1)

8 frames
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/engine/training.py in _distribution_standardize_user_data(self, x, y, sample_weight, class_weight, batch_size, validation_split, shuffle, epochs, allow_partial_batch)
   2307             strategy) and not drop_remainder:
   2308           dataset_size = first_x_value.shape[0]
-> 2309           if dataset_size % batch_size == 0:
   2310             drop_remainder = True
   2311 

TypeError: unsupported operand type(s) for %: 'int' and 'NoneType'
Sami Belkacem
fuente
Sería útil para ese último error si pudiera publicar un seguimiento completo de la pila, porque esa función parece llamarse en un montón de lugares en este archivo, por lo que no puedo decir dónde está: github.com/tensorflow/tensorflow /blob/r1.15/tensorflow/python/…
mdaoust
Acabo de editar la pregunta, puede verificar el seguimiento de la pila, gracias por su tiempo y consideración.
Sami Belkacem

Respuestas:

0

del código github :

ValueError se generará si xes un generador o una Sequenceinstancia y batch_sizese especifica como esperamos que los usuarios proporcionen conjuntos de datos por lotes.

Intenta usar batch_size = None

Ioannis Nasios
fuente
Recibo otro error en _distribution_standardize_user_data (self, x, y, sample_weight, class_weight, batch_size, validation_split, shuffle, epochs, allow_partial_batch) TypeError: tipos de operandos no compatibles para *: 'NoneType' y 'int
Sami Belkacem el
también debe establecer steps_per_epoch = None
Ioannis Nasios
No funciona, obtengo otro error: ValueError: intento de convertir un valor (Ninguno) con un tipo no admitido (<clase 'NoneType'>) en un Tensor. Creo que puede reproducir fácilmente el error copiando el programa corto
Sami Belkacem
0

No estoy seguro si lo siguiente se ajustará a su factura, pero hay algo que probar. Todo lo que he hecho es quitar la repetición () del conjunto de datos y batch_size = params ['batch_size'] de model.fit

Si lo anterior no es lo que estás dispuesto a sacrificar, ignora la publicación.

import os
import tensorflow as tf
import talos as ta
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

def iris_model(x_train, y_train, x_val, y_val, params):

    # Specify a distributed strategy to use TPU
    resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='grpc://' + os.environ['COLAB_TPU_ADDR'])
    tf.config.experimental_connect_to_host(resolver.master())
    tf.tpu.experimental.initialize_tpu_system(resolver)
    strategy = tf.distribute.experimental.TPUStrategy(resolver)

    with strategy.scope():
        model = Sequential()
        model.add(Dense(32, input_dim=4, activation=params['activation']))
        model.add(Dense(3, activation='softmax'))
        model.compile(optimizer=params['optimizer'], loss=params['losses'])

    # Convert the train set to a Dataset to use TPU
    dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
    dataset = dataset.cache().shuffle(1000, reshuffle_each_iteration=True).batch(params['batch_size'], drop_remainder=True)

    out = model.fit(dataset, epochs=params['epochs'], validation_data=[x_val, y_val], verbose=0)

    return out, model

x, y = ta.templates.datasets.iris()

p = {'activation': ['relu', 'elu'],
       'optimizer': ['Nadam', 'Adam'],
       'losses': ['logcosh'],
       'batch_size': (20, 50, 5),
       'epochs': [10, 20]}

scan_object = ta.Scan(x, y, model=iris_model, params=p, fraction_limit=0.1, experiment_name='first_test')
Amit
fuente
No funciona: TypeError: tipos de operando no admitidos para *: 'NoneType' e 'int'
Sami Belkacem
0

Ese segundo error que obtienes, _distribution_standardize_user_datacuando no pasas el batch_sizeajuste.

El código que está ejecutando para esa función está aquí:

https://github.com/tensorflow/tensorflow/blob/r1.15/tensorflow/python/keras/engine/training.py#L2192

No publicó un rastreo, pero apuesto a que está fallando en la línea 2294 , ya que ese es el único lugar donde batch_sizese multiplica por algo.

if shuffle:
          # We want a buffer size that is larger than the batch size provided by
          # the user and provides sufficient randomness. Note that larger
          # numbers introduce more memory usage based on the size of each
          # sample.
          ds = ds.shuffle(max(1024, batch_size * 8))

Parece que puedes apagarlo configurando shuffle=False.

fit(ds, shuffle=False,...)

¿Eso funciona?

mdaoust
fuente
Gracias, pero sigo teniendo el mismo error con shuffle = False. Está fallando en la línea 2309, no en 2294.
Sami Belkacem
@SamiBelkacem, eso '
mdaoust
0

¿Podría eliminar estas líneas de su código e intentar:

    dataset = dataset.cache()
    dataset = dataset.shuffle(1000, reshuffle_each_iteration=True).repeat()
    dataset = dataset.batch(params['batch_size'], drop_remainder=True)
WITH THESE:
    dataset = dataset.repeat()
    dataset = dataset.batch(128, drop_remainder=True)
    dataset = dataset.prefetch(1)

De lo contrario, lo que escribió tf.data.Dataset.from_tensor_slicestiene algo que ver con el error.

Rishabh Sahrawat
fuente
Sigue sin funcionar. Como dijiste, tf.data.Dataset tiene algo que ver con el error. Pero, la documentación dice que es necesario incluirlo cuando se usa un TPU en la nube tensorflow.org/guide/tpu#input_datasets
Sami Belkacem