Writing your own layer - tensorflow

I am very new to keras.
I'm trying to write (using Functional API) a custom layer in Keras as in Keras.io
class MyLayer(Layer):
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
super(MyLayer, self).__init__(**kwargs)
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(shape=(input_shape[1], self.output_dim),
initializer='uniform',
trainable=True)
super(MyLayer, self).build(input_shape) # Be sure to call this somewhere!
def call(self, x):
return K.dot(x, self.kernel)
def compute_output_shape(self, input_shape):
return (input_shape[0], self.output_dim)
calling as :
sourcedistribution = Mylayer(dropout2_target)
The error traceback is as follows:
File "/root/PycharmProjects/chNET/modelBuild.py", line 77, in
model = create_network([100, 100, 3])
File "/root/PycharmProjects/chNET/modelBuild.py", line 53, in create_network
sourcedistribution = Mylayer(dropout2_source)
NameError: global name 'Mylayer' is not defined
Please help to understand this error.

I think the only issue is you have defined MyLayer but you are calling it Mylayer.

Related

Keras load_model with custom objects doesn't work properly when class defined in other file

I got a problem with my custom layer
class L2Layer(tf.keras.layers.Layer):
def __init__(self, **kwargs):
super(L2Layer, self).__init__(**kwargs)
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self._x = self.add_weight(name='alpha_l2',
shape=(1,),
initializer='ones',
trainable=True)
super(L2Layer, self).build(input_shape) # Be sure to call this at the end
def call(self, x):
return self._x * tf.divide(x, tf.norm(x, ord='euclidean'))
def compute_output_shape(self, input_shape):
return input_shape[0]
which is saved in a different .py file, for instance: models.py.
When I am trying to load the model via
loaded_model = tf.keras.models.load_model('outputs/test.hdf5', custom_objects={'L2Layer': L2Layer})
I got the error:
NameError: name 'L2Layer' is not defined
Questions
How can I fix this problem?
You should define a get_config in class L2Layer .
Read this for more detail .

I want to use keras layers within my custom layer, but I am unable to return the output of the layer as a tensor instead of an object

The error shown is
Failed to convert object of type class 'tensorflow.python.keras.layers.pooling.MaxPooling2D'
to Tensor.
I have tried many things but I am unable to sort this error.
```class Mixed_pooling():
def __init__(self, **kwargs):
super(Mixed_pooling, self).__init__(**kwargs)
def build(self, input_shape):
self.alpha = self.add_weight(
name='alpha', shape=(1,),
initializer='random_normal',
trainable=True
)
super(Mixed_pooling, self).build(input_shape)
def call(self, x):
x1 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2,2), padding='VALID')
x2 = tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=(2,2), padding='VALID')
outputs = tf.add(tf.multiply(x1, self.alpha), tf.multiply(x2, (1-self.alpha)))
return outputs```
Providing the solution here (Answer Section) even though it is present in the Comment Section (Thanks to Slowpoke), for the benefit of the community.
As tf.keras.layers.MaxPooling2D() and tf.keras.layers.AveragePooling2D() are class objects, you need to instantiate the objects in build function and later use them in call function.
Modified Code -
import tensorflow as tf
class Mixed_pooling():
def __init__(self, **kwargs):
super(Mixed_pooling, self).__init__(**kwargs)
def build(self, input_shape):
self.alpha = self.add_weight(
name='alpha', shape=(1,),
initializer='random_normal',
trainable=True
)
self.maxpool=tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2,2), padding='VALID')
self.avgpool = tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=(2,2), padding='VALID')
super(Mixed_pooling, self).build(input_shape)
def call(self, x):
x1 = self.maxpool(x)
x2 = self.avgpool(x)
outputs = tf.add(tf.multiply(x1, self.alpha), tf.multiply(x2, (1-self.alpha)))
return outputs
layer1 = Mixed_pooling()
print(layer1)
Output -
<__main__.Mixed_pooling object at 0x7fce31e46550>
Hope this answers your question. Happy Learning.

Propagating through a custom layer in tensorflow just once

