调用自定义函数出现Input 0 of layer dense_1

我调用了自定义的激活函数以后,一直提示ValueError: Input 0 of layer dense_1 is incompatible with the layer: its rank is undefined, but the layer requires a defined rank.,这是什么缘故呢?

#-*- encoding:utf-8 -*-
#!/usr/local/env python
 
import numpy as np
import tensorflow as tf
import math
from tensorflow.python.framework import ops
 
def gaussian(x):
    return math.exp(- (x*x) / (0.25))
 
def gaussian_grad(x):
    return (-8) * x * math.exp(- (x*x) / (0.25))
 
gaussian_np = np.vectorize(gaussian)
gaussian_grad_np = np.vectorize(gaussian_grad)
 
gaussian_np_32 = lambda x: gaussian_np(x).astype(np.float32)
gaussian_grad_np_32 = lambda x: gaussian_grad_np(x).astype(np.float32)
 
def gaussian_grad_tf(x, name=None):
    with ops.name_scope(name, "gaussian_grad_tf", [x]) as name:
        y = tf.py_func(gaussian_grad_np_32, [x], [tf.float32], name=name, stateful=False)
        return y[0]
 
def my_py_func(func, inp, Tout, stateful=False, name=None, my_grad_func=None):
    # need to generate a unique name to avoid duplicates:
    random_name = "PyFuncGrad" + str(np.random.randint(0, 1E+8))
    tf.RegisterGradient(random_name)(my_grad_func)
    g = tf.get_default_graph()
    with g.gradient_override_map({"PyFunc": random_name, "PyFuncStateless": random_name}):
        return tf.py_func(func, inp, Tout, stateful=stateful, name=name)
 
def _gaussian_grad(op, pred_grad):
    x = op.inputs[0]
    cur_grad = gaussian_grad(x)
    next_grad = pred_grad * cur_grad
    return next_grad
 
def gaussian_activation(x, name=None):
    with ops.name_scope(name, "gaussian_activator", [x]) as name:
        y = my_py_func(gaussian_np_32 ,
                       [x],
                       [tf.float32],
                       stateful=False,
                       name=name,
                       my_grad_func=_gaussian_grad)
    return y[0]
 
 
mport numpy as np
import matplotlib.pyplot as plt
import tensorflow.python.keras as keras
from tensorflow.python.keras import layers
from tensorflow.keras.datasets import mnist
import tensorflow as tf
from tensorflow.python.framework import ops
from tensorflow.keras.layers import *
# print(tf.__version__) -> 2.1.0

from zuoye1 import gaussian_activation
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# print(np.max(x_train)) -> 255
# print(x_train.shape) -> 60000,28,28

# 归一化
x_train = x_train / 255.0
x_test = x_test / 255.0




model = keras.Sequential()
model.add(layers.Flatten(input_shape=(28, 28)))
model.add(layers.Dense(128,activation=gaussian_activation))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(10, activation='softmax'))

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)
res = model.evaluate(x_test, y_test)
# 返回损失和精度
print(model.metrics_names)
print(res)

 

您的代码缺少定义模型。如果您希望使用自定义激活函数,您需要在定义模型时将其传递给模型的某个层。例如,您可以在模型中定义一个全连接层,并将自定义激活函数传递给该层,如下所示:

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(units=64, input_shape=(32,), activation=gaussian_activation))

在这里,我们将自定义的激活函数“gaussian_activation”作为“Dense”层的激活函数传递给该层。此外,您可能希望将自定义激活函数的梯度函数定义为一个独立的函数,然后将其作为参数传递给“my_py_func”,以便您的自定义激活函数可以正确地进行反向传播。