【问题标题】:Pass additional parameter in call function of custom keras layer在自定义 keras 层的调用函数中传递附加参数
【发布时间】:2017-09-15 20:08:36
【问题描述】:

我创建了一个自定义 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 ,可以在调用它的评估函数之前用一些值初始化。我不确定如何实现这一目标。正确的方法是什么? 谢谢

【问题讨论】:

    标签: python tensorflow deep-learning keras


    【解决方案1】:

    您应该像Concatenate 层一样工作。 (在该链接中搜索class Concatenate(_Merge):)。

    这些接受多个输入的层依赖于在列表中传递的输入(和输入形状)。

    查看buildcallcomput_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 个输入传递给 fitpredict 方法。

    但是使用新选项,Input(shape=...) 将需要两个输入,所以:

    nArray = np.full((X_train.shape[0],1),n)
    model.fit([X_train,nArray],Y_train,....)
    

    不幸的是,我无法使用只有一个元素的n。它必须具有完全相同数量的样本(这是 keras 限制)。

    【讨论】:

    • 谢谢丹尼尔。这正是我一直在寻找的。但是我尝试了你的代码,它给了我以下错误:My Code Error Error 你知道我为什么会得到这个吗?
    • An issue 这里说:这是两件事之一的症状:您的输入不是来自 keras.layers.Input() 您的输出不是 Keras 的输出层。确保您只传递给模型 1) 通过输入生成的输入 2) 由 Keras 层生成的输出,而不对其应用进一步的操作。
    • 好的,抱歉。现在它正在工作。请注意,nInput 现在是 Input,并且必须在创建模型时考虑到 Model([inputTensor,nInput],out)
    • 我已经尝试了很多东西,唯一真正有效的方法是将Input((1,)) 用于nInput,然后将n 训练为n=np.full((X_train.shape[0],1), nValue) --- 查看更新的答案。
    • 啊!找到答案,使用 K.variable 而不是 K.placeholder:stackoverflow.com/questions/46234722/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    • 2019-09-06
    • 1970-01-01
    • 2013-11-06
    • 2020-12-03
    • 1970-01-01
    • 2020-10-25
    相关资源
    最近更新 更多