Использование tf.data.Dataset в качестве учебного ввода для модели Keras НЕ работает - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть простой код, который РАБОТАЕТ, для обучения модели Keras в Tensorflow, использующей массивы в качестве функций и меток. Если затем я оберну эти пустые массивы, используя tf.data.Dataset.from_tensor_slices, чтобы обучить ту же модель Keras с использованием набора данных тензорного потока, я получу ошибку. Я не смог понять, почему (это может быть ошибка в tenorflow или keras, но я также могу что-то упустить). Я на питоне 3, тензор потока 1.10.0, numpy 1.14.5, GPU не задействован.

OBS1 : Возможность использования tf.data.Dataset в качестве входа Keras показана в https://www.tensorflow.org/guide/keras, в разделе " Input tf.data datasets ".

OBS2 : В приведенном ниже коде код под "#Train with numpy arrays" выполняется с использованием массивов numpy. Если этот код закомментирован и вместо него используется код «#Train with tf.data datasets», ошибка будет воспроизведена.

OBS3 : В строке 13, которая комментируется и начинается с "###WORKAROUND 1###", если комментарий удаляется и строка используется для tf.data.Dataset inputs, ошибка меняется, хотя я могу не совсем понимаю, почему.

Полный код:

import tensorflow as tf
import numpy as np

np.random.seed(1)
tf.set_random_seed(1)

print(tf.__version__)
print(np.__version__)

#Import mnist dataset as numpy arrays
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()#Import
x_train, x_test = x_train / 255.0, x_test / 255.0 #normalizing
###WORKAROUND 1###y_train, y_test = (y_train.astype(dtype='float32'), y_test.astype(dtype='float32'))

x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1]*x_train.shape[2])) #reshaping 28 x 28 images to 1D vectors, similar to Flatten layer in Keras

batch_size = 32
#Create a tf.data.Dataset object equivalent to this data
tfdata_dataset_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
tfdata_dataset_train = tfdata_dataset_train.batch(batch_size).repeat()

#Creates model
keras_model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(512, activation=tf.nn.relu),
    tf.keras.layers.Dropout(0.2, seed=1),
    tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

#Compile the model
keras_model.compile(optimizer='adam',
                    loss=tf.keras.losses.sparse_categorical_crossentropy,
                    metrics=['accuracy'])

#Train with numpy arrays
keras_training_history = keras_model.fit(x_train,
                y_train,
                initial_epoch=0,
                epochs=1,
                batch_size=batch_size
                )

#Train with tf.data datasets
#keras_training_history = keras_model.fit(tfdata_dataset_train,
#                initial_epoch=0,
#                epochs=1,
#                steps_per_epoch=60000//batch_size
#                )

print(keras_training_history.history)

Ошибка при использовании tf.data.Dataset в качестве ввода :

(...)
ValueError: Tensor conversion requested dtype uint8 for Tensor with dtype float32: 'Tensor("metrics/acc/Cast:0", shape=(?,), dtype=float32)'

During handling of the above exception, another exception occurred:

(...)
TypeError: Input 'y' of 'Equal' Op has type float32 that does not match type uint8 of argument 'x'.

Ошибка при удалении комментария из строки 13, как указано выше в OBS3 , составляет :

(...)
tensorflow.python.framework.errors_impl.InvalidArgumentError: In[0] is not a matrix
     [[Node: dense/MatMul = MatMul[T=DT_FLOAT, _class=["loc:@training/Adam/gradients/dense/MatMul_grad/MatMul_1"], transpose_a=false, transpose_b=false, _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_sequential_input_0_0, dense/MatMul/ReadVariableOp)]]

Буду признателен за любую помощь, включая комментарии о том, что вы смогли воспроизвести ошибки, поэтому я могу сообщить об ошибке, если это так.

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Установка сборки tf-nightly вместе с изменением dtypes некоторых тензоров (ошибка меняется после установки tf-nightly) решила проблему, поэтому это проблема, которая (надеюсь) будет решена в 1.11.

Материалы по теме: https://github.com/tensorflow/tensorflow/issues/21894

0 голосов
/ 07 сентября 2018

Я только что обновился до Tensorflow 1.10, чтобы выполнить этот код . Я думаю, что это ответ, который также обсуждается в другой теме Stackoverflow

Этот код выполняется, но только если я удаляю нормализацию, поскольку эта строка, кажется, использует слишком много памяти процессора. Я вижу сообщения, указывающие на это. Я тоже уменьшил ядра.

import tensorflow as tf
import numpy as np
from tensorflow.keras.layers import Conv2D, MaxPool2D, Flatten, Dense, Dropout, Input

np.random.seed(1)
tf.set_random_seed(1)

batch_size = 128
NUM_CLASSES = 10

print(tf.__version__)

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
#x_train, x_test = x_train / 255.0, x_test / 255.0 #normalizing

def tfdata_generator(images, labels, is_training, batch_size=128):
    '''Construct a data generator using tf.Dataset'''

    def preprocess_fn(image, label):
        '''A transformation function to preprocess raw data
        into trainable input. '''
        x = tf.reshape(tf.cast(image, tf.float32), (28, 28, 1))
        y = tf.one_hot(tf.cast(label, tf.uint8), NUM_CLASSES)
        return x, y

    dataset = tf.data.Dataset.from_tensor_slices((images, labels))
    if is_training:
        dataset = dataset.shuffle(1000)  # depends on sample size

    # Transform and batch data at the same time
    dataset = dataset.apply(tf.contrib.data.map_and_batch(
        preprocess_fn, batch_size,
        num_parallel_batches=2,  # cpu cores
        drop_remainder=True if is_training else False))
    dataset = dataset.repeat()
    dataset = dataset.prefetch(tf.contrib.data.AUTOTUNE)

    return dataset

training_set = tfdata_generator(x_train, y_train,is_training=True, batch_size=batch_size)
testing_set  = tfdata_generator(x_test, y_test, is_training=False, batch_size=batch_size)

inputs = Input(shape=(28, 28, 1))
x = Conv2D(32, (3, 3), activation='relu', padding='valid')(inputs)
x = MaxPool2D(pool_size=(2, 2))(x)
x = Conv2D(64, (3, 3), activation='relu')(x)
x = MaxPool2D(pool_size=(2, 2))(x)
x = Flatten()(x)
x = Dense(512, activation='relu')(x)
x = Dropout(0.5)(x)
outputs = Dense(NUM_CLASSES, activation='softmax')(x)

keras_model =  tf.keras.Model(inputs, outputs)

#Compile the model
keras_model.compile('adam', 'categorical_crossentropy', metrics=['acc'])

#Train with tf.data datasets
keras_training_history = keras_model.fit(
                            training_set.make_one_shot_iterator(),
                            steps_per_epoch=len(x_train) // batch_size,
                            epochs=5,
                            validation_data=testing_set.make_one_shot_iterator(),
                            validation_steps=len(x_test) // batch_size,
                            verbose=1)
print(keras_training_history.history)
...