when define my own keras layer occur a none tensor object - tensorflow

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

Related

Tensorflow 2.0 How to handle tf.Variable as Weight in __call__ function?

I made 'Decoder' layer to make Product Item Matrix in Tensorflow.
I've tried to initialize W, bias and make a calculation to get loss using some value.
class Decoder(tf.keras.layers.Layer):
def __init__(self, units=len(counter), input_dim=300):
super(Decoder, self).__init__()
self.trainer = Trainer(vec_dict)
w_init = tf.random_normal_initializer()
self.w = tf.Variable(initial_value=w_init(shape=(units, input_dim), dtype='float32'), trainable=True)
b_init = tf.zeros_initializer()
self.b = tf.Variable(initial_value=b_init(shape=(units,), dtype='float32'), trainable=True)
def call(self, x_play, y_pos, y_neg):
x = self.trainer(x_play)
user_vector = x[..., tf.newaxis, :]
wp = self.w.numpy()[y_pos]
bp = self.b.numpy()[y_pos]
pos_mul = tf.multiply(user_vector, wp)
pos = tf.reduce_sum(pos_mul, axis=-1) + bp
wn = self.w.numpy()[y_neg]
bn = self.b.numpy()[y_neg]
neg_mul = tf.multiply(user_vector, wn)
neg = tf.reduce_sum(neg_mul, axis=-1) + bn
tot = tf.sigmoid(tf.concat([pos, neg], axis=1))
return tot
As you can see this, If I used '.numpy()', it can make me possible to get matrix which has the shape what I want to.
For instance, self.w has (10000, 300) shapes, and y_pos has (256, 100)
and self.w.numpy()[y_pos] has (256, 100, 300)
The problem is that if I ran this code for training, I got these kind of errors:
NotImplementedError: in converted code:
<ipython-input-835-8d5f0b593979>:4 train_step *
predictions = model(x, y_pos, y_neg)
/usr/local/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/base_layer.py:847 __call__
outputs = call_fn(cast_inputs, *args, **kwargs)
<ipython-input-838-b9b896ea4fff>:64 call
wp = self.w.numpy()[y_pos]
/usr/local/lib/python3.7/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:579 numpy
"numpy() is only available when eager execution is enabled.")
NotImplementedError: numpy() is only available when eager execution is enabled.
Somebody else who let me know what's going on.

Define custom LSTM with multiple inputs

