一、说明
TensorFlow 2发布已经接近2年时间,不仅继承了Keras快速上手和易于使用的特性,同时还扩展了原有Keras所不支持的分布式训练的特性。3大设计原则:简化概念,海纳百川,构建生态.这是本系列的第三部分,我们将创建激活层并在 TensorFlow 2 中训练它们。
之前我们已经了解了如何创建自定义损失函数 -使用 TensorFlow 2 创建自定义损失函数
自定义ReLU函数(来源:作者创建的图片)
二、介绍
在本文中,我们将了解如何创建自定义激活函数。虽然 TensorFlow 已经包含一堆内置激活函数,但有多种方法可以创建您自己的自定义激活函数或编辑现有激活函数。
ReLU(修正线性单元)仍然是任何神经网络架构的隐藏层中最常用的激活函数。ReLU 也可以表示为函数 f(x),其中,
f(x) = 0, 当 x < 0 时,
并且,当 x ≥ 0 时,f(x) = x。
因此,该函数仅考虑正部分,并写为:
f(x) = 最大值(0,x)
或在代码表示中,
if input > 0:
return input
else:
return 0
但这个ReLU函数是预定义的。如果我们想自定义此函数或创建我们自己的 ReLU 激活该怎么办?在 TensorFlow 中有一种非常简单的方法可以做到这一点——我们只需使用Lambda 层。
ReLU 和 GeLU 激活函数
如何使用 lambda 层?
tf.keras.layers.Lambda(lambda x: tf.abs(x))
Lambda 只是可以在 TensorFlow 中直接调用的另一层。在 lambda 层中,首先指定参数。在上面的代码片段中,该值为“x”(lambda x)。在本例中,我们想要求 x 的绝对值,因此我们使用 tf.abs(x)。因此,如果 x 的值为 -1,则该 lambda 层会将 x 的值更改为 1。
如何使用 lambda 层创建自定义 ReLU?
def custom_relu(x):
return K.maximum(0.0,x)
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(128,128)),
tf.keras.layers.Dense(512),
tf.keras.layers.Lambda(custom_relu),
tf.keras.layers.Dense(5, activation = 'softmax')
])
上面的代码片段展示了如何在 TensorFlow 模型中实现自定义 ReLU。我们创建一个函数 custom_relu 并返回 0 或 x 的最大值(与 ReLU 函数相同)。
在下面的顺序模型中,在 Dense 层之后,我们创建一个 Lambda 层并将其传递到自定义激活函数中。但这段代码仍然没有做任何与 ReLU 激活函数不同的事情。
当我们开始研究自定义函数的返回值时,乐趣就开始了。假设我们取 0.5 和 x 中的最大值,而不是 0 和 x。我们已经有了自己定制的 ReLU。然后可以根据需要更改这些值。
def custom_relu(x):
返回 K.maximum(0.5,x)
def custom_relu(x):
return K.maximum(0.5,x)
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(128,128)),
tf.keras.layers.Dense(512),
tf.keras.layers.Lambda(custom_relu),
tf.keras.layers.Dense(5, activation = 'softmax')
])
在 mnist 数据集上使用 lambda 激活的示例
#using absolute value (Lambda layer example 1)
import tensorflow as tf
from tensorflow.keras import backend as K
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128),
tf.keras.layers.Lambda(lambda x: tf.abs(x)),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)
将 ReLU 激活替换为 mnist 数据集上的绝对值,测试精度为 97.384%。
#using custom ReLU activation (Lambda layer example 2)
import tensorflow as tf
from tensorflow.keras import backend as K
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
def my_relu(x):
return K.maximum(-0.1, x)
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128),
tf.keras.layers.Lambda(my_relu),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)
将 ReLU 激活替换为自定义 ReLU 激活,在 mnist 数据集上取最大值 -0.1 或 x,测试精度为 97.778%。
三、结论
尽管 lambda 层使用起来非常简单,但它们有很多限制。在下一篇文章中,我将介绍如何在 TensorFlow 中创建可训练的完全自定义层。