2017-08-03 24 views
13

考虑具有以下结构的其最后的两层的完全连接的神经网络:Keras激活函数之前检索节点的值

[Dense] 
    units = 612 
    activation = softplus 

[Dense] 
    units = 1 
    activation = sigmoid 

净的输出值是1,但我想知道sigmoidal函数的输入x是什么(必须是一些很高的数字,因为sigm(x)在这里是1)。

Folllowing indraforyou's答案我设法获取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是负数?在这种情况下,最后一层的输出应该是一个比1.0更接近0.0的数字。 dense_0_outdense_1_weights错误的输出或权重?

+1

它不应该是'x = np.dot(dense_0_out,dense_1_weights)+ dense_1_bias'吗? –

+0

@MarcinMożejko你是对的,我纠正了它。由于偏见被训练到0.0,所以没有任何改变。 – johk95

+0

但是这个层的输出被送到softmax--你获得的值被压缩到[0,1]间隔。 –

回答

5

由于您使用的是get_value(),我假设您使用的是Theano后端。要在sigmoid激活之前获取节点的值,可以使用traverse the computation graph

该图可以从输出(某些计算的结果)开始遍历到使用所有者字段的输入。

在你的情况,你想要的是sigmoid激活op的输入x。 sigmoid op的输出是model.output。把它们放在一起,变量xmodel.output.owner.inputs[0]

如果你打印出这个值,你会看到Elemwise{add,no_inplace}.0,这是一个元素明智的加法操作。它可以从Dense.call()source code进行验证:

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]代替。

+0

谢谢你的答案!我很清楚你的方法更适合,但是你能否简单地评论一下我的原始代码......这是否会计算出错误?为什么? – johk95

+0

你有没有尝试过这种方法,它仍然给你一个负面的'x'?我试过你的代码,它给出了与这种方法完全相同的结果(一个* positive *'x',大约在600),所以我不太确定问题出在你的代码中。 –

+0

顺便说一句,我从程序中看到'dense_0_out.shape'等于'(1,612)'和'dense_1_weights.shape'等于'(612,1)',这与您发布的内容不同。你能提供你使用的'test_input'和Keras和TF的版本吗? –

4

我可以看到一个简单的方法,只是改变一点模型结构。 (最后查看如何使用现有模型并只更改结尾)。

这种方法的优点是:

  • 你不必去猜测,如果你做了正确的计算
  • 你不需要关心辍学层,以及如何实现退出计算
  • 这是一个纯粹的Keras解决方案(适用于任何后端,Theano或Tensorflow)。

有以下两种可能的解决方案:

  • 选项1 - 与提出的结构
  • 选项2创建一个从开始一个新的模型 - 重复使用现有的模型只改变其结束

模型结构

你可以ju st在最后两层中有最后一个密集分隔:

[Dense] 
    units = 612 
    activation = softplus 

[Dense] 
    units = 1 
    #no activation 

[Activation] 
    activation = sigmoid 

然后你只需得到最后一个密集层的输出。

我想说你应该创建两个模型,一个用于训练,另一个用于检查这个值。

选项1 - 从一开始就构建模型:

#if using the functional API 
    checkingModel = Model(yourInputs, denseOut) 

#if using the sequential model: 
    checkingModel = model 

trainingModel = Model(checkingModel.inputs, sigmoidOut) 

使用trianingModel

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) 

检查的密集输出创建一个从两个模型,一个是培训,一个正常训练。这两个模型分享权重,所以训练一个就是训练另一个。

使用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