我想用自定义keras图层操纵前一层的激活。下面的图层只是将一个数字乘以前一层的激活。
class myLayer(Layer):
def __init__(self, **kwargs):
super(myLayer, self).__init__(**kwargs)
def build(self, input_shape):
self.output_dim = input_shape[0][1]
super(myLayer, self).build(input_shape)
def call(self, inputs, **kwargs):
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)
forTest = changed
forTrain = inputs[0]
return K.in_train_phase(forTrain, forTest)
def compute_output_shape(self, input_shape):
print(input_shape)
return (input_shape[0][0], self.output_dim)
我正在创建模型
inputTensor = Input((5,))
out = Dense(units, input_shape=(5,),activation='relu')(inputTensor)
n = K.placeholder(shape=(1,))
auxInput = Input(tensor=n)
out = myLayer()([out, auxInput])
out = Dense(units, activation='relu')(out)
out = Dense(3, activation='softmax')(out)
model = Model(inputs=[inputTensor, auxInput], outputs=out)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics='acc'])
我尝试使用
时出现此错误 model.fit(X_train, Y_train, epochs=epochs, verbose=1)
错误
InvalidArgumentError: You must feed a value for placeholder tensor 'Placeholder_3' with dtype float and shape [1]
当我尝试将值赋予占位符时
model.fit([X_train, np.array([3])], Y_train, epochs=epochs, verbose=1)
我明白了:
ValueError: Error when checking model input: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 1 arrays but instead got the following list of 2 arrays:
我应该如何初始化这个占位符?我的目标是使用model.evaluate来测试推理期间模型的不同值的影响。 感谢。
答案 0 :(得分:5)
您可以使用Input(shape=(1,))
代替占位符。此外,由于input_shape
已经处理Dense
,因此无需向Input(shape=(5,))
提供inputTensor = Input(shape=(5,))
out = Dense(units, activation='relu')(inputTensor)
auxInput = Input(shape=(1,))
out = myLayer()([out, auxInput])
。
n
在将其输入模型时重复值n = 3
n_array = np.array([n] * len(X_train))
model.fit([X_train, n_array], Y_train, epochs=1, verbose=1)
,例如:
K.variable
上面描述的只是一个快速的黑客攻击。如果要为图层提供多个参数,可以在构造函数__init__()
中初始化class myLayer(Layer):
def __init__(self, default_scale=3.0, default_shift=1.0, **kwargs):
self.scale = K.variable(default_scale)
self.shift = K.variable(default_shift)
super(myLayer, self).__init__(**kwargs)
def call(self, inputs, **kwargs):
return K.in_train_phase(inputs, self.scale * inputs + self.shift)
inputTensor = Input(shape=(5,))
out = Dense(units, activation='relu')(inputTensor)
out = myLayer(name='my_layer')(out)
out = Dense(units, activation='relu')(out)
out = Dense(3, activation='softmax')(out)
model = Model(inputs=inputTensor, outputs=out)
。
例如,
K.set_value(model.get_layer('my_layer').scale, 5)
通过为此图层指定名称,可以更轻松地获取变量并在测试阶段修改值。例如。 ,mlr
。
答案 1 :(得分:4)
我找到了一个避免使用n
数组的解决方案。
不使用placeholder
,而是使用K.variable
:
n = K.variable([someInitialValue])
auxInput = Input(tensor=n)
然后您可以随时设置n
的值,即使在编译模型之后:
K.set_value(n,[anotherValue])
这使您无需重新编译模型即可继续进行培训,而无需将n
传递给fit
方法。
model.fit(X_train,Y_train,....)
如果使用这样的许多输入,你可以做到:
n = K.variable([val1,val2,val3,val4]) #tensor definition
K.set_value(n,[new1,new2,new3,new4]) #changing values
在图层中,第二个输入是n
的张量,将包含4个元素:
n1 = inputs[1][0]
n2 = inputs[1][1]
....