Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
keras-team
GitHub Repository: keras-team/keras-io
Path: blob/master/examples/keras_recipes/antirectifier.py
3507 views
1
"""
2
Title: Simple custom layer example: Antirectifier
3
Author: [fchollet](https://twitter.com/fchollet)
4
Date created: 2016/01/06
5
Last modified: 2023/11/20
6
Description: Demonstration of custom layer creation.
7
Accelerator: GPU
8
"""
9
10
"""
11
## Introduction
12
13
This example shows how to create custom layers, using the Antirectifier layer
14
(originally proposed as a Keras example script in January 2016), an alternative
15
to ReLU. Instead of zeroing-out the negative part of the input, it splits the negative
16
and positive parts and returns the concatenation of the absolute value
17
of both. This avoids loss of information, at the cost of an increase in dimensionality.
18
To fix the dimensionality increase, we linearly combine the
19
features back to a space of the original size.
20
"""
21
22
"""
23
## Setup
24
"""
25
26
import keras
27
from keras import layers
28
from keras import ops
29
30
"""
31
## The Antirectifier layer
32
33
To implement a custom layer:
34
35
- Create the state variables via `add_weight()` in `__init__` or `build()`.
36
Similarly, you can also create sublayers.
37
- Implement the `call()` method, taking the layer's input tensor(s) and
38
return the output tensor(s).
39
- Optionally, you can also enable serialization by implementing `get_config()`,
40
which returns a configuration dictionary.
41
42
See also the guide
43
[Making new layers and models via subclassing](https://keras.io/guides/making_new_layers_and_models_via_subclassing/).
44
"""
45
46
47
class Antirectifier(layers.Layer):
48
def __init__(self, initializer="he_normal", **kwargs):
49
super().__init__(**kwargs)
50
self.initializer = keras.initializers.get(initializer)
51
52
def build(self, input_shape):
53
output_dim = input_shape[-1]
54
self.kernel = self.add_weight(
55
shape=(output_dim * 2, output_dim),
56
initializer=self.initializer,
57
name="kernel",
58
trainable=True,
59
)
60
61
def call(self, inputs):
62
inputs -= ops.mean(inputs, axis=-1, keepdims=True)
63
pos = ops.relu(inputs)
64
neg = ops.relu(-inputs)
65
concatenated = ops.concatenate([pos, neg], axis=-1)
66
mixed = ops.matmul(concatenated, self.kernel)
67
return mixed
68
69
def get_config(self):
70
# Implement get_config to enable serialization. This is optional.
71
base_config = super().get_config()
72
config = {"initializer": keras.initializers.serialize(self.initializer)}
73
return dict(list(base_config.items()) + list(config.items()))
74
75
76
"""
77
## Let's test-drive it on MNIST
78
"""
79
80
# Training parameters
81
batch_size = 128
82
num_classes = 10
83
epochs = 20
84
85
# The data, split between train and test sets
86
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
87
88
x_train = x_train.reshape(-1, 784)
89
x_test = x_test.reshape(-1, 784)
90
x_train = x_train.astype("float32")
91
x_test = x_test.astype("float32")
92
x_train /= 255
93
x_test /= 255
94
print(x_train.shape[0], "train samples")
95
print(x_test.shape[0], "test samples")
96
97
# Build the model
98
model = keras.Sequential(
99
[
100
keras.Input(shape=(784,)),
101
layers.Dense(256),
102
Antirectifier(),
103
layers.Dense(256),
104
Antirectifier(),
105
layers.Dropout(0.5),
106
layers.Dense(10),
107
]
108
)
109
110
# Compile the model
111
model.compile(
112
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
113
optimizer=keras.optimizers.RMSprop(),
114
metrics=[keras.metrics.SparseCategoricalAccuracy()],
115
)
116
117
# Train the model
118
model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.15)
119
120
# Test the model
121
model.evaluate(x_test, y_test)
122
123