Keras получает значение узла перед активацией функции
представьте себе полностью связанную нейронную сеть с двумя последними слоями следующей структуры:
[Dense]
units = 612
activation = softplus
[Dense]
units = 1
activation = sigmoid
выходное значение сети равно 1, но я хотел бы знать, каким был вход x в сигмоидальную функцию (должно быть какое-то большое число, так как sigm(x) здесь равно 1).
опубликовала indraforyou это!--10--> ответ мне удалось получить выходные данные и веса слоев 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. Are dense_0_out
или dense_1_weights
неправильные выходы или Весов?
2 ответов
так как вы используете get_value()
, Я предполагаю, что вы используете бэкэнд Theano. Чтобы получить значение узла до активации сигмоида, вы можете пересечь график вычислений.
график может быть пройден, начиная с выходов (результат некоторых вычислений) до его входов, используя поле владельца.
в вашем случае, что вы хотите-это вход x
сигмовидной активации op. Выход сигмовидной op is model.output
. Складывая их вместе, переменная x
is model.output.owner.inputs[0]
.
если вы распечатаете это значение, вы увидите Elemwise{add,no_inplace}.0
, что является элементарным дополнением op. Это можно проверить из исходный код of 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
просто чтобы увидеть выходы плотного слоя, используйте 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)
важно, так как вы создали новый плотный слой, чтобы получить вес от старого:
wgts = oldModel.layers[indexForDense].get_weights()
checkingModel.get_layer('newDense').set_weights(wgts)
в этом случае обучение старой модели не обновит последний плотный слой в новой модели, поэтому давайте создадим trainingModel:
outSigmoid = Activation('sigmoid')(checkingModel.output)
trainingModel = Model(checkingModel.inputs,outSigmoid)
использовать checkingModel
для проверки значений, которые вы хотите с checkingModel.predict(X)
. И тренировать trainingModel
.