次の構造の最後の2つの層を持つ完全に接続されたニューラルネットワークを想像してみてください。
[Dense]
units = 612
activation = softplus
[Dense]
units = 1
activation = sigmoid
ネットの出力値は1ですが、シグモイド関数への入力xが何であるかを知りたいです(ここではsigm(x)が1であるため、高い数値である必要があります)。
以下 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_out
またはdense_1_weights
間違った出力または重み?
get_value()
を使用しているので、Theanoバックエンドを使用していると仮定します。シグモイドアクティブ化の前にノードの値を取得するには、 計算グラフをトラバースする 。
グラフは、所有者フィールドを使用して、出力(計算の結果)から入力に至るまでトラバースできます。
あなたの場合、あなたが望むのは、シグモイド活性化演算の入力x
です。 S状結腸手術の出力は_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]
_を使用してください。
モデルの構造を少し変えるだけで簡単な方法がわかります。 (最後に既存のモデルの使用方法を参照し、エンディングのみを変更してください)。
この方法の利点は次のとおりです。
以下の2つの可能な解決策があります。
モデル構造
最後に、最後のデンスを2つのレイヤーに分割することができます。
_[Dense]
units = 612
activation = softplus
[Dense]
units = 1
#no activation
[Activation]
activation = sigmoid
_
次に、最後の密なレイヤーの出力を取得するだけです。
2つのモデルを作成する必要があると思います。1つはトレーニング用で、もう1つはこの値をチェックするためのものです。
オプション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)
_
それから2つのモデルを作成します。1つはトレーニング用、もう1つはdenseの出力をチェックするためのものです。
_#if using the functional API
checkingModel = Model(yourInputs, denseOut)
#if using the sequential model:
checkingModel = model
trainingModel = Model(checkingModel.inputs, sigmoidOut)
_
通常のトレーニングにはtrianingModel
を使用します。 2つのモデルは重みを共有するため、一方をトレーニングすることはもう一方をトレーニングすることです。
checkingModel.predict(X)
を使用して、Denseレイヤーの出力を表示するためだけにcheckingModel
を使用します
オプション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.predict(X)
で必要な値を確認するには、checkingModel
を使用します。そして、trainingModel
をトレーニングします。
(TFバックエンド)コンバージョンレイヤーのソリューション。
同じ質問があり、モデルの構成を書き直すことはできませんでした。単純なハックは、呼び出し関数を手動で実行することです。アクティベーションを制御できます。
Kerasからのコピーアンドペースト source 、self
をlayer
に変更。他のレイヤーでも同じことができます。
def conv_no_activation(layer, inputs, activation=False):
if layer.rank == 1:
outputs = K.conv1d(
inputs,
layer.kernel,
strides=layer.strides[0],
padding=layer.padding,
data_format=layer.data_format,
dilation_rate=layer.dilation_rate[0])
if layer.rank == 2:
outputs = K.conv2d(
inputs,
layer.kernel,
strides=layer.strides,
padding=layer.padding,
data_format=layer.data_format,
dilation_rate=layer.dilation_rate)
if layer.rank == 3:
outputs = K.conv3d(
inputs,
layer.kernel,
strides=layer.strides,
padding=layer.padding,
data_format=layer.data_format,
dilation_rate=layer.dilation_rate)
if layer.use_bias:
outputs = K.bias_add(
outputs,
layer.bias,
data_format=layer.data_format)
if activation and layer.activation is not None:
outputs = layer.activation(outputs)
return outputs
次に、main関数を少し変更する必要があります。まず、レイヤーをその名前で識別します。次に、前のレイヤーからアクティベーションを取得します。そして最後に、ターゲットレイヤーからの出力を計算します。
def get_output_activation_control(model, images, layername, activation=False):
"""Get activations for the input from specified layer"""
inp = model.input
layer_id, layer = [(n, l) for n, l in enumerate(model.layers) if l.name == layername][0]
prev_layer = model.layers[layer_id - 1]
conv_out = conv_no_activation(layer, prev_layer.output, activation=activation)
functor = K.function([inp] + [K.learning_phase()], [conv_out])
return functor([images])
これが小さなテストです。 VGG16モデルを使用しています。
a_relu = get_output_activation_control(vgg_model, img, 'block4_conv1', activation=True)[0]
a_no_relu = get_output_activation_control(vgg_model, img, 'block4_conv1', activation=False)[0]
print(np.sum(a_no_relu < 0))
> 245293
すべてのネガをゼロに設定して、VGG16ReLu操作に埋め込まれた後に取得された結果と比較します。
a_no_relu[a_no_relu < 0] = 0
print(np.allclose(a_relu, a_no_relu))
> True