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 или весами?

Так как вы используете 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 .