【问题标题】:Tensorflow softmax does not ignore masking valueTensorflow softmax 不忽略掩码值
【发布时间】:2021-01-15 23:55:04
【问题描述】:

我正在恢复这个 github issue,因为我相信它是有效的并且需要解释。 tf.keras 有一个掩蔽层,其文档内容为

对于输入张量中的每个时间步(张量中的第 1 维),如果 在那个时间步,输入张量中的所有值都等于 mask_value,则时间步将全部被屏蔽(跳过) 下游层(只要它们支持遮罩)。

如果任何下游层不支持屏蔽但收到这样的 输入掩码,将引发异常。


# create padded zeros and change two valid entries.
inputs = np.zeros([1,5])
inputs[0,1] = 0.5
inputs[0,2] = 0.1
inputs = tf.Variable(inputs)
masked_inputs = tf.keras.layers.Masking(mask_value=0.0)(inputs)
with_masking = tf.keras.layers.Softmax()(masked_inputs)
without_masking = tf.keras.layers.Softmax()(inputs)

这两个结果几乎相同

with_masking
<tf.Tensor: shape=(1, 5), dtype=float32, numpy=
array([[0.1737954 , 0.28654018, 0.19207363, 0.1737954 , 0.1737954 ]],
      dtype=float32)>
without_masking
<tf.Tensor: shape=(1, 5), dtype=float64, numpy=array([[0.1737954 , 0.28654017, 0.19207362, 0.1737954 , 0.1737954 ]])>

预期行为

我希望只对有效条目进行 softmax,类似于

#Assign one large value 
inputs = np.zeros([1,2])
inputs[0,0] = 0.5
inputs[0,1] = 0.1
inputs = tf.Variable(inputs)
without_masking = tf.keras.layers.Softmax()(inputs)

without_masking
<tf.Tensor: shape=(1, 2), dtype=float64, numpy=array([[0.59868766, 0.40131234]])>

填充在正确的位置

with_masking
<tf.Tensor: shape=(1, 5), dtype=float32, numpy=
array([[0 , 0.59868766, 0.40131234, 0, 0 ]],
      dtype=float32)>

要忽略 softmax 函数中的 0,我们可以切换出大量负数吗?

相关:tensorflow - softmax ignore negative labels (just like caffe)

from tensorflow import __version__
__version__
'2.3.1'

【问题讨论】:

    标签: tensorflow keras deep-learning


    【解决方案1】:

    我认为这已经在您链接的Github issue 中得到了很好的解释。潜在的问题是,无论数组是否被屏蔽,softmax() 仍然对0.0 值进行操作,并按照数学预期返回non-zero 值(link)。

    softmax() 获得零输出的唯一方法是传递一个非常小的浮点值。如果您将屏蔽值设置为float64 的最小机器限制,则此值的Softmax() 将为零。

    要获得 float64 的机器限制,您需要 tf.float64.min,它等于 -1.7976931348623157e+308。有关此post 的机器限制的更多信息。

    这里有一个实现供您参考,仅供tf.boolean_mask 参考,以及使用tf.where 创建掩码并将其传递给softmax() 的正确方法-

    import tensorflow as tf
    
    inputs = np.zeros([1,5])
    inputs[0,1] = 0.5
    inputs[0,2] = 0.1
    inputs = tf.Variable(inputs)
    
    #Returns only the elements that are not masked (2,)
    with_boolmask = tf.boolean_mask(inputs, inputs!=0)
    with_boolmask = tf.keras.layers.Softmax()(with_boolmask)
    
    #Correct way to do it!
    masked_inp = tf.where(inputs!=0, inputs, tf.float64.min) #<----
    with_where = tf.keras.layers.Softmax()(masked_inp)
    
    print('BOOLEAN MASK (NOT EXPECTED)')
    print(with_boolmask)
    
    print('')
    print('MASKED INPUT - ')
    print(masked_inp)
    print('')
    print('SOFTMAX OUTPUT')
    print(with_where)
    
    BOOLEAN MASK (NOT EXPECTED)
    tf.Tensor([0.59868765 0.40131232], shape=(2,), dtype=float32)
    
    MASKED INPUT - 
    tf.Tensor(
    [[-1.79769313e+308  5.00000000e-001  1.00000000e-001 -1.79769313e+308
      -1.79769313e+308]], shape=(1, 5), dtype=float64)
    
    SOFTMAX OUTPUT
    tf.Tensor([[0.         0.59868765 0.40131232 0.         0.        ]], shape=(1, 5), dtype=float32)
    

    【讨论】:

    • 清晰、乐于助人并且得到很好的回答。
    【解决方案2】:

    如果我错了,请随时纠正我。我认为我们有一个简单的方法来做到这一点。

    import tensorflow as tf
    import numpy as np
    import math
    
    # create padded zeros and change two valid entries.
    inputs = tf.constant([0., 0.5, 0.1, 0., 0.])
    mask = tf.not_equal(inputs, 0.)
    with_masking = tf.keras.layers.Softmax()(inputs, mask=mask)
    without_masking = tf.keras.layers.Softmax()(inputs)
    
    print(with_masking)
    print(without_masking)
    

    输出是,

    tf.Tensor([0.         0.59868765 0.40131232 0.         0.        ], shape=(5,), dtype=float32)
    tf.Tensor([0.1737954  0.28654018 0.19207363 0.1737954  0.1737954 ], shape=(5,), dtype=float32)
    

    【讨论】:

      猜你喜欢
      • 2015-08-20
      • 2020-07-23
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-07
      相关资源
      最近更新 更多