Following the tutorial writing custom layer, I am trying to implement a custom LSTM layer with multiple input tensors. I am providing two vectors input_1 and input_2 as a list [input_1, input_2] as suggested in the tutorial. The single input code is working but when I change the code for multiple inputs, its throwing the error,
self.kernel = self.add_weight(shape=(input_shape[0][-1], self.units),
TypeError: 'NoneType' object is not subscriptable.
What change I have to do to get rid of the error? Here is the modified code.
class MinimalRNNCell(keras.layers.Layer):
def __init__(self, units, **kwargs):
self.units = units
self.state_size = units
super(MinimalRNNCell, self).__init__(**kwargs)
def build(self, input_shape):
print(type(input_shape))
self.kernel = self.add_weight(shape=(input_shape[0][-1], self.units),
initializer='uniform',
name='kernel')
self.recurrent_kernel = self.add_weight(
shape=(self.units, self.units),
initializer='uniform',
name='recurrent_kernel')
self.built = True
def call(self, inputs, states):
prev_output = states[0]
h = K.dot(inputs[0], self.kernel)
output = h + K.dot(prev_output, self.recurrent_kernel)
return output, [output]
# Let's use this cell in a RNN layer:
cell = MinimalRNNCell(32)
input_1 = keras.Input((None, 5))
input_2 = keras.Input((None, 5))
layer = RNN(cell)
y = layer([input_1, input_2])
Error is because of the line, y = layer([input_1, input_2]).
Replacing that line with y = layer((input_1, input_2)) (passing as Tuple of Inputs rather than List of Inputs), will resolve the error.
Complete working code using tf.keras is shown below:
from tensorflow import keras
from tensorflow.keras import backend as K
from tensorflow.keras.layers import RNN
import tensorflow as tf
class MinimalRNNCell(tf.keras.layers.Layer):
def __init__(self, units, **kwargs):
self.units = units
self.state_size = units
#self.state_size = [tf.TensorShape([units])]
super(MinimalRNNCell, self).__init__(**kwargs)
def build(self, input_shape):
print(type(input_shape))
self.kernel = self.add_weight(shape=(input_shape[0][-1], self.units),
initializer='uniform',
name='kernel')
self.recurrent_kernel = self.add_weight(
shape=(self.units, self.units),
initializer='uniform',
name='recurrent_kernel')
self.built = True
def call(self, inputs, states):
prev_output = states[0]
h = K.dot(inputs[0], self.kernel)
output = h + K.dot(prev_output, self.recurrent_kernel)
return output, [output]
# Let's use this cell in a RNN layer:
cell = MinimalRNNCell(32)
input_1 = tf.keras.Input((None, 5))
input_2 = tf.keras.Input((None, 5))
layer = RNN(cell)
y = layer((input_1, input_2))
Output of the above code is:
<class 'tuple'>
Hope this helps. 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

Attention layer output shape issue

I have been using BiLSTMs to classify each word in sentences and my input is n_sentences, max_sequence_length, classes. Recently, I have been trying to use this attention layer: https://www.kaggle.com/takuok/bidirectional-lstm-and-attention-lb-0-043
class Attention(Layer):
def __init__(self, step_dim,
W_regularizer=None, b_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
self.supports_masking = True
self.init = initializers.get('glorot_uniform')
self.W_regularizer = regularizers.get(W_regularizer)
self.b_regularizer = regularizers.get(b_regularizer)
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.bias = bias
self.step_dim = step_dim
self.features_dim = 0
super(Attention, self).__init__(**kwargs)
def build(self, input_shape):
assert len(input_shape) == 3
self.W = self.add_weight((input_shape[-1],),
initializer=self.init,
name='{}_W'.format(self.name),
regularizer=self.W_regularizer,
constraint=self.W_constraint)
self.features_dim = input_shape[-1]
if self.bias:
self.b = self.add_weight((input_shape[1],),
initializer='zero',
name='{}_b'.format(self.name),
regularizer=self.b_regularizer,
constraint=self.b_constraint)
else:
self.b = None
self.built = True
def compute_mask(self, input, input_mask=None):
return None
def call(self, x, mask=None):
features_dim = self.features_dim
step_dim = self.step_dim
eij = K.reshape(K.dot(K.reshape(x, (-1, features_dim)),
K.reshape(self.W, (features_dim, 1))), (-1, step_dim))
if self.bias:
eij += self.b
eij = K.tanh(eij)
a = K.exp(eij)
if mask is not None:
a *= K.cast(mask, K.floatx())
a /= K.cast(K.sum(a, axis=1, keepdims=True) + K.epsilon(), K.floatx())
a = K.expand_dims(a)
weighted_input = x * a
return K.sum(weighted_input, axis=1)
def compute_output_shape(self, input_shape):
return input_shape[0], self.features_dim
My output needs to be (samples, steps, features) or I get this
ValueError: Error when checking target: expected dense_2 to have 2 dimensions, but got array with shape (656, 109, 2)
So I switched:
return input_shape[0], self.features_dim
to
return input_shape[0], self.step_dim, self.features_dim
Doing so I get another error:
InvalidArgumentError: Incompatible shapes: [32,109] vs. [32]
[[{{node metrics/acc/Equal}}]]
What do I need to modify to actually use the attention layer on my sentences ?
Are u using SeqSelfAttention?
I faced the same issue and instead of SeqSelfAttention I used SeqWeightedAttention - and it solved my problem.
model.add(SeqWeightedAttention())

Writing your own layer

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.