Tensorflow: вывод, где max равно 1, а rest равно 0

#python #tensorflow #neural-network

#python #тензорный поток #нейронная сеть

Вопрос:

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

Каждая головоломка состоит из 9 частей, а y_hat представляет собой nparray длиной 81 (9×9), содержащий исходное положение каждой части.

Для сети я использую функциональную модель Tensorflow, где последний слой представляет собой 9 небольших подмоделей softmaxing, указывающих, куда должна идти часть. Мне было интересно, есть ли какой-либо способ заставить последний слой подмоделей выводить только 1 для самого высокого значения после softmax и 0 для остальных? Я искал уже несколько дней. Это все равно должно быть частью нейронной сети, чтобы ее можно было использовать при обучении.

Я имею в виду:

 [0.01,0.41,0.02,0.32,0.01,0.43] => [0,0,0,0,0,1]
  

Ответ №1:

Если вы просто хотите классифицировать вещи, затем используйте from_logit=True in tf.keras.losses.CategoricalCrossentropy [1] или tf.keras.losses.SparseCategoricalCrossentropy [2] и output tf.keras.layers.Dense layer . вычисление softmax будет выполняться в этих функциях потерь.

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

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

 import tensorflow as tf

class OneHot(tf.keras.layers.Layer):
    def __init__(self, infi=1e9):
        super(OneHot, self).__init__()
        self.infi = infi

    def call(self, x):
        return tf.nn.softmax(self.infi * x) # x has shape [B, 9]

    def get_config(self):
        return {'infi': self.infi}
  

Посмотрите, как это работает ниже.

 >>> a = tf.constant([[1.,2.], [3., 4.]], dtype=tf.float32)
>>> tf.nn.softmax(a)
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[0.26894143, 0.7310586 ],
       [0.26894143, 0.7310586 ]], dtype=float32)>
>>> tf.nn.softmax(1e9 * a)
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[0., 1.],
       [0., 1.]], dtype=float32)>
  

Я не уверен, как этот уровень вывода улучшает обучение.

== Мой первый ответ ниже. Не рекомендуется.

Вы можете использовать tf.one_hot [3], чтобы сделать это.

 import tensorflow as tf

x = tf.constant([0.01,0.41,0.02,0.32,0.01,0.43], dtype=tf.float32)
i = tf.argmax(x)
y = tf.one_hot(i, 6)
# <tf.Tensor: shape=(6,), dtype=float32, numpy=array([0., 0., 0., 0., 0., 1.], dtype=float32)>
  

Если вы хотите создать слой keras, создайте пользовательский слой [4] .

 import tensorflow as tf

class OneHot(tf.keras.layers.Layer):
    def __init__(self):
        super(OneHot, self).__init__()

    def call(self, x):
        i = tf.argmax(x, axis=1) # x has shape [B, 9]
        return tf.one_hot(i, 9)
  

[1] https://www.tensorflow.org/api_docs/python/tf/keras/losses/CategoricalCrossentropy
[2] https://www.tensorflow.org/api_docs/python/tf/keras/losses/SparseCategoricalCrossentropy
[3] https://www.tensorflow.org/api_docs/python/tf/one_hot
[4] https://www.tensorflow.org/guide/keras/custom_layers_and_models

Комментарии:

1. О том, чтобы сделать его дифференцируемым, есть несколько вариантов, которые вы также можете сделать, например i = tf.argmax(x); max_v = x[i]; y = tf.concat([tf.zeros(i, dtype=x.dtype), [max_v / max_v], tf.zeros(tf.size(x, out_type=i.dtype) - i - 1, dtype=x.dtype)], axis=0) , и это технически дифференцируемо, но градиент бесполезен… Поскольку OP говорит, что это для последнего уровня, я бы предложил просто изменить функцию потерь, чтобы использовать значения перед этой окончательной функцией активации («логиты»).

Ответ №2:

index = tf.argmax(one_hot_vector, axis=0)

Поиск с помощью «one hot decode» может вам помочь.

Комментарии:

1. Это не ответ, а комментарий.