也许这是微不足道的,但也许不是。我花了太多时间试图找出如何使这项工作。这是代码:
# batch x time x events
batch = 2
time = 3
events = 4
tensor = np.random.rand(batch, time, events)
tensor[0][0][2] = 0
tensor[0][0][3] = 0
tensor[0][1][3] = 0
tensor[0][2][1] = 0
tensor[0][2][2] = 0
tensor[0][2][3] = 0
tensor[1][0][3] = 0
non_zero = ~tf.equal(tensor, 0.)
s = tf.Session()
g = tf.global_variables_initializer()
s.run(g)
s.run(non_zero)
我正在尝试将 tf.nn.softmax
应用于每个 time
维度的非零值。但是,当我使用 tf.boolean_mask
时,它实际上将所有非零值聚集在一起。那不是我想要的。我想保留尺寸。
因此 tf.nn.softmax
应该只应用于那些组,并且应该将它们“放回”原来的位置。有谁知道如何做到这一点?
编辑:
在你们的帮助下,我几乎找到了我需要的解决方案。但我仍然缺少一步。将每个时间维度的 softmax 分配给非零值:
def apply_sparse_softmax(time_vector):
non_zeros = ~tf.equal(time_vector, 0.)
sparse_softmax = tf.nn.softmax(tf.boolean_mask(time_vector, non_zeros))
new_time_vector = sparse_softmax * tf.cast(non_zeros, tf.float64) # won't work because dimensions are different
return time_vector
另请注意,当您在整个时间维度上都为零时,此解决方案应该可以处理这种情况。那么它应该保持不变。
最佳答案
可能重复:Applying tf.nn.softmax() only to positive elements of a tensor
借助tf.map_fn
和tf.where
session.run(tf.map_fn(
lambda x : tf.where(x > 0, tf.nn.softmax(x,axis=2,name="pidgeon"), x), tensor))
针对 np.random.seed(1992)
进行了测试
# tensor
[[[0.86018176 0.42148685 0. 0. ]
[0.64714 0.68271286 0.6449022 0. ]
[0.92037941 0. 0. 0. ]]
[[0.38479139 0.26825327 0.43027759 0. ]
[0.56077674 0.49309016 0.2433904 0.85396874]
[0.1267429 0.1861004 0.92251748 0.67904445]]]
# result
[[[0.34841156, 0.33845624, 0. , 0. ],
[0.28155918, 0.43949257, 0.48794109, 0. ],
[0.37002926, 0. , 0. , 0. ]],
[[0.33727059, 0.31513436, 0.2885575 , 0. ],
[0.40216839, 0.39458556, 0.23936921, 0.44145382],
[0.26056102, 0.29028008, 0.47207329, 0.37060957]]])
0.34841156 == np.exp(0.86018176) / (np.exp(0.86018176) + np.exp(0.64714) + np.exp(0.92037941))
关于python - 跨维度将 softmax 应用于矩阵中的非零元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51408871/