#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. Это не ответ, а комментарий.