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

Custome GRU with new input, modle can not be built #558

Open
Tony-sy opened this issue Jun 7, 2021 · 0 comments
Open

Custome GRU with new input, modle can not be built #558

Tony-sy opened this issue Jun 7, 2021 · 0 comments

Comments

@Tony-sy
Copy link

Tony-sy commented Jun 7, 2021

Hello bodies,
I'm trying to build a new GRU layer that takes the input and a code of zero-one sequenses, the code has the same size of the input, every digit of the code encodes one input value as follows: If the digit is one then the cell will consider the input value to do the callculations, while if the digit is 0, then the cell will consider part of the hidden state h(t-1) to do the callculations. The new cell should be used in API model
I defined the cell and the layer classes. as follows:
class MyGRUCell(Layer):
"""This Cell are ale to deal with missing values in the input
1- adding another input matrex is not possible, GRU needs only one input matrix
2- include the mask of missing values with the values in the same input.
The mask of the missing values looks like extra samples. It has the same shape of the
input.
so the input shape should be
"""
def init(self, units,
Input_activation = 'relu',
activation = 'tanh',
recurrent_activation='hard_sigmoid',
use_bias=True,
kernel_initializer='glorot_uniform',
recurrent_initializer='orthogonal',
bias_initializer='zeros',
kernel_regularizer=None,
recurrent_regularizer=None,
bias_regularizer=None,
kernel_constraint=None,
recurrent_constraint=None,
bias_constraint=None,
dropout=0.,
recurrent_dropout=0.,
implementation=0,
**kwargs):
super(MyGRUCell, self).init(**kwargs)
self.units = units
self.Input_activation = activations.get(Input_activation)
self.activation = activations.get(activation)
self.recurrent_activation = activations.get(recurrent_activation)
self.use_bias = use_bias

self.kernel_initializer = initializers.get(kernel_initializer)
self.recurrent_initializer = initializers.get(recurrent_initializer)
self.bias_initializer = initializers.get(bias_initializer)

self.kernel_regularizer = regularizers.get(kernel_regularizer)
self.recurrent_regularizer = regularizers.get(recurrent_regularizer)
self.bias_regularizer = regularizers.get(bias_regularizer)

self.kernel_constraint = constraints.get(kernel_constraint)
self.recurrent_constraint = constraints.get(recurrent_constraint)
self.bias_constraint = constraints.get(bias_constraint)

self.dropout = min(1., max(0., dropout))
self.recurrent_dropout = min(1., max(0., recurrent_dropout))
self.implementation = implementation
self.state_size = self.units
self._dropout_mask = None
self._recurrent_dropout_mask = None

def build(self, input_shape):
input_dim = input_shape[-1]
print("Building: in_d = ", input_dim)
# add weights (W) to be multiplied by x
self.kernel = self.add_weight(shape=(input_dim, self.units * 3),
name='kernel',
initializer=self.kernel_initializer,
regularizer=self.kernel_regularizer,
constraint=self.kernel_constraint)
# add weights (Uht-1) to e multiplied by
self.recurrent_kernel = self.add_weight(
shape=(self.units, self.units * 4),
name='recurrent_kernel',
initializer=self.recurrent_initializer,
regularizer=self.recurrent_regularizer,
constraint=self.recurrent_constraint)

if self.use_bias:
    self.bias = self.add_weight(shape=(self.units * 4,),
                                name='bias',
                                initializer=self.bias_initializer,
                                regularizer=self.bias_regularizer,
                                constraint=self.bias_constraint)
else:
    self.bias = None

self.recurrent_kernel_x = self.recurrent_kernel[:, :self.units]

self.recurrent_kernel_z = self.recurrent_kernel[:, self.units: self.units * 2]

self.recurrent_kernel_r = self.recurrent_kernel[:, self.units: self.units * 3]

self.recurrent_kernel_h = self.recurrent_kernel[:, self.units * 3:]

if self.use_bias:
    self.bias_x = self.bias[:self.units]
    self.bias_z = self.bias[self.units: self.units * 2]
    self.bias_r = self.bias[self.units: self.units * 3]
    self.bias_h = self.bias[self.units * 3:]
else:
    self.bias_x = None
    self.bias_z = None
    self.bias_r = None
    self.bias_h = None
self.built = True

print("Kernal size =", self.kernel.shape)
print("Built Completed")

