将keras占位符初始化为自定义图层的输入

Wal*_*eed 4 python neural-network keras tensorflow

我想用自定义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)
Run Code Online (Sandbox Code Playgroud)

我正在创建模型

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'])
Run Code Online (Sandbox Code Playgroud)

我尝试使用时出现此错误

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]
Run Code Online (Sandbox Code Playgroud)

当我尝试将值赋予占位符时

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:
Run Code Online (Sandbox Code Playgroud)

我该如何初始化这个占位符?我的目标是使用model.evaluate来测试推理期间模型的不同值的影响.谢谢.

Dan*_*ler 8

我找到了避免在上使用数组的解决方案n

代替使用a placeholder,而使用K.variable

n = K.variable([someInitialValue])
auxInput = Input(tensor=n)
Run Code Online (Sandbox Code Playgroud)

然后n,即使在编译模型之后,也可以随时设置如下所示的值:

K.set_value(n,[anotherValue])
Run Code Online (Sandbox Code Playgroud)

这可以让你保持训练,而无需重新编译模型,并没有通过nfit法。

model.fit(X_train,Y_train,....)
Run Code Online (Sandbox Code Playgroud)

如果使用许多类似的输入,则可以:

n = K.variable([val1,val2,val3,val4]) #tensor definition
K.set_value(n,[new1,new2,new3,new4]) #changing values
Run Code Online (Sandbox Code Playgroud)

在图层内部,第二个输入(即张量)n将包含4个元素:

n1 = inputs[1][0]
n2 = inputs[1][1]
....
Run Code Online (Sandbox Code Playgroud)


Yu-*_*ang 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])
Run Code Online (Sandbox Code Playgroud)

n将数据输入模型时重复该值,例如:

n = 3
n_array = np.array([n] * len(X_train))
model.fit([X_train, n_array], Y_train,  epochs=1, verbose=1)
Run Code Online (Sandbox Code Playgroud)

编辑:

上面所描述的只是一个快速的黑客.如果要为图层提供多个参数,可以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)
Run Code Online (Sandbox Code Playgroud)

通过为此图层指定名称,可以更轻松地获取变量并在测试阶段修改值.例如,K.set_value(model.get_layer('my_layer').scale, 5).