Я согласен с комментарием @ blue-phoenox, что вы не должны использовать сигмоид с перекрестной энтропией, потому что сумма вероятностей классов не равна единице. Но если у вас есть причины для использования sigmoid
, вы можете нормализовать ваш вывод по сумме векторных элементов, чтобы сделать его равным 1:
output = output/tf.reshape(tf.reduce_sum(output, 1), (-1, 1))
И вы получите:
import tensorflow as tf
output = tf.Variable([[0.03902826, 0.00037046]])
output = output/tf.reshape(tf.reduce_sum(output, 1), (-1, 1))
summedup = tf.reduce_sum(output, axis=1)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(output.eval()) # [[0.9905971 0.00940284]] - new output
print(summedup.eval()) # [1.] - summs up to 1
Чтобы реализовать его в keras
, вы можете создать подкласс tf.keras.layers.Layer
следующим образом:
from tensorflow.keras import layers
class NormLayer(layers.Layer):
def __init__(self):
super(NormLayer, self).__init__()
def call(self, inputs):
return inputs / tf.reshape(tf.reduce_sum(inputs, 1), (-1, 1))
А затем используйте его в вашей Sequential()
модели:
# using dummy data to illustrate
x_train = np.array([[-1.551, -1.469], [1.022, 1.664]], dtype=np.float32)
y_train = np.array([[0, 1], [1, 0]], dtype=np.int32)
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(units=2, activation=tf.nn.sigmoid, input_shape=(2, )))
model.add(NormLayer())
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
model.fit(x=x_train,
y=y_train,
epochs=2,
batch_size=2)
# ...