Keras восстанавливает значение узла перед активацией

Представьте себе полностью связанную нейронную сеть с ее двумя последними слоями следующей структуры:

[Dense] units = 612 activation = softplus [Dense] units = 1 activation = sigmoid 

Выходное значение сети равно 1, но я хотел бы знать, что вход x в сигмоидальную функцию (должно быть некоторое большое число, так как sigm (x) здесь 1).

Ответ Foldlowing indraforyou Мне удалось получить выходные данные и веса слоев Keras:

 outputs = [layer.output for layer in model.layers[-2:]] functors = [K.function( [model.input]+[K.learning_phase()], [out] ) for out in outputs] test_input = np.array(...) layer_outs = [func([test_input, 0.]) for func in functors] print layer_outs[-1][0] # -> array([[ 1.]]) dense_0_out = layer_outs[-2][0] # shape (612, 1) dense_1_weights = model.layers[-1].weights[0].get_value() # shape (1, 612) dense_1_bias = model.layers[-1].weights[1].get_value() x = np.dot(dense_0_out, dense_1_weights) + dense_1_bias print x # -> -11.7 

Как x может быть отрицательным числом? В этом случае вывод последних слоев должен быть рядом ближе к 0.0, чем 1.0. Являются ли dense_0_out или dense_1_weights неправильными dense_1_weights или весами?

    2 Solutions collect form web for “Keras восстанавливает значение узла перед активацией”

    Так как вы используете get_value() , я предполагаю, что вы используете Theano backend. Чтобы получить значение узла перед активацией сигмоида, вы можете пересечь граф вычислений .

    График может быть пройден, начиная с выходов (результат некоторых вычислений) до его входов, используя поле владельца.

    В вашем случае, что вы хотите, это вход x сигмоидной активации op. Выход сигмоида op – model.output . Объединяя их, переменная x является model.output.owner.inputs[0] .

    Если вы распечатаете это значение, вы увидите Elemwise{add,no_inplace}.0 , который является дополнительным элементом. Он может быть проверен из исходного кода Dense.call() :

     def call(self, inputs): output = K.dot(inputs, self.kernel) if self.use_bias: output = K.bias_add(output, self.bias) if self.activation is not None: output = self.activation(output) return output 

    Вход в функцию активации – это выход K.bias_add() .

    С небольшой модификацией вашего кода вы можете получить значение узла перед активацией:

     x = model.output.owner.inputs[0] func = K.function([model.input] + [K.learning_phase()], [x]) print func([test_input, 0.]) 

    Для тех, кто использует TensorFlow: вместо этого используйте x = model.output.op.inputs[0] .

    Я вижу простой способ немного изменить структуру модели. (См. В конце, как использовать существующую модель и изменить только окончание).

    Преимущества этого метода:

    • Вам не нужно гадать, правильно ли вы делаете правильные вычисления
    • Вам не нужно заботиться о слоях отсева и о том, как реализовать выпадение
    • Это чистое решение Keras (применимо к любому бэкэнду, либо к Theano, либо к Tensorflow).

    Ниже приведены два возможных решения:

    • Вариант 1 – Создайте новую модель с начала с предлагаемой структурой
    • Вариант 2 – Повторное использование существующей модели, изменяющей только ее окончание

    Модельная структура

    Вы могли бы просто удалить последний плотный слой в два слоя в конце:

     [Dense] units = 612 activation = softplus [Dense] units = 1 #no activation [Activation] activation = sigmoid 

    Затем вы просто получаете результат последнего плотного слоя.

    Я бы сказал, что вы должны создать две модели, одну для обучения, другую для проверки этого значения.

    Вариант 1 – Построение моделей с самого начала:

     from keras.models import Model #build the initial part of the model the same way you would #add the Dense layer without an activation: #if using the functional Model API denseOut = Dense(1)(outputFromThePreviousLayer) sigmoidOut = Activation('sigmoid')(denseOut) #if using the sequential model - will need the functional API model.add(Dense(1)) sigmoidOut = Activation('sigmoid')(model.output) 

    Создайте две модели из них: одну для обучения, одну для проверки результата плотности:

     #if using the functional API checkingModel = Model(yourInputs, denseOut) #if using the sequential model: checkingModel = model trainingModel = Model(checkingModel.inputs, sigmoidOut) 

    Используйте trianingModel для обучения в обычном режиме. Две модели разделяют веса, поэтому обучение – это обучение другому.

    Используйте checkingModel чтобы видеть выходы слоя Dense, используя checkingModel.predict(X)

    Вариант 2 – создание этого из существующей модели:

     from keras.models import Model #find the softplus dense layer and get its output: softplusOut = oldModel.layers[indexForSoftplusLayer].output #or should this be the output from the dropout? Whichever comes immediately after the last Dense(1) #recreate the dense layer outDense = Dense(1, name='newDense', ...)(softPlusOut) #create the new model checkingModel = Model(oldModel.inputs,outDense) 

    Это важно, поскольку вы создали новый слой Dense, чтобы получить вес от старого:

     wgts = oldModel.layers[indexForDense].get_weights() checkingModel.get_layer('newDense').set_weights(wgts) 

    В этом случае обучение старой модели не будет обновлять последний плотный слой в новой модели, поэтому давайте создадим обучающую модель:

     outSigmoid = Activation('sigmoid')(checkingModel.output) trainingModel = Model(checkingModel.inputs,outSigmoid) 

    Используйте checkingModel для проверки значений, которые вы хотите, с помощью checkingModel.predict(X) . И тренируйте trainingModel .

    Python - лучший язык программирования в мире.