Tensorflow softmax 不忽略掩蔽值

bw4*_*4sz 1 python deep-learning keras tensorflow

我正在恢复这个 github问题,因为我相信它是有效的并且需要解释。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)
Run Code Online (Sandbox Code Playgroud)

两个结果几乎相同

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 ]])>
Run Code Online (Sandbox Code Playgroud)

预期行为

我希望只对有效条目进行 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]])>
Run Code Online (Sandbox Code Playgroud)

填充在正确的位置

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

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

相关:tensorflow - softmax忽略负标签(就像caffe一样)

from tensorflow import __version__
__version__
'2.3.1'
Run Code Online (Sandbox Code Playgroud)

Aks*_*gal 7

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

从 a 获得零输出的唯一方法softmax()是传递一个非常小的浮点值。如果将屏蔽值设置为 的最小可能机器限制float64Softmax()则该值将为零。

要获得 float64 的机器限制,您需要tf.float64.min等于-1.7976931348623157e+308。有关机器限制的更多信息,请参见这篇文章

这是仅供您参考的实现,以及用于创建掩码并将其传递给tf.boolean_mask的正确方法-tf.wheresoftmax()

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)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)