Introduce Symmetric/Reflection padding
Introduce two more padding variants which might fit better to time series forecasts than "same" (zero) padding.
The padding size has to be calculated as a function of the applied kernel size. Currently, I use n_{\text{pad}} = \frac{k - 1}{2}
which does not take strides other than one into account. Padding layers have to be passed as custom_objects
dictionary (custom_objects = {'SymmetricPadding2D': SymmetricPadding2D}
) when reloading the model from disk (model = load_model(experiment_name+'my_model.h5', custom_objects=custom_objects)
).
-
Add padding base class -
Add ReflectionPadding2D -
Add SymmetricPadding2D -
Add Sym/Ref padding to custom_objects => shifted to #62 (closed)
Code for paddings could look like this:
from keras.layers import ZeroPadding2D
import tensorflow as tf
class Paddings(ZeroPadding2D):
"""
Summary of padding methods based on tf.pad
Methods avaiable:
- ReflectionPadding2D
- SymmetricPadding2D
"""
@staticmethod
def get_padding_for_same(kernel_size):
"""
This methods calculates the padding size to keep input and output dimensions equal for a given kernel size
:param kernel_size:
:return:
"""
ks = np.array(kernel_size, dtype=np.int64)
if (d & 0x1 for d in ks):
pad = ((ks - 1) / 2).astype(np.int64)
pad = ((pad[0], pad[0]), (pad[1], pad[1]))
return pad
else:
raise NotImplementedError("even kernel size not implemented")
@staticmethod
def _set_paddings(padding):
if isinstance(padding, tuple):
pad1, pad2 = padding
if isinstance(pad1, tuple) and isinstance(pad2, tuple):
top_pad, bottom_pad = pad1
left_pad, right_pad = pad2
elif isinstance(pad1, int) and isinstance(pad2, int):
top_pad, bottom_pad = pad1, pad1
left_pad, right_pad = pad2, pad2
else:
raise NotImplementedError("Tuple, int mixtures not possible")
pattern = [[0, 0],
[top_pad, bottom_pad],
[left_pad, right_pad],
[0, 0]]
return pattern
class ReflectionPadding2D(Paddings, ZeroPadding2D):
"""
Works like ZeroPadding, but uses reflecting values are used instead of zeros
call: Copy pasted from
https://github.com/robertomest/neural-style-keras/blob/11fecd8e99228aab4851e4c00e85ed31217406db/layers.py#L11
"""
def call(self, x, mask=None):
"""
Call method
:param x:
:param mask:
:return:
"""
return tf.pad(x, self._set_paddings(padding=self.padding), mode='REFLECT')
class SymmetricPadding2D(Paddings, ZeroPadding2D):
"""
Works like ZeroPadding, but uses mode tf.pad with "symmetric"
"""
def call(self, x, mask=None):
"""
Call method
:param x:
:param mask:
:return:
"""
print(type(x))
return tf.pad(x, self._set_paddings(padding=self.padding), mode='SYMMETRIC')
Edited by Ghost User