Tensorflow 自定义激活函数

Tensorflow custom activation function

我使用 TensorFlow 实现了一个网络,并在我的代码中创建了执行以下操作的模型:

def multilayer_perceptron(x, weights, biases):
    layer_1 = tf.add(tf.matmul(x, weights["h1"]), biases["b1"])
    layer_1 = tf.nn.relu(layer_1)
    out_layer = tf.add(tf.matmul(layer_1, weights["out"]), biases["out"])
    return out_layer

我初始化权重和偏差:

weights = {
    "h": tf.Variable(tf.random_normal([n_input, n_hidden_1])),
    "out": tf.Variable(tf.random_normal([n_hidden_1, n_classes]))
    }

biases = {
    "b": tf.Variable(tf.random_normal([n_hidden_1])),
    "out": tf.Variable(tf.random_normal([n_classes]))
    }

现在我想使用自定义激活函数。因此,我将 tf.nn.relu(layer_1) 替换为自定义激活函数 custom_sigmoid(layer_1),其定义为:

def custom_sigmoid(x):
    beta = tf.Variable(tf.random.normal(x.get_shape[1]))
    return tf.sigmoid(beta*x)

其中 beta 是可训练参数。我意识到这行不通,因为我不知道如何实现 TensorFlow 可以使用的导数。

问:如何在 TensorFlow 中使用自定义激活函数?如果有任何帮助,我将不胜感激。

这就是自动微分的美妙之处!您不需要知道如何计算函数的导数,只要您使用所有固有可微分的 tensorflow 构造(在 tensorflow 中有些函数只是不可微分函数)。

对于其他一切,导数都是由 tensorflow 为您计算的,可以使用本质上可微分的任何操作组合,您永远不需要考虑梯度。通过在测试用例中使用 tf.graidents 来验证它,以表明 tensorflow 正在计算相对于您的成本函数的梯度。

对于好奇的人,这里有一个关于自动微分的很好的解释:

https://alexey.radul.name/ideas/2013/introduction-to-automatic-differentiation/

您可以通过检查它是否存在于集合 tf.GraphKeys.TRAINABLE_VARIABLES 中来确保 beta 是可训练参数,这意味着优化器将计算其导数 w.r.t。成本并更新它(如果它不在您应该调查的那个集合中)。

我试着回答我自己的问题。这是我所做的以及似乎有效的事情:

首先我定义了一个自定义激活函数:

def custom_sigmoid(x, beta_weights):
    return tf.sigmoid(beta_weights*x)

然后我为激活函数创建权重:

beta_weights = {
    "beta1": tf.Variable(tf.random_normal([n_hidden_1]))
    }

最后我将 beta_weights 添加到我的模型函数并替换 multilayer_perceptron() 中的激活函数:

def multilayer_perceptron(x, weights, biases, beta_weights):
    layer_1 = tf.add(tf.matmul(x, weights["h1"]), biases["b1"])
    #layer_1 = tf.nn.relu(layer_1) # Old
    layer_1 = custom_sigmoid(x, beta_weights["beta1"]) # New
    out_layer = tf.add(tf.matmul(layer_1, weights["out"]), biases["out"])
    return out_layer