TensorFlow 2.0 - Создание подкласса модели: без входного измерения

Я читал учебник TensorFlow 2.0 и наткнулся на создание подклассов моделей для создания моделей TensorFlow 2.0.

Код, который я нашел, был:

class MyModel(Model):
  def __init__(self):
    super(MyModel, self).__init__()
    self.conv1 = Conv2D(32, 3, activation='relu')
    self.flatten = Flatten()
    self.d1 = Dense(128, activation='relu')
    self.d2 = Dense(10, activation='softmax')

  def call(self, x):
    x = self.conv1(x)
    x = self.flatten(x)
    x = self.d1(x)
    return self.d2(x)

# Create an instance of the model
model = MyModel()

В этом коде меня беспокоит то, что автор кода не определяет входы?

Здесь нет-

self.input_layer = Input(
            shape = (28, 28)
            )

# OR-

self.conv1 = Conv2D(32, 3, activation='relu', input_dim = (28, 28)

Каким образом определенная модель узнает, сколько атрибутов / функций ожидать от обучающих данных?

Спасибо

2 ответа

По словам Франсуа Шоле, ответ на ваш вопрос следующий (при сравнении (функциональный + последовательный и модельный API):

Вы можете делать все это (печатать фигуры ввода / вывода) в функциональной или последовательной модели, потому что эти модели представляют собой статические графики слоев.

Напротив, модель с подклассом - это часть кода Python (метод вызова). Графики слоев здесь нет. Мы не можем знать, как слои связаны друг с другом (потому что это определено в теле вызова, а не как явная структура данных), поэтому мы не можем вывести формы ввода / вывода

Более подробное объяснение этих трех типов доступно здесь: https://medium.com/tensorflow/what-are-symbolic-and-imperative-apis-in-tensorflow-2-0-dfccecb01021

Пример того, как вы все еще можете достичь этого, смешивая API функционального + модельного подкласса, находится здесь (кредиты ixez на GitHub):

import tensorflow as tf
from tensorflow.keras.layers import Input

class MyModel(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.dense = tf.keras.layers.Dense(1)

    def call(self, inputs, **kwargs):
        return self.dense(inputs)

    def model(self):
        x = Input(shape=(1))
        return Model(inputs=[x], outputs=self.call(x))

MyModel().model().summary()

В tensorflow/keras модель представляет собой последовательность слоев, которая может служить подблоком для более сложных сетей. Основное понятие здесь — повторение.

Однако для большинства библиотек машинного обучения модель — это алгоритм, который принимает входные данные, обрабатывает их и генерирует выходные данные (ну, это алгоритм!), которые должны быть связаны с входными данными посредством теории принятия решений. По существу, его можно обучить и протестировать на заданном наборе данных или, по крайней мере, с использованием предписаний для набора данных (например, размера и типа данных). Основная идея заключается в рендеринге статического кода.

Таким образом, эти две концепции (рекуррентное построение и статическое построение) в каком-то смысле несовместимы, но можно найти обходной путь. То, как я это сделал, обобщено в приведенном ниже примере.

      class MultiLayerPerceptron(Model):

    def __init__(
            self,
            d_input: int = 32,
            d_hidden: int = 64,
            d_output: int = 16,
            dropout: float = 0.0):
        self.d_input = int(d_input)
        self.d_hidden = int(d_hidden)
        self.d_output = int(d_output)
        self.dropout = float(dropout)
        inputs = Input(shape=(self.d_input,), name='input')
        x = Dense(self.d_hidden, activation='relu', name='hidden')(inputs)
        x = Dropout(self.dropout, name='dropout')(x)
        outputs = Dense(self.d_output, activation='sigmoid', name='output')(x)
        super().__init__(inputs=inputs, outputs=outputs)
        loss_function = tf.keras.losses.BinaryCrossentropy(from_logits=False)
        optimizer = tf.keras.optimizers.Adam()
        super().compile(
            optimizer=optimizer, loss=loss_function, metrics=['accuracy'])
        return None

    def predict(self, x):
        y = super().predict(x)
        return tf.round(y).numpy().astype(int)

    def transform(self, x):
        return self(x)

что, я надеюсь, достаточно ясно. Я просто отложил звонокдо момента построения сети. Тогда возникло поразительное сходство с терминологией scikit-learn/machine-learning.

Тем не менее, обратите внимание, что

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

В любом случае, для простых моделей (в терминологии keras/recurrent) проще использовать функциональный API. Если вам нужно настроить слои, просто создайте собственные слои , а не модель , которые все равно можно создать на функциональном уровне API.

Другие вопросы по тегам