我创建了一个自定义keras图层,目的是在推理期间手动更改上一层的激活。以下是简单地将激活与数字相乘的基本层。
import numpy as np
from keras import backend as K
from keras.layers import Layer
import tensorflow as tf
class myLayer(Layer):
def __init__(self, n=None, **kwargs):
self.n = n
super(myLayer, self).__init__(**kwargs)
def build(self, input_shape):
self.output_dim = input_shape[1]
super(myLayer, self).build(input_shape)
def call(self, inputs):
changed = tf.multiply(inputs, self.n)
forTest = changed
forTrain = inputs
return K.in_train_phase(forTrain, forTest)
def compute_output_shape(self, input_shape):
return (input_shape[0], self.output_dim)
当我像这样使用IRIS数据集
时,它工作正常model = Sequential()
model.add(Dense(units, input_shape=(5,)))
model.add(Activation('relu'))
model.add(myLayer(n=3))
model.add(Dense(units))
model.add(Activation('relu'))
model.add(Dense(3))
model.add(Activation('softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])
model.summary()
但是现在我想移动' n'从 init 到调用函数,所以我可以在训练后应用不同的n值来评估模型。我们的想法是在n中放置占位符,在调用其上的evaluate函数之前可以用一些值初始化它。我不知道如何实现这一目标。对此有什么正确的解决方法? 感谢
答案 0 :(得分:1)
您的工作方式应与Concatenate图层的工作方式相同。 (在该链接中搜索class Concatenate(_Merge):
)。
这些采用多个输入的图层依赖于在列表中传递的输入(和输入形状)。
请参阅build
,call
和comput_output_shape
中的验证部分:
def call(self,inputs):
if not isinstance(inputs, list):
raise ValueError('This layer should be called on a list of inputs.')
mainInput = inputs[0]
nInput = inputs[1]
changed = tf.multiply(mainInput,nInput)
#I suggest using an equivalent function in K instead of tf here, if you ever want to test theano or another backend later.
#if n is a scalar, then just "changed=nInput * mainInput" is ok
#....the rest of the code....
然后你调用这个图层传递一个列表。但为此,我强烈建议您远离Sequential
模型。他们是纯粹的限制。
from keras.models import Model
inputTensor = Input((5,)) # the original input (from your input_shape)
#this is just a suggestion, to have n as a manually created var
#but you can figure out your own ways of calculating n later
nInput = Input((1,))
#old answer: nInput = Input(tensor=K.variable([n]))
#creating the graph
out = Dense(units, input_shape=(5,),activation='relu')(inputTensor)
#your layer here uses the output of the dense layer and the nInput
out = myLayer()([out,nInput])
#here you will have to handle n with the same number of samples as x.
#You can use `inputs[1][0,0]` inside the layer
out = Dense(units,activation='relu')(out)
out = Dense(3,activation='softmax')(out)
#create the model with two inputs and one output:
model = Model([inputTensor,nInput], out)
#nInput is now a part of the model's inputs
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])
使用旧答案Input(tensor=...)
,模型不会像通常那样要求您将2个输入传递给fit
和predict
方法。
但是使用新选项Input(shape=...)
,它将需要两个输入,所以:
nArray = np.full((X_train.shape[0],1),n)
model.fit([X_train,nArray],Y_train,....)
不幸的是,我不能让n
只有一个元素。它必须具有完全相同数量的样本(这是keras限制)。