El siguiente problema es una reducción de un problema real que tuve mientras diseñaba un arco de autoencoder elemental. El siguiente ejemplo es suficiente para reproducir exactamente el error que tuve. Lo he estado intentando durante dos días, pero no puedo encontrar ninguna manera de salir de eso.

import tensorflow as tf
import random
import os

RES = [256, 256]
def generator_data(n):
    for i in range(n):
        for j in range(6):
            yield tf.zeros((1, 256, 256, 3)), tf.zeros((1, 256, 256, 3))

def mymodel():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Conv2D(8, (3, 3), activation='relu', padding='same'))
    # 256 x 256 x 8
    model.add(tf.keras.layers.MaxPooling2D((2, 2), padding='same'))
    # 128 x 128 x 8
    model.add(tf.keras.layers.Conv2D(16, (3, 3), activation='relu', padding='same'))
    # 128 x 128 x 16
    model.add(tf.keras.layers.MaxPooling2D((2, 2), padding='same'))
    # 64 x 64 x 16
    model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
    # 64 x 64 x 32
    model.add(tf.keras.layers.MaxPooling2D((2, 2), padding='same'))
    # 32 x 32 x 32

    # 32 x 32 x 32
    model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
    # 32 x 32 x 32
    model.add(tf.keras.layers.UpSampling2D((2, 2)))
    # 64 x 64 x 32
    model.add(tf.keras.layers.Conv2D(16, (3, 3), activation='relu', padding='same'))
    # 64 x 64 x 16
    model.add(tf.keras.layers.UpSampling2D((2, 2)))
    # 128 x 128 x 16
    model.add(tf.keras.layers.Conv2D(8, (3, 3), activation='relu', padding='same'))
    # 128 x 128 x 8
    model.add(tf.keras.layers.UpSampling2D((2, 2)))
    # 256 x 256 x 8
    model.add(tf.keras.layers.Conv2D(1, (3, 3), activation='sigmoid', padding='same'))
    return model


if __name__ == "__main__":
    # import some data to play with
    x_val, y_val = zip(*generator_data(20))

    model = mymodel()
    optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
    model.compile(optimizer=optimizer, loss=tf.keras.losses.MeanSquaredError())
    model(tf.zeros((1, 256, 256, 3)))
    model.summary()

    # generator_data(train_list)
    model.fit(x=generator_data(1000),
        validation_data=(list(x_val), list(y_val)),
        verbose=1, epochs=1000)

En primer lugar, tengo el comportamiento extraño de un model.summary () que contiene:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
conv2d (Conv2D)              multiple                  224
_________________________________________________________________
max_pooling2d (MaxPooling2D) multiple                  0
_________________________________________________________________
conv2d_1 (Conv2D)            multiple                  1168
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 multiple                  0
_________________________________________________________________
conv2d_2 (Conv2D)            multiple                  4640
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 multiple                  0
_________________________________________________________________
conv2d_3 (Conv2D)            multiple                  9248
_________________________________________________________________
up_sampling2d (UpSampling2D) multiple                  0
_________________________________________________________________
conv2d_4 (Conv2D)            multiple                  4624
_________________________________________________________________
up_sampling2d_1 (UpSampling2 multiple                  0
_________________________________________________________________
conv2d_5 (Conv2D)            multiple                  1160
_________________________________________________________________
up_sampling2d_2 (UpSampling2 multiple                  0
_________________________________________________________________
conv2d_6 (Conv2D)            multiple                  73
=================================================================
Total params: 21,137
Trainable params: 21,137
Non-trainable params: 0

Solo múltiples en forma de salida. Lo he buscado aquí pero la solución no parece trabajo. Pero en segundo lugar y más importante, recibo el error:

ValueError: Error when checking model input: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 1 array(s), for inputs ['input_1'] but instead got the following list of 120 arrays: [<tf.Tensor: shape=(1, 256, 256, 3), dtype=float32, numpy=
array([[[[0., 0., 0.],
         [0., 0., 0.],
         [0., 0., 0.],
         ...,
         [0., 0., 0.],
         [0., 0., 0.],
         [0....

Lo que para mi inutilidad no tiene ningún sentido. Mi generador devuelve [batch, x-dim, y-dim, channel] (también lo intenté con [batch, channel, x-dim, y-dim] pero tampoco tuve suerte). Y en este caso el lote es igual a 1 y no a 120. Como dije, no puedo abordar / depurar estos problemas sin importar qué, así que realmente agradecería su ayuda. Soy bastante nuevo en DL pero no en Python y estoy usando Tensorflow-2.1.0, en Python-3.7

Muchas gracias.

1
John Sig 17 abr. 2020 a las 00:54

2 respuestas

Aquí está el código de trabajo.

import tensorflow as tf
import random
import os
import numpy as np

RES = [256, 256]
def generator_data(n):
    for i in range(n):
        for j in range(1):
            yield tf.zeros((1, 256, 256, 3)), tf.zeros((1, 256, 256, 3))

def mymodel():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Conv2D(8, (3, 3), activation='relu', padding='same'))
    # 256 x 256 x 8
    model.add(tf.keras.layers.MaxPooling2D((2, 2), padding='same'))
    # 128 x 128 x 8
    model.add(tf.keras.layers.Conv2D(16, (3, 3), activation='relu', padding='same'))
    # 128 x 128 x 16
    model.add(tf.keras.layers.MaxPooling2D((2, 2), padding='same'))
    # 64 x 64 x 16
    model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
    # 64 x 64 x 32
    model.add(tf.keras.layers.MaxPooling2D((2, 2), padding='same'))
    # 32 x 32 x 32

    # 32 x 32 x 32
    model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
    # 32 x 32 x 32
    model.add(tf.keras.layers.UpSampling2D((2, 2)))
    # 64 x 64 x 32
    model.add(tf.keras.layers.Conv2D(16, (3, 3), activation='relu', padding='same'))
    # 64 x 64 x 16
    model.add(tf.keras.layers.UpSampling2D((2, 2)))
    # 128 x 128 x 16
    model.add(tf.keras.layers.Conv2D(8, (3, 3), activation='relu', padding='same'))
    # 128 x 128 x 8
    model.add(tf.keras.layers.UpSampling2D((2, 2)))
    # 256 x 256 x 8
    model.add(tf.keras.layers.Conv2D(1, (3, 3), activation='sigmoid', padding='same'))
    return model


if __name__ == "__main__":
    # import some data to play with
    z = list(zip(*generator_data(2)))

    x_val = z[0][0]
    y_val = z[0][1]

    model = mymodel()
    optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
    model.compile(optimizer=optimizer, loss=tf.keras.losses.MeanSquaredError())
    model(tf.zeros((1, 256, 256, 3)))
    model.summary()


    print(x_val.numpy().shape)
    print(y_val.numpy().shape)
    model.fit(x=generator_data(10),
        validation_data=(x_val, y_val),
        verbose=1, epochs=1)

Estaba usando descomprimir con el generador de manera incorrecta. Escribí la salida en una lista para que se pueda suscribir. Uno de los trucos útiles es imprimir las formas y len de la X, y en cada paso para descubrir dónde está el error.

Actualizar:

Sí, exactamente, pero necesita pasar un tensor de forma [lote, 256, 256, 3]. Pero si a es una lista y un [0] tiene forma [1, 256, 256, 3], entonces necesita pasar un [0] al modelo y eso es lo que hice. Pero, estabas pasando a. Pero a es una lista, no una matriz / tensor numpy e incluso si lo convertimos en una matriz numpy obtendremos shape = (1, 1, 256, 256, 3), que no es válido.

Además, en su generador_datos, ¿por qué está utilizando un segundo bucle innecesario?

def generator_data(n):
    for i in range(n):
        for j in range(1): # ??????? Why?
            yield tf.zeros((1, 256, 256, 3)), tf.zeros((1, 256, 256, 3))
3
Zabir Al Nazi 18 abr. 2020 a las 08:16

Logré resolver esos problemas actualizando a tf-2.2 todas las noches y usando el módulo tf.data.

En caso de que tenga el mismo problema, eche un vistazo aquí:

import tensorflow as tf
import random
import os
from functools import partial

RES = [256, 256]
def generator_data(n):
    for i in range(n):
        for j in range(6):
            yield tf.zeros((1, 256, 256, 3)), tf.zeros((1, 256, 256, 3))

def generator_data_val(n):
    for i in range(n):
        for j in range(6):
            yield tf.zeros((256, 256, 3)), tf.zeros((256, 256, 3))


def model():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Conv2D(8, (3, 3), activation='relu', padding='same', input_shape=(256, 256, 3)))
    # 256 x 256 x 8
    model.add(tf.keras.layers.MaxPooling2D((2, 2), padding='same'))
    # 128 x 128 x 8
    model.add(tf.keras.layers.Conv2D(16, (3, 3), activation='relu', padding='same'))
    # 128 x 128 x 16
    model.add(tf.keras.layers.MaxPooling2D((2, 2), padding='same'))
    # 64 x 64 x 16
    model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
    # 64 x 64 x 32
    model.add(tf.keras.layers.MaxPooling2D((2, 2), padding='same'))
    # 32 x 32 x 32

    # 32 x 32 x 32
    model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
    # 32 x 32 x 32
    model.add(tf.keras.layers.UpSampling2D((2, 2)))
    # 64 x 64 x 32
    model.add(tf.keras.layers.Conv2D(16, (3, 3), activation='relu', padding='same'))
    # 64 x 64 x 16
    model.add(tf.keras.layers.UpSampling2D((2, 2)))
    # 128 x 128 x 16
    model.add(tf.keras.layers.Conv2D(8, (3, 3), activation='relu', padding='same'))
    # 128 x 128 x 8
    model.add(tf.keras.layers.UpSampling2D((2, 2)))
    # 256 x 256 x 8
    model.add(tf.keras.layers.Conv2D(1, (3, 3), activation='sigmoid', padding='same'))
    return model


if __name__ == "__main__":
    # import some data to play with
    x_val, y_val = zip(*generator_data_val(5))
    x_val, y_val = list(x_val), list(y_val)


    model = model()
    optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
    model.compile(optimizer=optimizer, loss=tf.keras.losses.MeanSquaredError())
    model(tf.zeros((1, 256, 256, 3)))
    model.summary()
    train_dataset = generator_data(5)

    gen = partial(generator_data, n=5)
    train_dataset = tf.data.Dataset.from_generator(
        gen, output_types=(tf.float32, tf.float32),
        output_shapes=(tf.TensorShape([1, 256, 256, 3]), tf.TensorShape([1, 256, 256, 3]))).repeat()
    val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val)).batch(2)

    # generator_data(train_list)
    model.fit(x=train_dataset,
        steps_per_epoch=40,
        validation_data=val_dataset,
        verbose=1, epochs=1000)
0
John Sig 18 abr. 2020 a las 11:22