TensorFlow2 / Keras: кажется, что input_shape не дает эффекта при создании подклассов keras.Model - PullRequest
0 голосов
/ 31 марта 2020

При доступе к выходу промежуточного уровня я всегда получал сообщение об ошибке: AttributeError: Layer l has no inbound nodes. Я прочитал, что для определения этой проблемы необходимо определить input_shape на начальном уровне:

class MyModel(tf.keras.Model):
    def __init__(self):
        super(MyModel, self).__init__()
        self.flatten = tf.keras.layers.Flatten(input_shape=(28, 28))
        self.dense = tf.keras.layers.Dense(64, activation=tf.nn.relu)
        self.classifier = tf.keras.layers.Dense(10, name='classifier')

    def call(self, inputs):
        x = self.flatten(inputs)
        x = self.dense(x)
        return self.classifier(x)

К сожалению, это не сработало для меня.

После этой неудачной попытки я попытался восстановить свою модель, используя tf.keras.Sequential, и снова указал input_shape для первого слоя:

tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(64, activation=tf.nn.relu),
    tf.keras.layers.Dense(10, name='classifier')
])

Это, с другой стороны, сработало!

Поэтому я спросил себя, почему первый подход не сработал. Чтобы проверить это, я указал произвольное / неправильное значение input_shapes для подклассовой модели следующим образом:

class WrongInputShapeModel(tf.keras.Model):
    def __init__(self):
        super(WrongInputShapeModel, self).__init__()
        self.flatten = tf.keras.layers.Flatten(input_shape=(42, 42, 42))
        # ...

Я заметил, что эта модель все еще функционирует с MNIST (который имеет 28x28 изображений). Это позволило мне поверить, что ключевое слово input_shape не влияет на определение подкласса модели tf.keras.Model.

Это ошибка или я что-то упустил?

1 Ответ

0 голосов
/ 01 апреля 2020

Из кода подкласса вашей модели выглядит, что вы не возвращаете вывод прямого прохода модели. Возможно, по этой причине это не сработало.

Это должно сработать:

import tensorflow as tf

class MyModel(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.flatten = tf.keras.layers.Flatten()
        self.dense = tf.keras.layers.Dense(64, activation=tf.nn.relu)
        self.classifier = tf.keras.layers.Dense(10, name='classifier', activation='softmax')

    def call(self, inputs):
        x = self.flatten(inputs)
        x = self.dense(x)
        return self.classifier(x)

А затем, просто в качестве примера:

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

model = MyModel()
model.compile(optimizer=tf.keras.optimizers.Adam(1e-3), loss=tf.keras.losses.SparseCategoricalCrossentropy(),
             metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])
history = model.fit(x_train, y_train, epochs=5)

Теперь, Flatten Форма ввода на самом деле определяется формой входного тензора слоя, поэтому она не требует аргумента input_shape. input_shape является атрибутом Layer, так что вы можете передать его, но прямой проход слоя не использует его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...