【问题标题】:Tensorflow: Output where max is 1 and rest is 0Tensorflow:输出最大值为1,其余为0
【发布时间】:2020-11-17 08:41:46
【问题描述】:

我正在研究用于解决谜题的卷积网络的一个特殊情况,它的一部分将在以后用于对图像进行分类。目前我正在设置拼图部分的最后一层。

每个拼图由 9 块组成,y_hat 是一个 81(9x9) 长的 nparray,包含每块的原始位置。

对于网络,我使用了 Tensorflow 函数模型,其中最后一层是 9 个小的子模型,通过 softmaxing 来指示片段的去向。我想知道是否有任何方法可以使子模型的最后一层在 softmax 之后仅输出 1 的最大值,其余的输出 0?我已经找了好几天了。这仍然必须是神经网络的一部分,因此可以在训练时使用。

我的意思是:

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

【问题讨论】:

    标签: python tensorflow neural-network


    【解决方案1】:

    如果你只是想对事物进行分类,那么在tf.keras.losses.CategoricalCrossentropy[1]tf.keras.losses.SparseCategoricalCrossentropy[2]中使用from_logit=True,并输出tf.keras.layers.Dense层。 softmax 计算将在这些损失函数中完成。

    通过将one_hot层和softmax层合二为一,计算效率更高。您不需要为网络的输出创建自己的 one_hot 层。设置好了

    如果你想要自己的 one_hot 矢量转换器层,我有一个想法来保持图微分。在 softmax 中使用称为热力学 beta 的非常大的参数。

    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

    【讨论】:

    • 关于使其可区分,有一些选项,您也可以这样做,例如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 说这是最后一层,我建议只更改损失函数以使用这个最终激活函数之前的值(“logits ")。
    【解决方案2】:

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

    使用“one hot decode”搜索可能会对您有所帮助。

    【讨论】:

    • 这不是答案,而是评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 2021-10-10
    • 2020-11-04
    相关资源
    最近更新 更多