def __call__(self, inputs, initial_state=None, initial_readout=None, ground_truth=None, **kwargs): req_num_inputs = 1 + self.num_states inputs = _to_list(inputs) inputs = inputs[:] if len(inputs) == 1: if initial_state is not None: if type(initial_state) is list: inputs += initial_state else: inputs.append(initial_state) else: if self.readout: initial_state = self._get_optional_input_placeholder('initial_state', self.num_states - 1) else: initial_state = self._get_optional_input_placeholder('initial_state', self.num_states) inputs += _to_list(initial_state) if self.readout: if initial_readout is None: initial_readout = self._get_optional_input_placeholder('initial_readout') inputs.append(initial_readout) if self.teacher_force: req_num_inputs += 1 if ground_truth is None: ground_truth = self._get_optional_input_placeholder('ground_truth') inputs.append(ground_truth) assert len(inputs) == req_num_inputs, "Required " + str(req_num_inputs) + " inputs, received " + str(len(inputs)) + "." with K.name_scope(self.name): if not self.built: self.build(K.int_shape(inputs[0])) if self._initial_weights is not None: self.set_weights(self._initial_weights) del self._initial_weights self._initial_weights = None previous_mask = _collect_previous_mask(inputs[:1]) user_kwargs = kwargs.copy() if not _is_all_none(previous_mask): if 'mask' in inspect.getargspec(self.call).args: if 'mask' not in kwargs: kwargs['mask'] = previous_mask input_shape = _collect_input_shape(inputs) output = self.call(inputs, **kwargs) output_mask = self.compute_mask(inputs[0], previous_mask) output_shape = self.compute_output_shape(input_shape[0]) self._add_inbound_node(input_tensors=inputs, output_tensors=output, input_masks=previous_mask, output_masks=output_mask, input_shapes=input_shape, output_shapes=output_shape, arguments=user_kwargs) if hasattr(self, 'activity_regularizer') and self.activity_regularizer is not None: regularization_losses = [self.activity_regularizer(x) for x in _to_list(output)] self.add_loss(regularization_losses, _to_list(inputs)) return output
def __call__(self, inputs, **kwargs): """ Overriding the Layer's __call__ method for graph wrappers. The overriding is mostly based on the __call__ code from 'keras/engine/base_layer.py' for the moment, with some changes to handle graphs. """ # If arguments are 'keras-style' arguments, let keras to the job if K.is_tensor(inputs) or (isinstance(inputs, list) and not isinstance(inputs, GraphWrapper)): output = super(GraphLayer, self).__call__(inputs, **kwargs) else: if isinstance(inputs, list) and not isinstance(inputs, GraphWrapper): inputs = inputs[:] with K.name_scope(self.name): # Build the layer if not self.built: # Check the comatibilty of inputs for each inputs (some can # be GraphWrapper) if isinstance(inputs, list) and not isinstance( inputs, GraphWrapper): for i in inputs: self.assert_input_compatibility(i) # Collect input shapes to build layer. input_shapes = [] if isinstance(inputs, GraphWrapper): inputs = [inputs] for x_elem in inputs: if hasattr(x_elem, '_keras_shape'): # For a GraphWrapper, _keras_shape is a GraphShape # object input_shapes.append(x_elem._keras_shape) elif hasattr(K, 'int_shape'): input_shapes.append(K.int_shape(x_elem)) else: raise ValueError( 'You tried to call layer "' + self.name + '". This layer has no information' ' about its expected input shape, ' 'and thus cannot be built. ' 'You can build it manually via: ' '`layer.build(batch_input_shape)`') self.build(unpack_singleton(input_shapes)) self._built = True # Load weights that were specified at layer instantiation. if self._initial_weights is not None: self.set_weights(self._initial_weights) # Raise exceptions in case the input is not compatible # with the input_spec set at build time. if isinstance(inputs, list) and not isinstance(inputs, GraphWrapper): for i in inputs: self.assert_input_compatibility(i) # Handle mask propagation. previous_mask = _collect_previous_mask(inputs) user_kwargs = copy.copy(kwargs) if not is_all_none(previous_mask): # The previous layer generated a mask. if has_arg(self.call, 'mask'): if 'mask' not in kwargs: # If mask is explicitly passed to __call__, # we should override the default mask. kwargs['mask'] = previous_mask # Handle automatic shape inference (only useful for Theano). input_shape = _collect_input_shape(inputs) # Actually call the layer, # collecting output(s), mask(s), and shape(s). # Note that inpputs can hold graph wrappers now output = self.call(unpack_singleton(inputs), **kwargs) output_mask = self.compute_mask(inputs, previous_mask) # If the layer returns tensors from its inputs, unmodified, # we copy them to avoid loss of tensor metadata. # output_ls = to_list(output) if isinstance(output, GraphWrapper): output_ls = [output] # Unpack wrappers inputs_ls = list( chain.from_iterable( [i for i in inputs if isinstance(i, GraphWrapper)])) inputs_ls += [ i for i in inputs if not isinstance(i, GraphWrapper) ] # Unpack adjacency and nodes inpadj_ls = list( chain.from_iterable([ to_list(i.adjacency) for i in inputs if isinstance(i, GraphWrapper) ])) inpnod_ls = to_list( [i.nodes for i in inputs if isinstance(i, GraphWrapper)]) output_ls_copy = [] adj_ls = [] for x in output_ls: if K.is_tensor(x) and x in inputs_ls: x = K.identity(x) # Apply adjacency-wise and node-wise identity elif isinstance(x, GraphWrapper): # Store changed or copy of unchanged adjacency matrices adj_ls.clear() for adj in to_list(x.adjacency): if adj in inpadj_ls: adj_ls.append(K.identity(adj)) else: adj_ls.append(adj) # Assign to output graph x.adjacency = unpack_singleton(adj_ls) # Store unchanged nodes if x.nodes in inpnod_ls: x.nodes = K.identity(x.nodes) output_ls_copy.append(x) output = unpack_singleton(output_ls_copy) # Inferring the output shape is only relevant for Theano. if all([s is not None for s in to_list(input_shape)]): output_shape = self.compute_output_shape(input_shape) else: if isinstance(input_shape, list): output_shape = [None for _ in input_shape] else: output_shape = None if (not isinstance(output_mask, (list, tuple)) and len(output_ls) > 1): # Augment the mask to match the length of the output. output_mask = [output_mask] * len(output_ls) # Add an inbound node to the layer, so that it keeps track # of the call and of all new variables created during the call. # This also updates the layer history of the output tensor(s). # If the input tensor(s) had not previous Keras history, # this does nothing. self._add_inbound_node(input_tensors=inputs_ls, output_tensors=unpack_singleton(output), input_masks=previous_mask, output_masks=output_mask, input_shapes=input_shape, output_shapes=output_shape, arguments=user_kwargs) # Apply activity regularizer if any: if (hasattr(self, 'activity_regularizer') and self.activity_regularizer is not None): with K.name_scope('activity_regularizer'): regularization_losses = [ self.activity_regularizer(x) for x in to_list(output) ] self.add_loss(regularization_losses, inputs=to_list(inputs)) return output
def _sup_rnn_call(self, inputs, initial_state=None, constants=None, **kwargs): # reshaped_input = Reshape((inputs._shape[1],inputs._keras_shape[2]*inputs._keras_shape[3]))(inputs) # super(RNNStackedAttention,self).__call__(reshaped_input,**kwargs) if isinstance(inputs, list): inputs = inputs[:] with K.name_scope(self.name): # Handle laying building (weight creating, input spec locking). if not self.built: input_shapes = [] input_shapes.append(self.shape_lstm) # Collect input shapes to build layer. #input_shapes.append(self.shape_lstm) for x_elem in to_list(inputs): if hasattr(x_elem, '_keras_shape'): input_shapes.append(x_elem._keras_shape) elif hasattr(K, 'int_shape'): input_shapes.append(K.int_shape(x_elem)) else: raise ValueError('You tried to call layer "' + self.name + '". This layer has no information' ' about its expected input shape, ' 'and thus cannot be built. ' 'You can build it manually via: ' '`layer.build(batch_input_shape)`') self.build(unpack_singleton(input_shapes)) self.built = True # Load weights that were specified at layer instantiation. if self._initial_weights is not None: self.set_weights(self._initial_weights) # Raise exceptions in case the input is not compatible # with the input_spec set at build time. # self.assert_input_compatibility(inputs) # Handle mask propagation. # previous_mask = _collect_previous_mask(inputs) user_kwargs = kwargs.copy() # if not is_all_none(previous_mask): # # The previous layer generated a mask. # if has_arg(self.call, 'mask'): # if 'mask' not in kwargs: # # If mask is explicitly passed to __call__, # # we should override the default mask. # kwargs['mask'] = previous_mask # # Handle automatic shape inference (only useful for Theano). # input_shape = _collect_input_shape(inputs) # Actually call the layer, # collecting output(s), mask(s), and shape(s). output = self.call(inputs, **kwargs) # output_mask = self.compute_mask(inputs, previous_mask) # If the layer returns tensors from its inputs, unmodified, # we copy them to avoid loss of tensor metadata. output_ls = to_list(output) inputs_ls = to_list(inputs) output_ls_copy = [] for x in output_ls: if id(x) in [id(i) for i in inputs_ls]: x = K.identity(x) output_ls_copy.append(x) output = unpack_singleton(output_ls_copy) input_shape = _collect_input_shape(inputs) input_shape[0] = self.shape_lstm # Inferring the output shape is only relevant for Theano. if all([s is not None for s in to_list(input_shape)]): output_shape = self.compute_output_shape(input_shape) else: if isinstance(input_shape, list): output_shape = [None for _ in input_shape] else: output_shape = None # # if (not isinstance(output_mask, (list, tuple)) and # len(output_ls) > 1): # # Augment the mask to match the length of the output. # output_mask = [output_mask] * len(output_ls) # Add an inbound node to the layer, so that it keeps track # of the call and of all new variables created during the call. # This also updates the layer history of the output tensor(s). # If the input tensor(s) had not previous Keras history, # this does nothing. previous_mask = None output_mask = None self._add_inbound_node(input_tensors=inputs, output_tensors=output, input_masks=previous_mask, output_masks=output_mask, input_shapes=input_shape, output_shapes=output_shape, arguments=user_kwargs) # Apply activity regularizer if any: if (hasattr(self, 'activity_regularizer') and self.activity_regularizer is not None): with K.name_scope('activity_regularizer'): regularization_losses = [ self.activity_regularizer(x) for x in to_list(output) ] self.add_loss(regularization_losses, inputs=to_list(inputs)) return output