Пользовательский слой softmax Keras: возможно ли иметь выходные нейроны равными 0 на выходе слоя softmax на основе нулей в качестве данных на входном слое? - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть нейронная сеть с 10 выходными нейронами в последнем слое с использованием активации softmax.Я также точно знаю, что на основе входных значений некоторые нейроны в выходном слое должны иметь 0 значений.Итак, у меня есть специальный входной слой из 10 нейронов, каждый из которых имеет значение 0 или 1.

Можно ли каким-то образом форсировать, скажем, выходной нейрон no.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).Но я хотел бы решить эту проблему внутри сети и использовать ее также во время обучения сети.Должен ли я использовать пользовательский слой для этого?

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

В конце я придумал этот код:

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
0 голосов
/ 19 декабря 2018

Вы можете использовать слой 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])
...