【问题标题】:Keras custom softmax layer: Is it possible to have output neurons set to 0 in the output of a softmax layer based on zeros as data in an input layer?Keras 自定义 softmax 层:是否可以在基于零的 softmax 层的输出中将输出神经元设置为 0 作为输入层中的数据?
【发布时间】:2019-05-19 22:36:40
【问题描述】:

我有一个神经网络,在最后一层使用 softmax 激活有 10 个输出神经元。我也确切地知道,根据输入值,输出层中的某些神经元应该有 0 值。所以我有一个由 10 个神经元组成的特殊输入层,每个神经元不是 0 就是 1。

是否有可能以某种方式强制假设输出神经元没有。如果输入神经元 3 也为 0,则 3 的值 = 0?

action_input = Input(shape=(10,), name='action_input')
...

x = Dense(10,  kernel_initializer = RandomNormal(),bias_initializer = RandomNormal() )(x)
x = Activation('softmax')(x)

我知道有一种方法可以屏蔽掉神经网络之外的输出层的结果,并对所有非零相关的输出进行重新整形(以便总和为 1)。但我想在网络内解决这个问题,并在网络训练期间也使用它。我应该为此使用自定义层吗?

【问题讨论】:

  • 所以你想让一些输出神经元为零,并重新调整其他神经元以使它们的总和为 1?

标签: python machine-learning keras neural-network softmax


【解决方案1】:

您可以使用Lambda 层和K.switch 检查输入中的零值并在输出中屏蔽它们:

from keras import backend as K

inp = Input((5,))
soft_out = Dense(5, activation='softmax')(inp)
out = Lambda(lambda x: K.switch(x[0], x[1], K.zeros_like(x[1])))([inp, soft_out])

model = Model(inp, out)

model.predict(np.array([[0, 3, 0, 2, 0]]))
# array([[0., 0.35963967, 0., 0.47805876, 0.]], dtype=float32)

但是,正如您所见,输出的总和不再是 1。如果您希望总和为 1,则可以重新调整值:

def mask_output(x):
    inp, soft_out = x
    y = K.switch(inp, soft_out, K.zeros_like(inp))
    y /= K.sum(y, axis=-1)
    return y

# ...
out = Lambda(mask_output)([inp, soft_out])

【讨论】:

  • 嗨,我试图让这个工作,但有一个错误:在'y /= K.sum(y,axis = -1)'行中,因为y张量的形状是(batch_size,5) 和 K.sum 返回 (5) 的形状,python 在第一次运行时在这里报告错误。最重要的是,情况有点复杂,因为我们必须避免除以零,如果 K.sum 返回零,我们不仅需要将其更正为 1,而且我们必须以某种方式将 inp 行数据设置为也不同于零,以便在最后重塑它们并使输出总和等于 1。你能帮忙吗?
  • @user898160 它适用于我的机器。总和的结果将被广播。你得到什么错误?编辑您的问题并添加您得到的错误。至于零和,只有输入全为零时才会发生,否则永远不会发生,因为Softmax的输出根本不为零。
【解决方案2】:

最后我想出了这个代码:

from keras import backend as K
import tensorflow as tf
def mask_output2(x):
    inp, soft_out = x
    # add a very small value in order to avoid having 0 everywhere
    c = K.constant(0.0000001, dtype='float32', shape=(32, 13))
    y = soft_out + c

    y = Lambda(lambda x: K.switch(K.equal(x[0],0), x[1], K.zeros_like(x[1])))([inp, soft_out])
    y_sum =  K.sum(y, axis=-1)

    y_sum_corrected = Lambda(lambda x: K.switch(K.equal(x[0],0), K.ones_like(x[0]), x[0] ))([y_sum])

    y_sum_corrected = tf.divide(1,y_sum_corrected)

    y = tf.einsum('ij,i->ij', y, y_sum_corrected)
    return y

【讨论】:

    猜你喜欢
    • 2019-05-22
    • 1970-01-01
    • 2023-03-15
    • 2023-03-21
    • 2021-04-23
    • 1970-01-01
    • 2020-07-07
    • 1970-01-01
    • 2019-04-27
    相关资源
    最近更新 更多