我想尝试在Keras中实现此激活功能。我之前已实施过自定义激活,例如正弦激活:
def sin(x):
return K.sin(x)
get_custom_objects().update({'sin': Activation(sin)})
然而,本文中的激活功能有3个独特的属性:
我认为,一旦我有处理上述3个问题的骨架,我可以自己计算出数学,但我会得到任何帮助!
答案 0 :(得分:5)
在这里,我们需要这两个中的一个:
如果您的参数不可训练,您可以为lambda图层定义函数。该函数采用一个输入张量,它可以返回任何你想要的东西:
import keras.backend as K
def customFunction(x):
#x can be either a single tensor or a list of tensors
#if a list, use the elements x[0], x[1], etc.
#Perform your calculations here using the keras backend
#If you could share which formula exactly you're trying to implement,
#it's possible to make this answer better and more to the point
#dummy example
alphaReal = K.variable([someValue])
alphaImag = K.variable([anotherValue]) #or even an array of values
realPart = alphaReal * K.someFunction(x) + ...
imagPart = alphaImag * K.someFunction(x) + ....
#You can return them as two outputs in a list (requires the fuctional API model
#Or you can find backend functions that join them together, such as K.stack
return [realPart,imagPart]
#I think the separate approach will give you a better control of what to do next.
如果您可以做,请浏览backend functions。
对于参数,您可以在上面的函数内部或外部将它们定义为keras常量或变量(K.constant
或K.variable
),甚至可以在模型输入中对它们进行转换。 See details in this answer
在模型中,您只需添加使用该功能的lambda图层。
model.add(Lambda(customFunction, output_shape=someShape))
output = Lambda(customFunction, ...)(inputOrListOfInputs)
如果您要向函数传递更多输入,则需要功能模型API 如果您正在使用Tensorflow,则会自动计算output_shape,我相信只有Theano需要它。 (不确定CNTK)。
自定义图层是您创建的新类。只有在您的函数中具有可训练参数时,才需要使用此方法。 (例如:用反向传播优化α)
Keras teaches it here。
基本上,你有一个__init__
方法可以传递常量参数,build
方法可以创建可训练参数(权重),call
方法可以进行计算(如果你没有可训练的参数,那就是lambda图层中的内容)和compute_output_shape
方法,这样你就可以告诉模型输出形状是什么。
class CustomLayer(Layer):
def __init__(self, alphaReal, alphaImag):
self.alphaReal = alphaReal
self.alphaImage = alphaImag
def build(self,input_shape):
#weights may or may not depend on the input shape
#you may use it or not...
#suppose we want just two trainable values:
weigthShape = (2,)
#create the weights:
self.kernel = self.add_weight(name='kernel',
shape=weightShape,
initializer='uniform',
trainable=True)
super(CustomLayer, self).build(input_shape) # Be sure to call this somewhere!
def call(self,x):
#all the calculations go here:
#dummy example using the constant inputs
realPart = self.alphaReal * K.someFunction(x) + ...
imagPart = self.alphaImag * K.someFunction(x) + ....
#dummy example taking elements of the trainable weights
realPart = self.kernel[0] * realPart
imagPart = self.kernel[1] * imagPart
#all the comments for the lambda layer above are valid here
#example returning a list
return [realPart,imagPart]
def compute_output_shape(self,input_shape):
#if you decide to return a list of tensors in the call method,
#return a list of shapes here, twice the input shape:
return [input_shape,input_shape]
#if you stacked your results somehow in a single tensor, compute a single tuple, maybe with an additional dimension equal to 2:
return input_shape + (2,)
答案 1 :(得分:4)
您需要实现" Layer"而不是常见的激活功能。
我认为在Keras中实施pReLU将是您的任务的一个很好的例子。见pReLU
答案 2 :(得分:1)
激活中的lambda函数对我有用。也许不是您想要的,但是比简单地使用内置激活功能要复杂得多。
encoder_outputs = Dense(units=latent_vector_len, activation=k.layers.Lambda(lambda z: k.backend.round(k.layers.activations.sigmoid(x=z))), kernel_initializer="lecun_normal")(x)
此代码将密集的输出从实数更改为0,1(即二进制)。
Keras发出警告,但代码仍然有效。