def call(self, inputs, states, training=None):
print("Call of the cell . . .")
h_tm1 = states[0] # previous memory
print("Cell input shape: ",inputs.shape)
missing = inputs[:, int(inputs.shape[1]/2) :,:]
Values = inputs[:, : int(inputs.shape[1]/2),:]
print("Values and missing code is separated")
if self.implementation == 1:
## My input
h_as_x = K.dot(h_tm1, self.recurrent_kernel_x)
if self.use_bias:
# wh(t-1)+b
h_as_x = K.bias_add(h_as_x, self.bias_x)

    h_as_input = self.Input_activation(h_as_x)
   
    
    inputs_z = missing * Values + (1-missing) * h_as_input
    inputs_r = missing * Values + (1-missing) * h_as_input
    inputs_h = missing * Values + (1-missing) * h_as_input
    
    x_z = K.dot(inputs_z, self.kernel[:, :self.units])
    x_r = K.dot(inputs_r, self.kernel[:, self.units: self.units * 2])
    x_h = K.dot(inputs_h, self.kernel[:, self.units * 2:])
    if self.use_bias:
        x_z = K.bias_add(x_z, self.bias_z)
        x_r = K.bias_add(x_r, self.bias_r)
        x_h = K.bias_add(x_h, self.bias_h)
        
    h_tm1_z = h_tm1
    h_tm1_r = h_tm1
    h_tm1_h = h_tm1
    
    z = self.recurrent_activation(x_z + K.dot(h_tm1_z, self.recurrent_kernel_z))
    r = self.recurrent_activation(x_r + K.dot(h_tm1_r, self.recurrent_kernel_r))

    hh = self.activation(x_h + K.dot(r * h_tm1_h, self.recurrent_kernel_h))
else:
    # Custom implementation of inputs which are already embedding parameters
    print("Else...")
    matrix_x = K.dot(Values, self.kernel)
    if self.use_bias:
        matrix_x = K.bias_add(matrix_x, self.bias)
    
    matrix_inner = K.dot(h_tm1, self.recurrent_kernel[:, :2 * self.units])

    x_z = matrix_x[:, :self.units]
    x_r = matrix_x[:, self.units: 2 * self.units]
    recurrent_z = matrix_inner[:, :self.units]
    recurrent_r = matrix_inner[:, self.units: 2 * self.units]

    z = self.recurrent_activation(x_z + recurrent_z)
    r = self.recurrent_activation(x_r + recurrent_r)

    x_h = matrix_x[:, 2 * self.units:]
    recurrent_h = K.dot(r * h_tm1,
                        self.recurrent_kernel[:, 2 * self.units:])
    hh = self.activation(x_h + recurrent_h)
h = z * h_tm1 + (1 - z) * hh
print(h.shape)
np.concatenate((h, missing), axis =0)
if training is None:
        h._uses_learning_phase = True
print("Call of the Cell is built")
return h, [h],

def get_config(self):
config = {'units': self.units,
'activation': activations.serialize(self.activation),
'recurrent_activation': activations.serialize(self.recurrent_activation),
'use_bias': self.use_bias,
'kernel_initializer': initializers.serialize(self.kernel_initializer),
'recurrent_initializer': initializers.serialize(self.recurrent_initializer),
'bias_initializer': initializers.serialize(self.bias_initializer),
'kernel_regularizer': regularizers.serialize(self.kernel_regularizer),
'recurrent_regularizer': regularizers.serialize(self.recurrent_regularizer),
'bias_regularizer': regularizers.serialize(self.bias_regularizer),
'kernel_constraint': constraints.serialize(self.kernel_constraint),
'recurrent_constraint': constraints.serialize(self.recurrent_constraint),
'bias_constraint': constraints.serialize(self.bias_constraint),
'recurrent_dropout': self.recurrent_dropout,
'implementation': self.implementation}
base_config = super(MyGRUCell, self).get_config()
return dict(list(base_config.items()) + list(config.items()))

