Keras 自定义 softmax 层:是否可以根据输入层中的零作为数据,在 softmax 层的输出中将输出神经元设置为 0?
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?
我有一个神经网络,最后一层有 10 个输出神经元,使用 softmax 激活。我还确切地知道,根据输入值,输出层中的某些神经元应具有 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)。但我想在网络内解决这个问题,并在网络训练期间也使用它。我应该为此使用自定义图层吗?
您可以使用 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)
但是,如您所见,输出的总和不再为一。如果你希望总和为一,你可以重新缩放值:
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])
最后我想出了这个代码:
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
我有一个神经网络,最后一层有 10 个输出神经元,使用 softmax 激活。我还确切地知道,根据输入值,输出层中的某些神经元应具有 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)。但我想在网络内解决这个问题,并在网络训练期间也使用它。我应该为此使用自定义图层吗?
您可以使用 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)
但是,如您所见,输出的总和不再为一。如果你希望总和为一,你可以重新缩放值:
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])
最后我想出了这个代码:
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