Given a custom layer in tensorflow, is it possible to let the model use it just during one epoch? The layer may just be ignored for all other epochs or simple be an identity.
For example: Given data I would like the layer to simply double the given data. The other layers should may work normally. How would one do that?
def do_stuff(data):
return 2*data
def run_once(data):
return tf.py_func(do_stuff,
[data],
'float32',
stateful=False,
name='I run once')
class CustomLayer(Layer):
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
self.trainable = False
super(CustomLayer, self).__init__(**kwargs)
def call(self, x):
res = tf.map_fn(run_once, x)
res.set_shape([x.shape[0],
self.output_dim[1],
self.output_dim[0],
x.shape[-1]])
return res
inputs = Input(shape=(224, 224, 1))
x = Lambda(preprocess_input(x), input_shape=(224, 224, 1), output_shape=(224, 224, 3))
outputs = Dense(1)(x)
model = Model(input=inputs, output=outputs)
output = model(x)
Interesting question. To execute a TF operation just in the first epoch, one could use tf.cond and tf.control_dependencies to check/update the value of a boolean tensor. For example, your custom layer could be implemented as follows:
class CustomLayer(Layer):
def __init__(self, **kwargs):
super(CustomLayer, self).__init__(**kwargs)
def build(self, input_shape):
self.first_epoch = tf.Variable(True)
def call(self, x):
res = tf.cond(self.first_epoch,
true_fn=lambda: run_once(x),
false_fn=lambda: x)
with tf.control_dependencies([res]):
assign_op = self.first_epoch.assign(False)
with tf.control_dependencies([assign_op]):
res = tf.identity(res)
return res
To validate that this layer works as expected, define run_once as:
def run_once(data):
print_op = tf.print('First epoch')
with tf.control_dependencies([print_op]):
out = tf.identity(data)
return out

Is there any way to debug a value inside a tensor while training on Keras?

I'm trying to implement my own layer on Keras with a TensorFlow backend.
Is there any way to print the value inside tensors while training?
For example, I want to print x and self.kernel in the following code:
class MyLayer(Layer):
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
super(MyLayer, self).__init__(**kwargs)
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(name='kernel',
shape=(input_shape[1], self.output_dim),
initializer='uniform',
trainable=True)
super(MyLayer, self).build(input_shape)
def call(self, x):
# print x
# print self.kernel
return K.dot(x, self.kernel)
def compute_output_shape(self, input_shape):
return (input_shape[0], self.output_dim)
You can use keras.backend.print_tensor, which is just an identity transform that has the side-effect of printing the value of the tensor, and optionally a message. For example:
import keras.backend as K
def call(self, x):
return K.dot(K.print_tensor(x, message='Value of x'),
K.print_tensor(self.kernel,
message='Value of kernel'))
See https://keras.io/backend/#print_tensor for more information.
You can also use tf.print when using the TensorFlow backend.
def call(self, x):
tf.print(x)
tf.print(self.kernel)
return K.dot(x, self.kernel)

when define my own keras layer occur a none tensor object

here is my own layer code and the model can compile and predict fine, but when I use the model method model.fit(x,y) it turn out an error about none tensor error, and I can not find the reason
class CenterPointClassifierLayer(Layer):
def __init__(self, c, **kwargs):
self.c = c
super(CenterPointClassifierLayer, self).__init__(**kwargs)
def build(self, input_shape):
# check input_shape
if len(input_shape) != 2:
raise 'input should be in 1 dimension'
self.kernel = self.add_weight(name='kernel',
shape=(self.c, input_shape[1]),
initializer='uniform',
trainable=True)
self.one = K.constant(np.ones((self.c, 1)))
super(CenterPointClassifierLayer, self).build(input_shape)
def call(self, x):
def elem_op(pre, x_input):
x_shape = K.int_shape(x_input)
e = K.reshape(x_input, (1, x_shape[0]))
_x = K.dot(self.one, e)
del_x = K.square(tf.subtract(self.kernel, _x))
distance = K.sum(del_x, axis=1)
_c = K.argmin(distance)
_class = K.one_hot(_c, self.c)
return _class
y_pred = tf.scan(elem_op, x, initializer=K.one_hot(1, self.c))
return y_pred
def compute_output_shape(self, input_shape):
out_shape = (input_shape[0], self.c)
return out_shape
and here is the error i got when use fit method:
File "\tensorflow\python\ops\math_ops.py", line 412, in square
return gen_math_ops.square(x, name=name)
File "\tensorflow\python\ops\gen_math_ops.py", line 2585, in square
result = _op_def_lib.apply_op("Square", x=x, name=name)
File "\tensorflow\python\framework\op_def_library.py", line 509, in apply_op
(input_name, err))
ValueError: Tried to convert 'x' to a tensor and failed. Error: None values not supported.
please help, how can i fix the error when fit!!!
I do not know where the x come from and got the none values, and why there a square op in tf