print("Cell is Built")
##################
######## Build the class of the GRU
class CMyGRU(RNN):
#@interfaces.legacy_recurrent_support
def init(self, units,
Input_activation= 'relu',
activation='tanh',
recurrent_activation='hard_sigmoid',
use_bias=True,
kernel_initializer='glorot_uniform',
recurrent_initializer='orthogonal',
bias_initializer='zeros',
kernel_regularizer=None,
recurrent_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
recurrent_constraint=None,
bias_constraint=None,
dropout=0.,
recurrent_dropout=0.,
implementation=1,
return_sequences=False,
return_state=False,
go_backwards=False,
stateful=False,
unroll=False,
**kwargs):
if implementation == 0:
warnings.warn('implementation=0 has been deprecated, '
'and now defaults to implementation=1.'
'Please update your layer call.')

    cell = MyGRUCell(units,
               Input_activation=Input_activation,
               activation=activation,
               recurrent_activation=recurrent_activation,
               use_bias=use_bias,
               kernel_initializer=kernel_initializer,
               recurrent_initializer=recurrent_initializer,
               bias_initializer=bias_initializer,
               kernel_regularizer=kernel_regularizer,
               recurrent_regularizer=recurrent_regularizer,
               bias_regularizer=bias_regularizer,
               kernel_constraint=kernel_constraint,
               recurrent_constraint=recurrent_constraint,
               bias_constraint=bias_constraint,
               dropout=dropout,
               recurrent_dropout=recurrent_dropout,
               implementation=implementation)
    super(CMyGRU, self).__init__(cell,
                          return_sequences=return_sequences,
                          return_state=return_state,
                          go_backwards=go_backwards,
                          stateful=stateful,
                          unroll=unroll,
                          **kwargs)
    self.activity_regularizer = regularizers.get(activity_regularizer)
    self.input_spec = [InputSpec(ndim=3)]

def call(self, inputs, mask=None, training=None, initial_state=None):
    print("Call of the Class...")
    print("Call Class input shape:", inputs.shape)
    self.cell._dropout_mask = None
    self.cell._recurrent_dropout_mask = None
    return super(CMyGRU, self).call(inputs,  
                                 mask=mask,
                                 training=training,
                                 initial_state=initial_state)

print("Layer is Built")
#######################

I'm trying to build a neural network model with the new GRU layer as follows:
Input_Features_size = 10
Enter = Input((Input_Features_size*2,1))
print(Enter.shape)
L1 = CMyGRU(units=20, return_sequences = True)(Enter)
L2 = CMyGRU(20, return_sequences = True)(L1, miss= mis_values)
L3 = CMyGRU(10, return_sequences = True )(L2, mis_values)
L4 = CMyGRU(1, return_sequences = False )(L3, mis_values)

Mdl = Model(inputs = Enter, outputs = L4)

opt= optimizers.Adam(lr = 0.001)
Mdl.compile(optimizer = opt, loss = losses.MeanSquaredError(), metrics = ['accuracy'])
Mdl.summary()

unfortunatilly, it gives the following error
ValueError: in user code:

<ipython-input-3-44cc98e553c7>:65 call  *
    mask=mask,
<ipython-input-2-c78e99a9f3df>:106 call  *
    missing = inputs[:, int(inputs.shape[1]/2) :,:]
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\util\dispatch.py:201 wrapper
    return target(*args, **kwargs)
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\ops\array_ops.py:1024 _slice_helper
    name=name)
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\util\dispatch.py:201 wrapper
    return target(*args, **kwargs)
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\ops\array_ops.py:1196 strided_slice
    shrink_axis_mask=shrink_axis_mask)
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\ops\gen_array_ops.py:10351 strided_slice
    shrink_axis_mask=shrink_axis_mask, name=name)
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\framework\op_def_library.py:744 _apply_op_helper
    attrs=attr_protos, op_def=op_def)
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\framework\func_graph.py:593 _create_op_internal
    compute_device)
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\framework\ops.py:3485 _create_op_internal
    op_def=op_def)
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\framework\ops.py:1975 __init__
    control_input_ops, op_def)
D:\Users\Me\Anaconda3\envs\Work_with_CPU\lib\site-packages\tensorflow\python\framework\ops.py:1815 _create_c_op
    raise ValueError(str(e))

ValueError: Index out of range using input dim 2; input has only 2 dims for '{{node c_my_gru/my_gru_cell/strided_slice}} = StridedSlice[Index=DT_INT32, T=DT_FLOAT, begin_mask=5, ellipsis_mask=0, end_mask=7, new_axis_mask=0, shrink_axis_mask=0](c_my_gru/strided_slice_2, c_my_gru/my_gru_cell/strided_slice/stack, c_my_gru/my_gru_cell/strided_slice/stack_1, c_my_gru/my_gru_cell/strided_slice/stack_2)' with input shapes: [?,1], [3], [3], [3] and with computed input tensors: input[3] = <1 1 1>.

Anyone can find the reason, I think it is related to shape of the input and how it is passed to the inner cell, but i don't know how to fix it.

@Tony-sy Tony-sy changed the title Custome GRU with new input can not be trained Custome GRU with new input, modle can not be built Jun 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant