tf.keras сверточная архитектура не работает - PullRequest
1 голос
/ 17 апреля 2020

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

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)

Во-первых, у меня странное поведение model.summary (), который содержит:

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

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

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....

, которая для моего понимания вообще не имеет смысла. Мой генератор возвращает [batch, x-dim, y-dim, channel] (я пробовал также с [batch, channel, x-dim, y-dim], но тоже не повезло). И в этом случае пакет равен 1, а не 120. Как я уже сказал, я не могу решать / устранять эти проблемы, несмотря ни на что, поэтому я был бы очень признателен за вашу помощь. Я совсем новичок в DL, но не в python, и я использую Tensorflow-2.1.0, в python -3.7

Большое спасибо.

Ответы [ 2 ]

3 голосов
/ 17 апреля 2020

Вот рабочий код.

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)

Вы неправильно распаковали архив с генератором. Я напечатал вывод в список, чтобы он был подписан. Один из полезных приемов - печатать формы и длины X, y на каждом шаге, чтобы выяснить, где находится ошибка.

Обновление:

Да, именно так, но вам нужно пройти тензор формы [партия, 256, 256, 3]. Но если a является списком, а a [0] имеет форму [1, 256, 256, 3], то вам нужно передать [0] в модель, и это то, что я сделал. Но вы проходили мимо. Но a - это список, а не numpy массив / тензор, и даже если мы приведем его к массиву numpy, мы получим shape = (1, 1, 256, 256, 3) - что недопустимо.

Кроме того, в ваших generator_data, почему вы используете ненужную секунду l oop?

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))
0 голосов
/ 18 апреля 2020

Мне удалось решить эти проблемы путем ночного обновления до tf-2.2 и использования модуля tf.data.

Если у вас возникла та же проблема, посмотрите здесь:

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)
...