Для l oop в tenorflow / keras - PullRequest
       7

Для l oop в tenorflow / keras

0 голосов
/ 11 июля 2020

Я пытаюсь использовать a для l oop в определении модели (и пытаюсь воссоздать Ta bNet в keras).

class TabNet(keras.Model):
    def __init__(self, input_dim, output_dim, steps, n_d, n_a, gamma=1.3):
        super().__init__()
        self.n_d, self.n_a, self.steps = n_d, n_a, steps
        self.shared = SharedBlock(n_d+n_a)
        self.first_block = SharedBlock(n_a)
        self.decision_blocks = [DecisionBlock(n_d+n_a)] * steps
        self.prior_scale = Prior(input_dim, gamma)
        self.bn = layers.BatchNormalization()
        self.attention = [AttentiveTransformer(input_dim)] * steps
        self.final = layers.Dense(output_dim)
        self.eps = 1e-8

    @tf.function
    def call(self, x):
        self.prior_scale.reset()
        final_out = 0
        M_loss = 0

        x = self.bn(x)
        attention = self.first_block(self.shared(x))
        for i in range(self.steps):
            mask = self.attention[i](attention, self.prior_scale.P)
            M_loss += tf.reduce_sum(mask * tf.math.log(mask + self.eps), axis=-1) / self.steps

            prior = self.prior_scale(mask)
            out = self.decision_blocks[i](self.shared(x * prior))
            attention, output = out[:,:self.n_a], out[:,self.n_a:]
            final_out += tf.nn.relu(output)

        return self.final(final_out), M_loss

Если вы не знаете, что эти отдельные блоки есть, просто предположим, что это линейные слои. У меня есть записная книжка с полным кодом, если вы используете sh, чтобы увидеть, что они на самом деле.

Однако я не могу обучить его, так как получаю сообщение об ошибке iterating over tf .Тензор is not allowed: AutoGraph did not convert this function. Try decorating it directly with @tf.function.. Я украсил его, но до сих пор не помогает.

Я почти уверен, что это для l oop, которое вызывает у меня ошибку, когда я делаю model.fit(train_x, train_y). Буду признателен за любые мысли о том, как реализовать вышеизложенное для l oop способом тензорного потока. tf.while_loop - это все, что я видел до сих пор, и приведенные примеры довольно упрощены c по сравнению с тем, что я хочу сделать.

Ответы [ 2 ]

1 голос
/ 22 июля 2020

это мое предложение ...

Я не знаю, что конкретно делает ваша сеть, но я вижу, что вы хотите создать 2 выхода и объединить их внутри своей потери. Один из ваших выходных данных также является результатом некоторой скрытой операции внутри сети (M_loss).

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

Как было сказано ранее, вы пытаетесь построить объединенную потерю как sparse_entropy(y_true, y_pred) - reg_sparse * M_loss. Чтобы сделать это возможным , я разделил потерю на две части (по одной для каждого вывода): разреженная часть и часть M_loss . Редкая потеря - это просто SparseCategoricalCrossentropy (from_logits = True) из keras, а для M_loss я написал эту функцию после вашего кода

def m_loss(y_true, y_pred):
  m = tf.reduce_mean(y_pred, keepdims=True)
  return m

m_loss использует только 'y_pred', которые являются скрытыми частями ваша сеть. y_true в этом случае не имеет значения для требуемой операции. вот почему мы передаем массив нулей при подгонке.

На этом этапе мы должны объединить две потери, и это возможно в keras таким образом

reg_sparse = 0.1

model.compile('Adam', loss=[sce, m_loss], loss_weights=[1,-reg_sparse])
model.fit(train_x, [train_y, np.zeros(train_y.shape[0])], epochs=3)

в этом случае, окончательная потеря является результатом комбинации 1*sce + (-reg_sparse)*m_loss

это полный рабочий код: https://colab.research.google.com/drive/152q1rmqTJ0dWLbFN8PqzCBhWkVKirkU5?usp=sharing

Я также вношу небольшие изменения в Ta bNet, например, как создаются final_out и M_loss

1 голос
/ 20 июля 2020

Нет, на самом деле это не проблема for l oop. Я проверил ваш код, проблема заключалась в том, что вы забыли вызвать конструктор суперкласса в своих SharedBlock, DecisionBlock и Prior.

Например, ваш код должен выглядеть так.

class SharedBlock(layers.Layer):
    def __init__(self, units, mult=tf.sqrt(0.5)):
        super().__init__()
        self.layer1 = FCBlock(units)
        self.layer2 = FCBlock(units)
        self.mult = mult

После внесения этих изменений вы больше не увидите эту ошибку, но появится что-то еще.

TypeError: in user code:

    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:1147 predict_function  *
        outputs = self.distribute_strategy.run(
    <ipython-input-46-f609cb1acdfa>:15 call  *
        self.prior_scale.reset()

    TypeError: tf__reset() missing 1 required positional argument: 'len_x'

Чтобы решить эту проблему, вам необходимо внести следующие изменения в класс class Prior(layers.Layer):.

def reset(self, len_x=1.0):
        self.P = 1.0

Тогда вы получите еще одну проблему.

AttributeError: в коде пользователя:

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:1147 predict_function  *
    outputs = self.distribute_strategy.run(
<ipython-input-46-f609cb1acdfa>:26 call  *
    out = self.decision[i](self.shared(x * prior))

AttributeError: 'TabNet' object has no attribute 'decision'

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

ОБНОВЛЕНИЕ:

Вы можете заглянуть в раздел комментариев этого ответа, там было предоставлено решение проблемы AttributeError: 'TabNet' object has no attribute 'decision'

ОБНОВЛЕНИЕ: 21/07

Я должен вас снова разочаровать, что проблема не в for l oop.

Если вы внимательно посмотрите журнал ошибок, вы увидите, что проблема связана с функцией full_loss.

<ipython-input-10-07e59f23d230>:7 full_loss  *
        logits, M_loss = y_pred
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py:561 __iter__
        self._disallow_iteration()
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py:554 _disallow_iteration
        self._disallow_when_autograph_enabled("iterating over `tf.Tensor`")
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py:532 _disallow_when_autograph_enabled
        " decorating it directly with @tf.function.".format(task))

    OperatorNotAllowedInGraphError: iterating over `tf.Tensor` is not allowed: AutoGraph did not convert this function. Try decorating it directly with @tf.function.

Точная проблема вызвана приведенным ниже утверждением.

logits, M_loss = y_pred

Если вы используете приведенный ниже код, который не использует вашу функцию потерь, вы увидите другой результат.

model.compile('Adam', loss='sparse_categorical_crossentropy')
model.fit(train_x, train_y, batch_size=1)

Received a label value of 1 which is outside the valid range of [0, 1).  Label values: 1
     [[node sparse_categorical_crossentropy_1/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits (defined at <ipython-input-26-d39f533b7a69>:2) ]] [Op:__inference_train_function_18003]

Я не совсем понимаю код модели, и model.summary() не так полезен в вашем случае. Есть некоторая проблема с вашим последним слоем, по крайней мере, сообщение об ошибке предполагает, что у вас недостаточно нейронов (по 1 для каждого класса).

Я предлагаю изучить последний слой и функцию потерь.

Почему я уверен, что это не из-за for l oop, потому что даже если вы прокомментируете for l oop, вы все равно получите ту же ошибку.

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

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