在自定义Keras层中使用python代码和tf.py_func

时间:2018-05-05 09:04:45

标签: python tensorflow keras

我想编写自己的Keras层来调用python函数。 所以我遇到tf.py_func应该真正做到这一点。

我尝试了以下内容:在 MyLayer 类的调用方法中,我在tf.py_func中包装了自定义python函数 myFunc 。所以call-method返回tf.py_func(myFunc, [input], tf.float32)

我收到以下错误消息:

TypeError: unsupported operand type(s) for %=: 'int' and 'NoneType'

在自定义Keras图层中调用python函数的正确方法是什么?我做错了什么?

4 个答案:

答案 0 :(得分:1)

您必须显示图层的代码以及传递给pyfunc的函数,以便我们了解错误。 但是,尽管可以在自定义Keras层中嵌入tf函数,但在这种情况下,最好的选择可能是使用Keras lambda层: https://keras.io/layers/core/#lambda

这直接将python函数作为参数。与tf.py_func一样,它期望一个函数将numpy数组作为输入并输出一个numpy数组。

答案 1 :(得分:1)

如果在def build(self,input_shape):处声明权重,则必须在tf.py_func调用之后“使用”所有权重。

import tensorflow as tf

from keras import backend as K
from keras.engine.topology import Layer

class MultiplyLayer(Layer):

    def __init__(self, **kwargs):

        super(MultiplyLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        self.filters = self.add_weight(name='Filters', shape=(1, input_shape[1]), initializer='uniform', trainable=True)

        super(MultiplyLayer, self).build(input_shape)  # Be sure to call this at the end

    def call(self, x):
        xw = x * self.filters

        def my_func(x):
            return 5 * x

        X = tf.py_func(my_func, [xw], tf.float32)

        return X + (self.filters - self.filters)

    def compute_output_shape(self, input_shape):
        return (input_shape)

def get_model():
    model = Sequential()

    model.add(MultiplyLayer(input_shape=(num_features,)))

    model.add(Dense(128, activation='relu'))
    model.add(Dropout(0.25))
    model.add(Dense(64, activation='relu'))
    model.add(Dropout(0.4))
    model.add(Dense(num_classes, activation='softmax'))
    model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])
    return model

model = get_model()
model.summary()
model.fit(X_train, y_train_hot, batch_size=batch_size, epochs=epochs, verbose=verbose, validation_data=(X_test, y_test_hot))

答案 2 :(得分:0)

您只需要使用Lambda图层包装函数。 这是一个例子:

def complex_tf_fn(x):
    u, v = tf.nn.moments(x, axes=[1], keep_dims=True)
    return (x - u) / tf.sqrt(v)

with tf.device('/cpu:0'):
    model = tf.keras.Sequential([
        tf.keras.layers.Lambda(complex_tf_fn, input_shape=[784]),
        tf.keras.layers.Dense(1024, activation='relu'),
        tf.keras.layers.Lambda(complex_tf_fn),
        tf.keras.layers.Dense(10, activation='softmax')
    ])

答案 3 :(得分:0)

使用Lambda层包装函数,并在函数中调用py_func

def my_func(x):
    return 5 * x
def my_lambda_func(x):
    return py_func(my_func,[x],tf.float32)
x = Lambda(my_lambda_func)(x)