Skip to content
This repository has been archived by the owner on Nov 3, 2022. It is now read-only.

Added Inverse Square Root Linear Unit (ISRLU) activation layer #456

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ keras_contrib/callbacks/snapshot.py @titu1994


# layers
keras_contrib/layers/advanced_activations/isrlu.py @SriRangaTarun
keras_contrib/layers/advanced_activations/sinerelu.py @wilderrodrigues
keras_contrib/layers/advanced_activations/swish.py @gabrieldemarmiesse
keras_contrib/layers/convolutional/subpixelupscaling.py @titu1994
Expand Down
1 change: 1 addition & 0 deletions keras_contrib/layers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import absolute_import

from .advanced_activations.isrlu import ISRLU
from .advanced_activations.pelu import PELU
from .advanced_activations.srelu import SReLU
from .advanced_activations.swish import Swish
Expand Down
79 changes: 79 additions & 0 deletions keras_contrib/layers/advanced_activations/isrlu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
from keras import backend as K
from keras.layers import Layer
from keras_contrib.utils.test_utils import to_tuple
from keras_contrib.utils.test_utils import is_tf_keras


class ISRLU(Layer):
"""Inverse Square Root Linear Unit
See: https://arxiv.org/pdf/1710.09967.pdf by AI Perf
Reference: https://en.wikipedia.org/wiki/Activation_function
Inverse Square Root Linear activation f(α, x):
x >= 0: x
x < 0: x / sqrt(1 + α * x^2)
# Input shape
Arbitrary. Use the keyword argument `input_shape`
(tuple of integers, does not include the samples axis)
when using this layer as the first layer in a model.
# Output shape
Same shape as the input.
# Arguments
alpha: Value of the alpha weights (float)
NOTE : This function can become unstable for
negative values of α (it may return
NaNs). In particular, this happens when
α < 0 and x < -1/sqrt(α).
If this happens, try limiting the magnitude
of α below a certain threshold, such that
1 + α * x^2 is always positive.
Alternatively, you can normalize the inputs
into fixed ranges before passing them to ISRLU.
Adjust the value of α based on your specific
dataset and use-case.
# Example
model = Sequential()
model.add(Dense(5, input_shape=(15,))
model.add(ISRLU(alpha=-0.3))
"""
def __init__(self,
alpha=0.1,
**kwargs):

super(ISRLU, self).__init__(**kwargs)
self.alpha = alpha
self.trainable = False

if is_tf_keras:
def alpha_initializer(self, input_shape, dtype='float32', partition_info=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the other PR, partition_info is not used and is_tf_keras if loop can be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RaphaelMeudec The initializer does not work in tf.keras without the partition_info argument.

Copy link
Contributor Author

@SriRangaTarun SriRangaTarun Mar 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gabrieldemarmiesse Added **kwargs

return self.alpha * K.ones(input_shape,
dtype=dtype)

else:
def alpha_initializer(self, input_shape, dtype='float32'):
return self.alpha * K.ones(input_shape,
dtype=dtype)

def build(self, input_shape):
input_shape = to_tuple(input_shape)
new_input_shape = input_shape[1:]
self.alphas = self.add_weight(shape=new_input_shape,
name='{}_alphas'.format(self.name),
initializer=self.alpha_initializer,
trainable=self.trainable)
self.build = True

def call(self, x):
def inverse_quadratic_square_root(x):
return x / K.sqrt(1 + self.alphas * K.square(x))

return K.switch(K.less(x, K.zeros_like(x)), inverse_quadratic_square_root(x), x)

def compute_output_shape(self, input_shape):
return input_shape

def get_config(self):
config = {'alpha': self.alpha,
'trainable': self.trainable}
base_config = super(ISRLU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
15 changes: 15 additions & 0 deletions tests/keras_contrib/layers/advanced_activations/test_isrlu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
import pytest
from keras_contrib.utils.test_utils import layer_test
from keras_contrib.layers import ISRLU


@pytest.mark.parametrize('alpha', [0.2, 0.3, -0.01])
def test_isrlu(alpha):
layer_test(ISRLU,
kwargs={'alpha': alpha},
input_shape=(2, 3, 4))


if __name__ == '__main__':
pytest.main([__file__])