1# Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15# pylint: disable=protected-access 16# pylint: disable=redefined-outer-name 17# pylint: disable=redefined-builtin 18"""Keras backend API. 19""" 20from __future__ import absolute_import 21from __future__ import division 22from __future__ import print_function 23 24import collections 25import itertools 26import json 27import os 28import threading 29import weakref 30 31import numpy as np 32 33from tensorflow.core.protobuf import config_pb2 34from tensorflow.python.client import session as session_module 35from tensorflow.python.distribute import distribute_coordinator as dc 36from tensorflow.python.distribute import distribute_coordinator_context as dc_context 37from tensorflow.python.distribute import distribution_strategy_context 38from tensorflow.python.eager import context 39from tensorflow.python.eager import function as eager_function 40from tensorflow.python.eager import lift_to_graph 41from tensorflow.python.framework import constant_op 42from tensorflow.python.framework import dtypes as dtypes_module 43from tensorflow.python.framework import func_graph 44from tensorflow.python.framework import ops 45from tensorflow.python.framework import sparse_tensor 46from tensorflow.python.framework import tensor_util 47from tensorflow.python.keras import backend_config 48from tensorflow.python.ops import array_ops 49from tensorflow.python.ops import clip_ops 50from tensorflow.python.ops import control_flow_ops 51from tensorflow.python.ops import ctc_ops as ctc 52from tensorflow.python.ops import functional_ops 53from tensorflow.python.ops import gradients as gradients_module 54from tensorflow.python.ops import image_ops 55from tensorflow.python.ops import init_ops 56from tensorflow.python.ops import linalg_ops 57from tensorflow.python.ops import logging_ops 58from tensorflow.python.ops import map_fn as map_fn_lib 59from tensorflow.python.ops import math_ops 60from tensorflow.python.ops import nn 61from tensorflow.python.ops import random_ops 62from tensorflow.python.ops import resource_variable_ops 63from tensorflow.python.ops import sparse_ops 64from tensorflow.python.ops import state_ops 65from tensorflow.python.ops import tensor_array_grad # pylint: disable=unused-import 66from tensorflow.python.ops import tensor_array_ops 67from tensorflow.python.ops import variables as variables_module 68from tensorflow.python.training import server_lib 69from tensorflow.python.util import nest 70from tensorflow.python.util import tf_contextlib 71from tensorflow.python.util import tf_inspect 72from tensorflow.python.util.tf_export import keras_export 73 74py_all = all 75py_sum = sum 76 77# INTERNAL UTILS 78 79# The internal graph maintained by Keras and used by the symbolic Keras APIs 80# while executing eagerly (such as the functional API for model-building). 81_GRAPH = None 82 83# A graph which is used for constructing functions in eager mode. 84_CURRENT_SCRATCH_GRAPH = None 85 86# This is a thread local object that will hold the default internal TF session 87# used by Keras. It can be set manually via `set_session(sess)`. 88_SESSION = threading.local() 89 90# This dictionary holds a mapping {graph: learning_phase}. 91# A learning phase is a bool tensor used to run Keras models in 92# either train mode (learning_phase == 1) or test mode (learning_phase == 0). 93_GRAPH_LEARNING_PHASES = weakref.WeakKeyDictionary() 94 95 96# _DUMMY_EAGER_GRAPH is used as a key in _GRAPH_LEARNING_PHASES. 97# We keep a separate reference to it to make sure it does not get removed from 98# _GRAPH_LEARNING_PHASES. 99_DUMMY_EAGER_GRAPH = threading.local() 100 101# This boolean flag can be set to True to leave variable initialization 102# up to the user. 103# Change its value via `manual_variable_initialization(value)`. 104_MANUAL_VAR_INIT = False 105 106# This list holds the available devices. 107# It is populated when `_get_available_gpus()` is called for the first time. 108# We assume our devices don't change henceforth. 109_LOCAL_DEVICES = None 110 111# This dictionary holds a mapping between a graph and variables to initialize 112# in the graph. 113_GRAPH_VARIABLES = weakref.WeakKeyDictionary() 114 115# This dictionary holds a mapping between a graph and TF optimizers created in 116# the graph. 117_GRAPH_TF_OPTIMIZERS = weakref.WeakKeyDictionary() 118 119# The below functions are kept accessible from backend for compatibility. 120epsilon = backend_config.epsilon 121floatx = backend_config.floatx 122image_data_format = backend_config.image_data_format 123set_epsilon = backend_config.set_epsilon 124set_floatx = backend_config.set_floatx 125set_image_data_format = backend_config.set_image_data_format 126 127 128@keras_export('keras.backend.backend') 129def backend(): 130 """Publicly accessible method for determining the current backend. 131 132 Only exists for API compatibility with multi-backend Keras. 133 134 Returns: 135 The string "tensorflow". 136 """ 137 return 'tensorflow' 138 139 140@keras_export('keras.backend.cast_to_floatx') 141def cast_to_floatx(x): 142 """Cast a Numpy array to the default Keras float type. 143 144 Arguments: 145 x: Numpy array. 146 147 Returns: 148 The same Numpy array, cast to its new type. 149 150 Example: 151 ```python 152 >>> from keras import backend as K 153 >>> K.floatx() 154 'float32' 155 >>> arr = numpy.array([1.0, 2.0], dtype='float64') 156 >>> arr.dtype 157 dtype('float64') 158 >>> new_arr = K.cast_to_floatx(arr) 159 >>> new_arr 160 array([ 1., 2.], dtype=float32) 161 >>> new_arr.dtype 162 dtype('float32') 163 ``` 164 """ 165 return np.asarray(x, dtype=floatx()) 166 167 168# A global dictionary mapping graph objects to an index of counters used 169# for various layer names in each graph. 170# Allows to give unique autogenerated names to layers, in a graph-specific way. 171PER_GRAPH_LAYER_NAME_UIDS = weakref.WeakKeyDictionary() 172 173 174@keras_export('keras.backend.get_uid') 175def get_uid(prefix=''): 176 """Associates a string prefix with an integer counter in a TensorFlow graph. 177 178 Arguments: 179 prefix: String prefix to index. 180 181 Returns: 182 Unique integer ID. 183 184 Example: 185 186 ``` 187 >>> get_uid('dense') 188 1 189 >>> get_uid('dense') 190 2 191 ``` 192 """ 193 graph = get_graph() 194 if graph not in PER_GRAPH_LAYER_NAME_UIDS: 195 PER_GRAPH_LAYER_NAME_UIDS[graph] = collections.defaultdict(int) 196 layer_name_uids = PER_GRAPH_LAYER_NAME_UIDS[graph] 197 layer_name_uids[prefix] += 1 198 return layer_name_uids[prefix] 199 200 201@keras_export('keras.backend.reset_uids') 202def reset_uids(): 203 """Resets graph identifiers. 204 """ 205 per_graph_layer_name_uids = PER_GRAPH_LAYER_NAME_UIDS 206 keys = list(per_graph_layer_name_uids.keys()) 207 for key in keys: 208 del per_graph_layer_name_uids[key] 209 210 211@keras_export('keras.backend.clear_session') 212def clear_session(): 213 """Destroys the current TF graph and creates a new one. 214 215 Useful to avoid clutter from old models / layers. 216 """ 217 global _SESSION 218 global _GRAPH_LEARNING_PHASES # pylint: disable=global-variable-not-assigned 219 global _GRAPH_VARIABLES # pylint: disable=global-variable-not-assigned 220 global _GRAPH_TF_OPTIMIZERS # pylint: disable=global-variable-not-assigned 221 ops.reset_default_graph() 222 reset_uids() 223 _SESSION.session = None 224 graph = get_graph() 225 with graph.as_default(): 226 with ops.name_scope(''): 227 phase = array_ops.placeholder_with_default( 228 False, shape=(), name='keras_learning_phase') 229 _GRAPH_LEARNING_PHASES = {} 230 _GRAPH_LEARNING_PHASES[graph] = phase 231 _GRAPH_VARIABLES.pop(graph, None) 232 _GRAPH_TF_OPTIMIZERS.pop(graph, None) 233 234 235@keras_export('keras.backend.manual_variable_initialization') 236def manual_variable_initialization(value): 237 """Sets the manual variable initialization flag. 238 239 This boolean flag determines whether 240 variables should be initialized 241 as they are instantiated (default), or if 242 the user should handle the initialization 243 (e.g. via `tf.initialize_all_variables()`). 244 245 Arguments: 246 value: Python boolean. 247 """ 248 global _MANUAL_VAR_INIT 249 _MANUAL_VAR_INIT = value 250 251 252@keras_export('keras.backend.learning_phase') 253def learning_phase(): 254 """Returns the learning phase flag. 255 256 The learning phase flag is a bool tensor (0 = test, 1 = train) 257 to be passed as input to any Keras function 258 that uses a different behavior at train time and test time. 259 260 Returns: 261 Learning phase (scalar integer tensor or Python integer). 262 """ 263 if ops.get_default_graph() is _GRAPH: 264 # Don't enter an init_scope for the learning phase if eager execution 265 # is enabled but we're inside the Keras workspace graph. 266 return symbolic_learning_phase() 267 with ops.init_scope(): 268 # We always check & set the learning phase inside the init_scope, 269 # otherwise the wrong default_graph will be used to look up the learning 270 # phase inside of functions & defuns. 271 # 272 # This is because functions & defuns (both in graph & in eager mode) 273 # will always execute non-eagerly using a function-specific default 274 # subgraph. 275 if context.executing_eagerly(): 276 if _DUMMY_EAGER_GRAPH not in _GRAPH_LEARNING_PHASES: 277 # Fallback to inference mode as default. 278 return 0 279 return _GRAPH_LEARNING_PHASES[_DUMMY_EAGER_GRAPH] 280 return symbolic_learning_phase() 281 282 283def symbolic_learning_phase(): 284 graph = get_graph() 285 with graph.as_default(): 286 if graph not in _GRAPH_LEARNING_PHASES: 287 with ops.name_scope(''): 288 phase = array_ops.placeholder_with_default( 289 False, shape=(), name='keras_learning_phase') 290 _GRAPH_LEARNING_PHASES[graph] = phase 291 return _GRAPH_LEARNING_PHASES[graph] 292 293 294@keras_export('keras.backend.set_learning_phase') 295def set_learning_phase(value): 296 """Sets the learning phase to a fixed value. 297 298 Arguments: 299 value: Learning phase value, either 0 or 1 (integers). 300 301 Raises: 302 ValueError: if `value` is neither `0` nor `1`. 303 """ 304 global _GRAPH_LEARNING_PHASES # pylint: disable=global-variable-not-assigned 305 if value not in {0, 1}: 306 raise ValueError('Expected learning phase to be 0 or 1.') 307 with ops.init_scope(): 308 if context.executing_eagerly(): 309 # In an eager context, the learning phase values applies to both the eager 310 # context and the internal Keras graph. 311 _GRAPH_LEARNING_PHASES[_DUMMY_EAGER_GRAPH] = value 312 _GRAPH_LEARNING_PHASES[get_graph()] = value 313 314 315def set_eager_learning_phase(value): 316 """Internal utility that sets the learning phase in eager execution only. 317 318 Arguments: 319 value: Learning phase value, either 0 or 1 (integers). 320 """ 321 global _GRAPH_LEARNING_PHASES # pylint: disable=global-variable-not-assigned 322 assert value in {0, 1} 323 assert context.executing_eagerly() 324 _GRAPH_LEARNING_PHASES[_DUMMY_EAGER_GRAPH] = value 325 326 327@keras_export('keras.backend.learning_phase_scope') 328@tf_contextlib.contextmanager 329def learning_phase_scope(value): 330 """Provides a scope within which the learning phase is equal to `value`. 331 332 The learning phase gets restored to its original value upon exiting the scope. 333 334 Arguments: 335 value: Learning phase value, either 0 or 1 (integers). 336 337 Yields: 338 None. 339 340 Raises: 341 ValueError: if `value` is neither `0` nor `1`. 342 """ 343 global _GRAPH_LEARNING_PHASES # pylint: disable=global-variable-not-assigned 344 if value not in {0, 1}: 345 raise ValueError('Expected learning phase to be 0 or 1.') 346 347 with ops.init_scope(): 348 if context.executing_eagerly(): 349 previous_eager_value = _GRAPH_LEARNING_PHASES.get( 350 _DUMMY_EAGER_GRAPH, None) 351 previous_graph_value = _GRAPH_LEARNING_PHASES.get(get_graph(), None) 352 353 try: 354 set_learning_phase(value) 355 yield 356 finally: 357 # Restore learning phase to initial value. 358 with ops.init_scope(): 359 if context.executing_eagerly(): 360 if previous_eager_value is not None: 361 _GRAPH_LEARNING_PHASES[_DUMMY_EAGER_GRAPH] = previous_eager_value 362 elif _DUMMY_EAGER_GRAPH in _GRAPH_LEARNING_PHASES: 363 del _GRAPH_LEARNING_PHASES[_DUMMY_EAGER_GRAPH] 364 365 graph = get_graph() 366 if previous_graph_value is not None: 367 _GRAPH_LEARNING_PHASES[graph] = previous_graph_value 368 elif graph in _GRAPH_LEARNING_PHASES: 369 del _GRAPH_LEARNING_PHASES[graph] 370 371@tf_contextlib.contextmanager 372def eager_learning_phase_scope(value): 373 """Internal scope that sets the learning phase in eager execution only. 374 375 Arguments: 376 value: Learning phase value, either 0 or 1 (integers). 377 378 Yields: 379 None. 380 381 Raises: 382 ValueError: if `value` is neither `0` nor `1`. 383 """ 384 global _GRAPH_LEARNING_PHASES # pylint: disable=global-variable-not-assigned 385 assert value in {0, 1} 386 assert context.executing_eagerly() 387 previous_value = learning_phase() 388 try: 389 _GRAPH_LEARNING_PHASES[_DUMMY_EAGER_GRAPH] = value 390 yield 391 finally: 392 # Restore learning phase to initial value. 393 _GRAPH_LEARNING_PHASES[_DUMMY_EAGER_GRAPH] = previous_value 394 395 396def _current_graph(op_input_list): 397 """Return the graph members of `op_input_list`, or the current graph.""" 398 return ops._get_graph_from_inputs(op_input_list) 399 400 401def _get_session(op_input_list=()): 402 """Returns the session object for the current thread.""" 403 global _SESSION 404 default_session = ops.get_default_session() 405 if default_session is not None: 406 session = default_session 407 else: 408 if ops.inside_function(): 409 raise RuntimeError('Cannot get session inside Tensorflow graph function.') 410 # If we don't have a session, or that session does not match the current 411 # graph, create and cache a new session. 412 if (getattr(_SESSION, 'session', None) is None or 413 _SESSION.session.graph is not _current_graph(op_input_list)): 414 # If we are creating the Session inside a tf.distribute.Strategy scope, 415 # we ask the strategy for the right session options to use. 416 if distribution_strategy_context.has_strategy(): 417 configure_and_create_distributed_session( 418 distribution_strategy_context.get_strategy()) 419 else: 420 _SESSION.session = session_module.Session( 421 config=get_default_session_config()) 422 session = _SESSION.session 423 return session 424 425 426@keras_export(v1=['keras.backend.get_session']) 427def get_session(op_input_list=()): 428 """Returns the TF session to be used by the backend. 429 430 If a default TensorFlow session is available, we will return it. 431 432 Else, we will return the global Keras session assuming it matches 433 the current graph. 434 435 If no global Keras session exists at this point: 436 we will create a new global session. 437 438 Note that you can manually set the global session 439 via `K.set_session(sess)`. 440 441 Arguments: 442 op_input_list: An option sequence of tensors or ops, which will be used 443 to determine the current graph. Otherwise the default graph will be 444 used. 445 446 Returns: 447 A TensorFlow session. 448 """ 449 session = _get_session(op_input_list) 450 if not _MANUAL_VAR_INIT: 451 with session.graph.as_default(): 452 _initialize_variables(session) 453 return session 454 455 456def get_graph(): 457 if context.executing_eagerly(): 458 global _GRAPH 459 if _GRAPH is None: 460 _GRAPH = func_graph.FuncGraph('keras_graph') 461 return _GRAPH 462 else: 463 return ops.get_default_graph() 464 465 466@tf_contextlib.contextmanager 467def _scratch_graph(graph=None): 468 """Retrieve a shared and temporary func graph. 469 470 The eager execution path lifts a subgraph from the keras global graph into 471 a scratch graph in order to create a function. DistributionStrategies, in 472 turn, constructs multiple functions as well as a final combined function. In 473 order for that logic to work correctly, all of the functions need to be 474 created on the same scratch FuncGraph. 475 476 Args: 477 graph: A graph to be used as the current scratch graph. If not set then 478 a scratch graph will either be retrieved or created: 479 480 Yields: 481 The current scratch graph. 482 """ 483 global _CURRENT_SCRATCH_GRAPH 484 if (_CURRENT_SCRATCH_GRAPH is not None and graph is not None and 485 _CURRENT_SCRATCH_GRAPH is not graph): 486 raise ValueError('Multiple scratch graphs specified.') 487 488 if _CURRENT_SCRATCH_GRAPH: 489 yield _CURRENT_SCRATCH_GRAPH 490 return 491 492 graph = graph or func_graph.FuncGraph('keras_scratch_graph') 493 try: 494 _CURRENT_SCRATCH_GRAPH = graph 495 yield graph 496 finally: 497 _CURRENT_SCRATCH_GRAPH = None 498 499 500@keras_export('keras.backend.set_session') 501def set_session(session): 502 """Sets the global TensorFlow session. 503 504 Arguments: 505 session: A TF Session. 506 """ 507 global _SESSION 508 _SESSION.session = session 509 510 511def get_default_session_config(): 512 if not os.environ.get('OMP_NUM_THREADS'): 513 config = config_pb2.ConfigProto(allow_soft_placement=True) 514 else: 515 num_thread = int(os.environ.get('OMP_NUM_THREADS')) 516 config = config_pb2.ConfigProto( 517 intra_op_parallelism_threads=num_thread, 518 inter_op_parallelism_threads=num_thread, 519 allow_soft_placement=True) 520 return config 521 522 523# DEVICE MANIPULATION 524 525 526class _TfDeviceCaptureOp(object): 527 """Class for capturing the TF device scope.""" 528 529 def __init__(self): 530 self.device = None 531 532 def _set_device(self, device): 533 """This method captures TF's explicit device scope setting.""" 534 self.device = device 535 536 537def _get_current_tf_device(): 538 """Return explicit device of current context, otherwise returns `None`. 539 540 Returns: 541 If the current device scope is explicitly set, it returns a string with 542 the device (`CPU` or `GPU`). If the scope is not explicitly set, it will 543 return `None`. 544 """ 545 graph = get_graph() 546 op = _TfDeviceCaptureOp() 547 graph._apply_device_functions(op) 548 return op.device 549 550 551def _is_current_explicit_device(device_type): 552 """Check if the current device is explicitly set on the device type specified. 553 554 Arguments: 555 device_type: A string containing `GPU` or `CPU` (case-insensitive). 556 557 Returns: 558 A boolean indicating if the current device scope is explicitly set on the 559 device type. 560 561 Raises: 562 ValueError: If the `device_type` string indicates an unsupported device. 563 """ 564 device_type = device_type.upper() 565 if device_type not in ['CPU', 'GPU']: 566 raise ValueError('`device_type` should be either "CPU" or "GPU".') 567 device = _get_current_tf_device() 568 return device is not None and device.device_type == device_type.upper() 569 570 571def _get_available_gpus(): 572 """Get a list of available gpu devices (formatted as strings). 573 574 Returns: 575 A list of available GPU devices. 576 """ 577 if ops.executing_eagerly_outside_functions(): 578 # Returns names of devices directly. 579 return [name for name in context.list_devices() if 'GPU' in name] 580 581 global _LOCAL_DEVICES 582 if _LOCAL_DEVICES is None: 583 _LOCAL_DEVICES = get_session().list_devices() 584 return [x.name for x in _LOCAL_DEVICES if x.device_type == 'GPU'] 585 586 587def _has_nchw_support(): 588 """Check whether the current scope supports NCHW ops. 589 590 TensorFlow does not support NCHW on CPU. Therefore we check if we are not 591 explicitly put on 592 CPU, and have GPUs available. In this case there will be soft-placing on the 593 GPU device. 594 595 Returns: 596 bool: if the current scope device placement would support nchw 597 """ 598 explicitly_on_cpu = _is_current_explicit_device('CPU') 599 gpus_available = bool(_get_available_gpus()) 600 return not explicitly_on_cpu and gpus_available 601 602 603# VARIABLE MANIPULATION 604 605 606def _to_tensor(x, dtype): 607 """Convert the input `x` to a tensor of type `dtype`. 608 609 Arguments: 610 x: An object to be converted (numpy array, list, tensors). 611 dtype: The destination type. 612 613 Returns: 614 A tensor. 615 """ 616 return ops.convert_to_tensor(x, dtype=dtype) 617 618 619@keras_export('keras.backend.is_sparse') 620def is_sparse(tensor): 621 """Returns whether a tensor is a sparse tensor. 622 623 Arguments: 624 tensor: A tensor instance. 625 626 Returns: 627 A boolean. 628 629 Example: 630 ```python 631 >>> from keras import backend as K 632 >>> a = K.placeholder((2, 2), sparse=False) 633 >>> print(K.is_sparse(a)) 634 False 635 >>> b = K.placeholder((2, 2), sparse=True) 636 >>> print(K.is_sparse(b)) 637 True 638 ``` 639 """ 640 return isinstance(tensor, sparse_tensor.SparseTensor) 641 642 643@keras_export('keras.backend.to_dense') 644def to_dense(tensor): 645 """Converts a sparse tensor into a dense tensor and returns it. 646 647 Arguments: 648 tensor: A tensor instance (potentially sparse). 649 650 Returns: 651 A dense tensor. 652 653 Examples: 654 ```python 655 >>> from keras import backend as K 656 >>> b = K.placeholder((2, 2), sparse=True) 657 >>> print(K.is_sparse(b)) 658 True 659 >>> c = K.to_dense(b) 660 >>> print(K.is_sparse(c)) 661 False 662 ``` 663 """ 664 if is_sparse(tensor): 665 return sparse_ops.sparse_tensor_to_dense(tensor) 666 else: 667 return tensor 668 669 670name_scope = ops.name_scope 671 672 673@keras_export('keras.backend.variable') 674def variable(value, dtype=None, name=None, constraint=None): 675 """Instantiates a variable and returns it. 676 677 Arguments: 678 value: Numpy array, initial value of the tensor. 679 dtype: Tensor type. 680 name: Optional name string for the tensor. 681 constraint: Optional projection function to be 682 applied to the variable after an optimizer update. 683 684 Returns: 685 A variable instance (with Keras metadata included). 686 687 Examples: 688 ```python 689 >>> import numpy as np 690 >>> from keras import backend as K 691 >>> val = np.array([[1, 2], [3, 4]]) 692 >>> kvar = K.variable(value=val, dtype='float64', name='example_var') 693 >>> K.dtype(kvar) 694 'float64' 695 >>> print(kvar) 696 example_var 697 >>> kvar.eval() 698 array([[ 1., 2.], 699 [ 3., 4.]]) 700 ``` 701 """ 702 if dtype is None: 703 dtype = floatx() 704 if hasattr(value, 'tocoo'): 705 sparse_coo = value.tocoo() 706 indices = np.concatenate((np.expand_dims(sparse_coo.row, 1), np.expand_dims( 707 sparse_coo.col, 1)), 1) 708 v = sparse_tensor.SparseTensor( 709 indices=indices, values=sparse_coo.data, dense_shape=sparse_coo.shape) 710 v._keras_shape = sparse_coo.shape 711 return v 712 v = resource_variable_ops.ResourceVariable( 713 value, 714 dtype=dtypes_module.as_dtype(dtype), 715 name=name, 716 constraint=constraint) 717 if isinstance(value, np.ndarray): 718 v._keras_shape = value.shape 719 elif hasattr(value, 'shape'): 720 v._keras_shape = int_shape(value) 721 track_variable(v) 722 return v 723 724 725def track_tf_optimizer(tf_optimizer): 726 """Tracks the given TF optimizer for initialization of its variables.""" 727 if context.executing_eagerly(): 728 return 729 graph = get_graph() 730 optimizers = _GRAPH_TF_OPTIMIZERS.setdefault(graph, weakref.WeakSet()) 731 optimizers.add(tf_optimizer) 732 733 734def track_variable(v): 735 """Tracks the given variable for initialization.""" 736 if context.executing_eagerly(): 737 return 738 graph = v.graph if hasattr(v, 'graph') else get_graph() 739 if graph not in _GRAPH_VARIABLES: 740 _GRAPH_VARIABLES[graph] = weakref.WeakSet() 741 _GRAPH_VARIABLES[graph].add(v) 742 743 744def _get_variables(graph=None): 745 """Returns variables corresponding to the given graph for initialization.""" 746 assert not context.executing_eagerly() 747 variables = _GRAPH_VARIABLES.setdefault(graph, weakref.WeakSet()) 748 for opt in _GRAPH_TF_OPTIMIZERS.get(graph, set()): 749 variables.update(opt.optimizer.variables()) 750 return variables 751 752 753def _initialize_variables(session): 754 """Utility to initialize uninitialized variables on the fly.""" 755 variables = _get_variables(get_graph()) 756 candidate_vars = [] 757 for v in variables: 758 if not getattr(v, '_keras_initialized', False): 759 candidate_vars.append(v) 760 if candidate_vars: 761 # This step is expensive, so we only run it on variables not already 762 # marked as initialized. 763 is_initialized = session.run( 764 [variables_module.is_variable_initialized(v) for v in candidate_vars]) 765 uninitialized_vars = [] 766 for flag, v in zip(is_initialized, candidate_vars): 767 if not flag: 768 uninitialized_vars.append(v) 769 v._keras_initialized = True 770 if uninitialized_vars: 771 session.run(variables_module.variables_initializer(uninitialized_vars)) 772 773 774@keras_export('keras.backend.constant') 775def constant(value, dtype=None, shape=None, name=None): 776 """Creates a constant tensor. 777 778 Arguments: 779 value: A constant value (or list) 780 dtype: The type of the elements of the resulting tensor. 781 shape: Optional dimensions of resulting tensor. 782 name: Optional name for the tensor. 783 784 Returns: 785 A Constant Tensor. 786 """ 787 if dtype is None: 788 dtype = floatx() 789 790 # If the outer context is eager but we are executing under the keras 791 # FuncGraph, we create EagerTensors and use them as constants. 792 if (ops.executing_eagerly_outside_functions() and 793 getattr(get_graph(), 'name', '') == 'keras_graph'): 794 with ops.init_scope(): 795 return constant_op.constant(value, dtype=dtype, shape=shape, name=name) 796 797 return constant_op.constant(value, dtype=dtype, shape=shape, name=name) 798 799 800def is_keras_tensor(x): 801 """Returns whether `x` is a Keras tensor. 802 803 A "Keras tensor" is a tensor that was returned by a Keras layer, 804 (`Layer` class) or by `Input`. 805 806 Arguments: 807 x: A candidate tensor. 808 809 Returns: 810 A boolean: Whether the argument is a Keras tensor. 811 812 Raises: 813 ValueError: In case `x` is not a symbolic tensor. 814 815 Examples: 816 ```python 817 >>> import tensorflow as tf 818 >>> import numpy 819 >>> from keras import backend as K 820 >>> from keras.layers import Input, Dense 821 >>> np_var = numpy.array([1, 2]) 822 >>> K.is_keras_tensor(np_var) # A numpy array is not a symbolic tensor. 823 ValueError 824 >>> k_var = tf.placeholder('float32', shape=(1,1)) 825 >>> K.is_keras_tensor(k_var) # A variable indirectly created outside of 826 keras is not a Keras tensor. 827 False 828 >>> keras_var = K.variable(np_var) 829 >>> K.is_keras_tensor(keras_var) # A variable created with the keras 830 backend is not a Keras tensor. 831 False 832 >>> keras_placeholder = K.placeholder(shape=(2, 4, 5)) 833 >>> K.is_keras_tensor(keras_placeholder) # A placeholder is not a Keras 834 tensor. 835 False 836 >>> keras_input = Input([10]) 837 >>> K.is_keras_tensor(keras_input) # An Input is a Keras tensor. 838 True 839 >>> keras_layer_output = Dense(10)(keras_input) 840 >>> K.is_keras_tensor(keras_layer_output) # Any Keras layer output is a 841 Keras tensor. 842 True 843 ``` 844 """ 845 if not isinstance(x, (ops.Tensor, 846 variables_module.Variable, 847 sparse_tensor.SparseTensor)): 848 raise ValueError('Unexpectedly found an instance of type `' + str(type(x)) + 849 '`. Expected a symbolic tensor instance.') 850 return hasattr(x, '_keras_history') 851 852 853@keras_export('keras.backend.placeholder') 854def placeholder(shape=None, ndim=None, dtype=None, sparse=False, name=None): 855 """Instantiates a placeholder tensor and returns it. 856 857 Arguments: 858 shape: Shape of the placeholder 859 (integer tuple, may include `None` entries). 860 ndim: Number of axes of the tensor. 861 At least one of {`shape`, `ndim`} must be specified. 862 If both are specified, `shape` is used. 863 dtype: Placeholder type. 864 sparse: Boolean, whether the placeholder should have a sparse type. 865 name: Optional name string for the placeholder. 866 867 Raises: 868 ValueError: If called with eager execution. 869 870 Returns: 871 Tensor instance (with Keras metadata included). 872 873 Examples: 874 ```python 875 >>> from keras import backend as K 876 >>> input_ph = K.placeholder(shape=(2, 4, 5)) 877 >>> input_ph 878 <tf.Tensor 'Placeholder_4:0' shape=(2, 4, 5) dtype=float32> 879 ``` 880 """ 881 if dtype is None: 882 dtype = floatx() 883 if not shape: 884 if ndim: 885 shape = tuple([None for _ in range(ndim)]) 886 with get_graph().as_default(): 887 if sparse: 888 x = array_ops.sparse_placeholder(dtype, shape=shape, name=name) 889 else: 890 x = array_ops.placeholder(dtype, shape=shape, name=name) 891 return x 892 893 894def is_placeholder(x): 895 """Returns whether `x` is a placeholder. 896 897 Arguments: 898 x: A candidate placeholder. 899 900 Returns: 901 Boolean. 902 """ 903 try: 904 return x.op.type == 'Placeholder' 905 except AttributeError: 906 return False 907 908 909@keras_export('keras.backend.shape') 910def shape(x): 911 """Returns the symbolic shape of a tensor or variable. 912 913 Arguments: 914 x: A tensor or variable. 915 916 Returns: 917 A symbolic shape (which is itself a tensor). 918 919 Examples: 920 921 ```python 922 # TensorFlow example 923 >>> from keras import backend as K 924 >>> tf_session = K.get_session() 925 >>> val = np.array([[1, 2], [3, 4]]) 926 >>> kvar = K.variable(value=val) 927 >>> input = keras.backend.placeholder(shape=(2, 4, 5)) 928 >>> K.shape(kvar) 929 <tf.Tensor 'Shape_8:0' shape=(2,) dtype=int32> 930 >>> K.shape(input) 931 <tf.Tensor 'Shape_9:0' shape=(3,) dtype=int32> 932 # To get integer shape (Instead, you can use K.int_shape(x)) 933 >>> K.shape(kvar).eval(session=tf_session) 934 array([2, 2], dtype=int32) 935 >>> K.shape(input).eval(session=tf_session) 936 array([2, 4, 5], dtype=int32) 937 ``` 938 """ 939 return array_ops.shape(x) 940 941 942@keras_export('keras.backend.int_shape') 943def int_shape(x): 944 """Returns the shape of tensor or variable as a tuple of int or None entries. 945 946 Arguments: 947 x: Tensor or variable. 948 949 Returns: 950 A tuple of integers (or None entries). 951 952 Examples: 953 ```python 954 >>> from keras import backend as K 955 >>> input = K.placeholder(shape=(2, 4, 5)) 956 >>> K.int_shape(input) 957 (2, 4, 5) 958 >>> val = np.array([[1, 2], [3, 4]]) 959 >>> kvar = K.variable(value=val) 960 >>> K.int_shape(kvar) 961 (2, 2) 962 ``` 963 """ 964 try: 965 shape = x.shape 966 if not isinstance(shape, tuple): 967 shape = tuple(shape.as_list()) 968 return shape 969 except ValueError: 970 return None 971 972 973@keras_export('keras.backend.ndim') 974def ndim(x): 975 """Returns the number of axes in a tensor, as an integer. 976 977 Arguments: 978 x: Tensor or variable. 979 980 Returns: 981 Integer (scalar), number of axes. 982 983 Examples: 984 ```python 985 >>> from keras import backend as K 986 >>> input = K.placeholder(shape=(2, 4, 5)) 987 >>> val = np.array([[1, 2], [3, 4]]) 988 >>> kvar = K.variable(value=val) 989 >>> K.ndim(input) 990 3 991 >>> K.ndim(kvar) 992 2 993 ``` 994 """ 995 dims = x.shape._dims 996 if dims is not None: 997 return len(dims) 998 return None 999 1000 1001@keras_export('keras.backend.dtype') 1002def dtype(x): 1003 """Returns the dtype of a Keras tensor or variable, as a string. 1004 1005 Arguments: 1006 x: Tensor or variable. 1007 1008 Returns: 1009 String, dtype of `x`. 1010 1011 Examples: 1012 ```python 1013 >>> from keras import backend as K 1014 >>> K.dtype(K.placeholder(shape=(2,4,5))) 1015 'float32' 1016 >>> K.dtype(K.placeholder(shape=(2,4,5), dtype='float32')) 1017 'float32' 1018 >>> K.dtype(K.placeholder(shape=(2,4,5), dtype='float64')) 1019 'float64' 1020 # Keras variable 1021 >>> kvar = K.variable(np.array([[1, 2], [3, 4]])) 1022 >>> K.dtype(kvar) 1023 'float32' 1024 >>> kvar = K.variable(np.array([[1, 2], [3, 4]]), dtype='float32') 1025 >>> K.dtype(kvar) 1026 'float32' 1027 ``` 1028 """ 1029 return x.dtype.base_dtype.name 1030 1031 1032@keras_export('keras.backend.eval') 1033def eval(x): 1034 """Evaluates the value of a variable. 1035 1036 Arguments: 1037 x: A variable. 1038 1039 Returns: 1040 A Numpy array. 1041 1042 Examples: 1043 ```python 1044 >>> from keras import backend as K 1045 >>> kvar = K.variable(np.array([[1, 2], [3, 4]]), dtype='float32') 1046 >>> K.eval(kvar) 1047 array([[ 1., 2.], 1048 [ 3., 4.]], dtype=float32) 1049 ``` 1050 """ 1051 return get_value(to_dense(x)) 1052 1053 1054@keras_export('keras.backend.zeros') 1055def zeros(shape, dtype=None, name=None): 1056 """Instantiates an all-zeros variable and returns it. 1057 1058 Arguments: 1059 shape: Tuple of integers, shape of returned Keras variable 1060 dtype: String, data type of returned Keras variable 1061 name: String, name of returned Keras variable 1062 1063 Returns: 1064 A variable (including Keras metadata), filled with `0.0`. 1065 Note that if `shape` was symbolic, we cannot return a variable, 1066 and will return a dynamically-shaped tensor instead. 1067 1068 Example: 1069 ```python 1070 >>> from keras import backend as K 1071 >>> kvar = K.zeros((3,4)) 1072 >>> K.eval(kvar) 1073 array([[ 0., 0., 0., 0.], 1074 [ 0., 0., 0., 0.], 1075 [ 0., 0., 0., 0.]], dtype=float32) 1076 ``` 1077 """ 1078 with ops.init_scope(): 1079 if dtype is None: 1080 dtype = floatx() 1081 tf_dtype = dtypes_module.as_dtype(dtype) 1082 v = array_ops.zeros(shape=shape, dtype=tf_dtype, name=name) 1083 if py_all(v.shape.as_list()): 1084 return variable(v, dtype=dtype, name=name) 1085 track_variable(v) 1086 return v 1087 1088 1089@keras_export('keras.backend.ones') 1090def ones(shape, dtype=None, name=None): 1091 """Instantiates an all-ones variable and returns it. 1092 1093 Arguments: 1094 shape: Tuple of integers, shape of returned Keras variable. 1095 dtype: String, data type of returned Keras variable. 1096 name: String, name of returned Keras variable. 1097 1098 Returns: 1099 A Keras variable, filled with `1.0`. 1100 Note that if `shape` was symbolic, we cannot return a variable, 1101 and will return a dynamically-shaped tensor instead. 1102 1103 Example: 1104 ```python 1105 >>> from keras import backend as K 1106 >>> kvar = K.ones((3,4)) 1107 >>> K.eval(kvar) 1108 array([[ 1., 1., 1., 1.], 1109 [ 1., 1., 1., 1.], 1110 [ 1., 1., 1., 1.]], dtype=float32) 1111 ``` 1112 """ 1113 with ops.init_scope(): 1114 if dtype is None: 1115 dtype = floatx() 1116 tf_dtype = dtypes_module.as_dtype(dtype) 1117 v = array_ops.ones(shape=shape, dtype=tf_dtype, name=name) 1118 if py_all(v.shape.as_list()): 1119 return variable(v, dtype=dtype, name=name) 1120 track_variable(v) 1121 return v 1122 1123 1124@keras_export('keras.backend.eye') 1125def eye(size, dtype=None, name=None): 1126 """Instantiate an identity matrix and returns it. 1127 1128 Arguments: 1129 size: Integer, number of rows/columns. 1130 dtype: String, data type of returned Keras variable. 1131 name: String, name of returned Keras variable. 1132 1133 Returns: 1134 A Keras variable, an identity matrix. 1135 1136 Example: 1137 ```python 1138 >>> from keras import backend as K 1139 >>> kvar = K.eye(3) 1140 >>> K.eval(kvar) 1141 array([[ 1., 0., 0.], 1142 [ 0., 1., 0.], 1143 [ 0., 0., 1.]], dtype=float32) 1144 ``` 1145 1146 """ 1147 if dtype is None: 1148 dtype = floatx() 1149 tf_dtype = dtypes_module.as_dtype(dtype) 1150 return variable(linalg_ops.eye(size, dtype=tf_dtype), dtype, name) 1151 1152 1153@keras_export('keras.backend.zeros_like') 1154def zeros_like(x, dtype=None, name=None): 1155 """Instantiates an all-zeros variable of the same shape as another tensor. 1156 1157 Arguments: 1158 x: Keras variable or Keras tensor. 1159 dtype: String, dtype of returned Keras variable. 1160 None uses the dtype of x. 1161 name: String, name for the variable to create. 1162 1163 Returns: 1164 A Keras variable with the shape of x filled with zeros. 1165 1166 Example: 1167 ```python 1168 >>> from keras import backend as K 1169 >>> kvar = K.variable(np.random.random((2,3))) 1170 >>> kvar_zeros = K.zeros_like(kvar) 1171 >>> K.eval(kvar_zeros) 1172 array([[ 0., 0., 0.], 1173 [ 0., 0., 0.]], dtype=float32) 1174 ``` 1175 """ 1176 return array_ops.zeros_like(x, dtype=dtype, name=name) 1177 1178 1179@keras_export('keras.backend.ones_like') 1180def ones_like(x, dtype=None, name=None): 1181 """Instantiates an all-ones variable of the same shape as another tensor. 1182 1183 Arguments: 1184 x: Keras variable or tensor. 1185 dtype: String, dtype of returned Keras variable. 1186 None uses the dtype of x. 1187 name: String, name for the variable to create. 1188 1189 Returns: 1190 A Keras variable with the shape of x filled with ones. 1191 1192 Example: 1193 ```python 1194 >>> from keras import backend as K 1195 >>> kvar = K.variable(np.random.random((2,3))) 1196 >>> kvar_ones = K.ones_like(kvar) 1197 >>> K.eval(kvar_ones) 1198 array([[ 1., 1., 1.], 1199 [ 1., 1., 1.]], dtype=float32) 1200 ``` 1201 """ 1202 return array_ops.ones_like(x, dtype=dtype, name=name) 1203 1204 1205def identity(x, name=None): 1206 """Returns a tensor with the same content as the input tensor. 1207 1208 Arguments: 1209 x: The input tensor. 1210 name: String, name for the variable to create. 1211 1212 Returns: 1213 A tensor of the same shape, type and content. 1214 """ 1215 return array_ops.identity(x, name=name) 1216 1217 1218@keras_export('keras.backend.random_uniform_variable') 1219def random_uniform_variable(shape, low, high, dtype=None, name=None, seed=None): 1220 """Instantiates a variable with values drawn from a uniform distribution. 1221 1222 Arguments: 1223 shape: Tuple of integers, shape of returned Keras variable. 1224 low: Float, lower boundary of the output interval. 1225 high: Float, upper boundary of the output interval. 1226 dtype: String, dtype of returned Keras variable. 1227 name: String, name of returned Keras variable. 1228 seed: Integer, random seed. 1229 1230 Returns: 1231 A Keras variable, filled with drawn samples. 1232 1233 Example: 1234 ```python 1235 # TensorFlow example 1236 >>> kvar = K.random_uniform_variable((2,3), 0, 1) 1237 >>> kvar 1238 <tensorflow.python.ops.variables.Variable object at 0x10ab40b10> 1239 >>> K.eval(kvar) 1240 array([[ 0.10940075, 0.10047495, 0.476143 ], 1241 [ 0.66137183, 0.00869417, 0.89220798]], dtype=float32) 1242 ``` 1243 """ 1244 if dtype is None: 1245 dtype = floatx() 1246 tf_dtype = dtypes_module.as_dtype(dtype) 1247 if seed is None: 1248 # ensure that randomness is conditioned by the Numpy RNG 1249 seed = np.random.randint(10e8) 1250 value = init_ops.random_uniform_initializer( 1251 low, high, dtype=tf_dtype, seed=seed)(shape) 1252 return variable(value, dtype=dtype, name=name) 1253 1254 1255@keras_export('keras.backend.random_normal_variable') 1256def random_normal_variable(shape, mean, scale, dtype=None, name=None, 1257 seed=None): 1258 """Instantiates a variable with values drawn from a normal distribution. 1259 1260 Arguments: 1261 shape: Tuple of integers, shape of returned Keras variable. 1262 mean: Float, mean of the normal distribution. 1263 scale: Float, standard deviation of the normal distribution. 1264 dtype: String, dtype of returned Keras variable. 1265 name: String, name of returned Keras variable. 1266 seed: Integer, random seed. 1267 1268 Returns: 1269 A Keras variable, filled with drawn samples. 1270 1271 Example: 1272 ```python 1273 # TensorFlow example 1274 >>> kvar = K.random_normal_variable((2,3), 0, 1) 1275 >>> kvar 1276 <tensorflow.python.ops.variables.Variable object at 0x10ab12dd0> 1277 >>> K.eval(kvar) 1278 array([[ 1.19591331, 0.68685907, -0.63814116], 1279 [ 0.92629528, 0.28055015, 1.70484698]], dtype=float32) 1280 ``` 1281 """ 1282 if dtype is None: 1283 dtype = floatx() 1284 tf_dtype = dtypes_module.as_dtype(dtype) 1285 if seed is None: 1286 # ensure that randomness is conditioned by the Numpy RNG 1287 seed = np.random.randint(10e8) 1288 value = init_ops.random_normal_initializer( 1289 mean, scale, dtype=tf_dtype, seed=seed)(shape) 1290 return variable(value, dtype=dtype, name=name) 1291 1292 1293@keras_export('keras.backend.count_params') 1294def count_params(x): 1295 """Returns the static number of elements in a variable or tensor. 1296 1297 Arguments: 1298 x: Variable or tensor. 1299 1300 Returns: 1301 Integer, the number of scalars in `x`. 1302 1303 Example: 1304 ```python 1305 >>> kvar = K.zeros((2,3)) 1306 >>> K.count_params(kvar) 1307 6 1308 >>> K.eval(kvar) 1309 array([[ 0., 0., 0.], 1310 [ 0., 0., 0.]], dtype=float32) 1311 ``` 1312 """ 1313 return np.prod(x.shape.as_list()) 1314 1315 1316@keras_export('keras.backend.cast') 1317def cast(x, dtype): 1318 """Casts a tensor to a different dtype and returns it. 1319 1320 You can cast a Keras variable but it still returns a Keras tensor. 1321 1322 Arguments: 1323 x: Keras tensor (or variable). 1324 dtype: String, either (`'float16'`, `'float32'`, or `'float64'`). 1325 1326 Returns: 1327 Keras tensor with dtype `dtype`. 1328 1329 Example: 1330 ```python 1331 >>> from keras import backend as K 1332 >>> input = K.placeholder((2, 3), dtype='float32') 1333 >>> input 1334 <tf.Tensor 'Placeholder_2:0' shape=(2, 3) dtype=float32> 1335 # It doesn't work in-place as below. 1336 >>> K.cast(input, dtype='float16') 1337 <tf.Tensor 'Cast_1:0' shape=(2, 3) dtype=float16> 1338 >>> input 1339 <tf.Tensor 'Placeholder_2:0' shape=(2, 3) dtype=float32> 1340 # you need to assign it. 1341 >>> input = K.cast(input, dtype='float16') 1342 >>> input 1343 <tf.Tensor 'Cast_2:0' shape=(2, 3) dtype=float16> 1344 ``` 1345 """ 1346 return math_ops.cast(x, dtype) 1347 1348 1349# UPDATES OPS 1350 1351 1352@keras_export('keras.backend.update') 1353def update(x, new_x): 1354 return state_ops.assign(x, new_x) 1355 1356 1357@keras_export('keras.backend.update_add') 1358def update_add(x, increment): 1359 """Update the value of `x` by adding `increment`. 1360 1361 Arguments: 1362 x: A Variable. 1363 increment: A tensor of same shape as `x`. 1364 1365 Returns: 1366 The variable `x` updated. 1367 """ 1368 return state_ops.assign_add(x, increment) 1369 1370 1371@keras_export('keras.backend.update_sub') 1372def update_sub(x, decrement): 1373 """Update the value of `x` by subtracting `decrement`. 1374 1375 Arguments: 1376 x: A Variable. 1377 decrement: A tensor of same shape as `x`. 1378 1379 Returns: 1380 The variable `x` updated. 1381 """ 1382 return state_ops.assign_sub(x, decrement) 1383 1384 1385@keras_export('keras.backend.moving_average_update') 1386def moving_average_update(x, value, momentum): 1387 """Compute the moving average of a variable. 1388 1389 Arguments: 1390 x: A Variable. 1391 value: A tensor with the same shape as `variable`. 1392 momentum: The moving average momentum. 1393 1394 Returns: 1395 An Operation to update the variable. 1396 """ 1397 # `training` is higher-up than the Keras backend in the abstraction hierarchy. 1398 # In particular, `training` depends on layers, and thus on Keras. 1399 # moving_averages, being low-level ops, should not be part of the training 1400 # module. 1401 from tensorflow.python.training import moving_averages # pylint: disable=g-import-not-at-top 1402 return moving_averages.assign_moving_average( 1403 x, value, momentum, zero_debias=True) 1404 1405 1406# LINEAR ALGEBRA 1407 1408 1409@keras_export('keras.backend.dot') 1410def dot(x, y): 1411 """Multiplies 2 tensors (and/or variables) and returns a *tensor*. 1412 1413 When attempting to multiply a nD tensor 1414 with a nD tensor, it reproduces the Theano behavior. 1415 (e.g. `(2, 3) * (4, 3, 5) -> (2, 4, 5)`) 1416 1417 Arguments: 1418 x: Tensor or variable. 1419 y: Tensor or variable. 1420 1421 Returns: 1422 A tensor, dot product of `x` and `y`. 1423 1424 Examples: 1425 ```python 1426 # dot product between tensors 1427 >>> x = K.placeholder(shape=(2, 3)) 1428 >>> y = K.placeholder(shape=(3, 4)) 1429 >>> xy = K.dot(x, y) 1430 >>> xy 1431 <tf.Tensor 'MatMul_9:0' shape=(2, 4) dtype=float32> 1432 ``` 1433 1434 ```python 1435 # dot product between tensors 1436 >>> x = K.placeholder(shape=(32, 28, 3)) 1437 >>> y = K.placeholder(shape=(3, 4)) 1438 >>> xy = K.dot(x, y) 1439 >>> xy 1440 <tf.Tensor 'MatMul_9:0' shape=(32, 28, 4) dtype=float32> 1441 ``` 1442 1443 ```python 1444 # Theano-like behavior example 1445 >>> x = K.random_uniform_variable(shape=(2, 3), low=0, high=1) 1446 >>> y = K.ones((4, 3, 5)) 1447 >>> xy = K.dot(x, y) 1448 >>> K.int_shape(xy) 1449 (2, 4, 5) 1450 ``` 1451 """ 1452 if ndim(x) is not None and (ndim(x) > 2 or ndim(y) > 2): 1453 x_shape = [] 1454 for i, s in zip(int_shape(x), array_ops.unstack(array_ops.shape(x))): 1455 if i is not None: 1456 x_shape.append(i) 1457 else: 1458 x_shape.append(s) 1459 x_shape = tuple(x_shape) 1460 y_shape = [] 1461 for i, s in zip(int_shape(y), array_ops.unstack(array_ops.shape(y))): 1462 if i is not None: 1463 y_shape.append(i) 1464 else: 1465 y_shape.append(s) 1466 y_shape = tuple(y_shape) 1467 y_permute_dim = list(range(ndim(y))) 1468 y_permute_dim = [y_permute_dim.pop(-2)] + y_permute_dim 1469 xt = array_ops.reshape(x, [-1, x_shape[-1]]) 1470 yt = array_ops.reshape( 1471 array_ops.transpose(y, perm=y_permute_dim), [y_shape[-2], -1]) 1472 return array_ops.reshape( 1473 math_ops.matmul(xt, yt), x_shape[:-1] + y_shape[:-2] + y_shape[-1:]) 1474 if is_sparse(x): 1475 out = sparse_ops.sparse_tensor_dense_matmul(x, y) 1476 else: 1477 out = math_ops.matmul(x, y) 1478 return out 1479 1480 1481@keras_export('keras.backend.batch_dot') 1482def batch_dot(x, y, axes=None): 1483 """Batchwise dot product. 1484 1485 `batch_dot` is used to compute dot product of `x` and `y` when 1486 `x` and `y` are data in batch, i.e. in a shape of 1487 `(batch_size, :)`. 1488 `batch_dot` results in a tensor or variable with less dimensions 1489 than the input. If the number of dimensions is reduced to 1, 1490 we use `expand_dims` to make sure that ndim is at least 2. 1491 1492 Arguments: 1493 x: Keras tensor or variable with `ndim >= 2`. 1494 y: Keras tensor or variable with `ndim >= 2`. 1495 axes: list of (or single) int with target dimensions. 1496 The lengths of `axes[0]` and `axes[1]` should be the same. 1497 1498 Returns: 1499 A tensor with shape equal to the concatenation of `x`'s shape 1500 (less the dimension that was summed over) and `y`'s shape 1501 (less the batch dimension and the dimension that was summed over). 1502 If the final rank is 1, we reshape it to `(batch_size, 1)`. 1503 1504 Examples: 1505 Assume `x = [[1, 2], [3, 4]]` and `y = [[5, 6], [7, 8]]` 1506 `batch_dot(x, y, axes=1) = [[17, 53]]` which is the main diagonal 1507 of `x.dot(y.T)`, although we never have to calculate the off-diagonal 1508 elements. 1509 1510 Shape inference: 1511 Let `x`'s shape be `(100, 20)` and `y`'s shape be `(100, 30, 20)`. 1512 If `axes` is (1, 2), to find the output shape of resultant tensor, 1513 loop through each dimension in `x`'s shape and `y`'s shape: 1514 1515 * `x.shape[0]` : 100 : append to output shape 1516 * `x.shape[1]` : 20 : do not append to output shape, 1517 dimension 1 of `x` has been summed over. (`dot_axes[0]` = 1) 1518 * `y.shape[0]` : 100 : do not append to output shape, 1519 always ignore first dimension of `y` 1520 * `y.shape[1]` : 30 : append to output shape 1521 * `y.shape[2]` : 20 : do not append to output shape, 1522 dimension 2 of `y` has been summed over. (`dot_axes[1]` = 2) 1523 `output_shape` = `(100, 30)` 1524 1525 ```python 1526 >>> x_batch = K.ones(shape=(32, 20, 1)) 1527 >>> y_batch = K.ones(shape=(32, 30, 20)) 1528 >>> xy_batch_dot = K.batch_dot(x_batch, y_batch, axes=[1, 2]) 1529 >>> K.int_shape(xy_batch_dot) 1530 (32, 1, 30) 1531 ``` 1532 """ 1533 if isinstance(axes, int): 1534 axes = (axes, axes) 1535 x_ndim = ndim(x) 1536 y_ndim = ndim(y) 1537 if axes is None: 1538 # behaves like tf.batch_matmul as default 1539 axes = [x_ndim - 1, y_ndim - 2] 1540 if x_ndim > y_ndim: 1541 diff = x_ndim - y_ndim 1542 y = array_ops.reshape(y, 1543 array_ops.concat( 1544 [array_ops.shape(y), [1] * (diff)], axis=0)) 1545 elif y_ndim > x_ndim: 1546 diff = y_ndim - x_ndim 1547 x = array_ops.reshape(x, 1548 array_ops.concat( 1549 [array_ops.shape(x), [1] * (diff)], axis=0)) 1550 else: 1551 diff = 0 1552 if ndim(x) == 2 and ndim(y) == 2: 1553 if axes[0] == axes[1]: 1554 out = math_ops.reduce_sum(math_ops.multiply(x, y), axes[0]) 1555 else: 1556 out = math_ops.reduce_sum( 1557 math_ops.multiply(array_ops.transpose(x, [1, 0]), y), axes[1]) 1558 else: 1559 adj_x = None if axes[0] == ndim(x) - 1 else True 1560 adj_y = True if axes[1] == ndim(y) - 1 else None 1561 out = math_ops.matmul(x, y, adjoint_a=adj_x, adjoint_b=adj_y) 1562 if diff: 1563 if x_ndim > y_ndim: 1564 idx = x_ndim + y_ndim - 3 1565 else: 1566 idx = x_ndim - 1 1567 out = array_ops.squeeze(out, list(range(idx, idx + diff))) 1568 if ndim(out) == 1: 1569 out = expand_dims(out, 1) 1570 return out 1571 1572 1573@keras_export('keras.backend.transpose') 1574def transpose(x): 1575 """Transposes a tensor and returns it. 1576 1577 Arguments: 1578 x: Tensor or variable. 1579 1580 Returns: 1581 A tensor. 1582 1583 Examples: 1584 ```python 1585 >>> var = K.variable([[1, 2, 3], [4, 5, 6]]) 1586 >>> K.eval(var) 1587 array([[ 1., 2., 3.], 1588 [ 4., 5., 6.]], dtype=float32) 1589 >>> var_transposed = K.transpose(var) 1590 >>> K.eval(var_transposed) 1591 array([[ 1., 4.], 1592 [ 2., 5.], 1593 [ 3., 6.]], dtype=float32) 1594 ``` 1595 1596 ```python 1597 >>> input = K.placeholder((2, 3)) 1598 >>> input 1599 <tf.Tensor 'Placeholder_11:0' shape=(2, 3) dtype=float32> 1600 >>> input_transposed = K.transpose(input) 1601 >>> input_transposed 1602 <tf.Tensor 'transpose_4:0' shape=(3, 2) dtype=float32> 1603 1604 ``` 1605 """ 1606 return array_ops.transpose(x) 1607 1608 1609@keras_export('keras.backend.gather') 1610def gather(reference, indices): 1611 """Retrieves the elements of indices `indices` in the tensor `reference`. 1612 1613 Arguments: 1614 reference: A tensor. 1615 indices: An integer tensor of indices. 1616 1617 Returns: 1618 A tensor of same type as `reference`. 1619 """ 1620 return array_ops.gather(reference, indices) 1621 1622 1623# ELEMENT-WISE OPERATIONS 1624 1625 1626@keras_export('keras.backend.max') 1627def max(x, axis=None, keepdims=False): 1628 """Maximum value in a tensor. 1629 1630 Arguments: 1631 x: A tensor or variable. 1632 axis: An integer, the axis to find maximum values. 1633 keepdims: A boolean, whether to keep the dimensions or not. 1634 If `keepdims` is `False`, the rank of the tensor is reduced 1635 by 1. If `keepdims` is `True`, 1636 the reduced dimension is retained with length 1. 1637 1638 Returns: 1639 A tensor with maximum values of `x`. 1640 """ 1641 return math_ops.reduce_max(x, axis, keepdims) 1642 1643 1644@keras_export('keras.backend.min') 1645def min(x, axis=None, keepdims=False): 1646 """Minimum value in a tensor. 1647 1648 Arguments: 1649 x: A tensor or variable. 1650 axis: An integer, the axis to find minimum values. 1651 keepdims: A boolean, whether to keep the dimensions or not. 1652 If `keepdims` is `False`, the rank of the tensor is reduced 1653 by 1. If `keepdims` is `True`, 1654 the reduced dimension is retained with length 1. 1655 1656 Returns: 1657 A tensor with minimum values of `x`. 1658 """ 1659 return math_ops.reduce_min(x, axis, keepdims) 1660 1661 1662@keras_export('keras.backend.sum') 1663def sum(x, axis=None, keepdims=False): 1664 """Sum of the values in a tensor, alongside the specified axis. 1665 1666 Arguments: 1667 x: A tensor or variable. 1668 axis: An integer, the axis to sum over. 1669 keepdims: A boolean, whether to keep the dimensions or not. 1670 If `keepdims` is `False`, the rank of the tensor is reduced 1671 by 1. If `keepdims` is `True`, 1672 the reduced dimension is retained with length 1. 1673 1674 Returns: 1675 A tensor with sum of `x`. 1676 """ 1677 return math_ops.reduce_sum(x, axis, keepdims) 1678 1679 1680@keras_export('keras.backend.prod') 1681def prod(x, axis=None, keepdims=False): 1682 """Multiplies the values in a tensor, alongside the specified axis. 1683 1684 Arguments: 1685 x: A tensor or variable. 1686 axis: An integer, the axis to compute the product. 1687 keepdims: A boolean, whether to keep the dimensions or not. 1688 If `keepdims` is `False`, the rank of the tensor is reduced 1689 by 1. If `keepdims` is `True`, 1690 the reduced dimension is retained with length 1. 1691 1692 Returns: 1693 A tensor with the product of elements of `x`. 1694 """ 1695 return math_ops.reduce_prod(x, axis, keepdims) 1696 1697 1698@keras_export('keras.backend.cumsum') 1699def cumsum(x, axis=0): 1700 """Cumulative sum of the values in a tensor, alongside the specified axis. 1701 1702 Arguments: 1703 x: A tensor or variable. 1704 axis: An integer, the axis to compute the sum. 1705 1706 Returns: 1707 A tensor of the cumulative sum of values of `x` along `axis`. 1708 """ 1709 return math_ops.cumsum(x, axis=axis) 1710 1711 1712@keras_export('keras.backend.cumprod') 1713def cumprod(x, axis=0): 1714 """Cumulative product of the values in a tensor, alongside the specified axis. 1715 1716 Arguments: 1717 x: A tensor or variable. 1718 axis: An integer, the axis to compute the product. 1719 1720 Returns: 1721 A tensor of the cumulative product of values of `x` along `axis`. 1722 """ 1723 return math_ops.cumprod(x, axis=axis) 1724 1725 1726@keras_export('keras.backend.var') 1727def var(x, axis=None, keepdims=False): 1728 """Variance of a tensor, alongside the specified axis. 1729 1730 Arguments: 1731 x: A tensor or variable. 1732 axis: An integer, the axis to compute the variance. 1733 keepdims: A boolean, whether to keep the dimensions or not. 1734 If `keepdims` is `False`, the rank of the tensor is reduced 1735 by 1. If `keepdims` is `True`, 1736 the reduced dimension is retained with length 1. 1737 1738 Returns: 1739 A tensor with the variance of elements of `x`. 1740 """ 1741 if x.dtype.base_dtype == dtypes_module.bool: 1742 x = math_ops.cast(x, floatx()) 1743 return math_ops.reduce_variance(x, axis=axis, keepdims=keepdims) 1744 1745 1746@keras_export('keras.backend.std') 1747def std(x, axis=None, keepdims=False): 1748 """Standard deviation of a tensor, alongside the specified axis. 1749 1750 Arguments: 1751 x: A tensor or variable. 1752 axis: An integer, the axis to compute the standard deviation. 1753 keepdims: A boolean, whether to keep the dimensions or not. 1754 If `keepdims` is `False`, the rank of the tensor is reduced 1755 by 1. If `keepdims` is `True`, 1756 the reduced dimension is retained with length 1. 1757 1758 Returns: 1759 A tensor with the standard deviation of elements of `x`. 1760 """ 1761 if x.dtype.base_dtype == dtypes_module.bool: 1762 x = math_ops.cast(x, floatx()) 1763 return math_ops.reduce_std(x, axis=axis, keepdims=keepdims) 1764 1765 1766@keras_export('keras.backend.mean') 1767def mean(x, axis=None, keepdims=False): 1768 """Mean of a tensor, alongside the specified axis. 1769 1770 Arguments: 1771 x: A tensor or variable. 1772 axis: A list of integer. Axes to compute the mean. 1773 keepdims: A boolean, whether to keep the dimensions or not. 1774 If `keepdims` is `False`, the rank of the tensor is reduced 1775 by 1 for each entry in `axis`. If `keepdims` is `True`, 1776 the reduced dimensions are retained with length 1. 1777 1778 Returns: 1779 A tensor with the mean of elements of `x`. 1780 """ 1781 if x.dtype.base_dtype == dtypes_module.bool: 1782 x = math_ops.cast(x, floatx()) 1783 return math_ops.reduce_mean(x, axis, keepdims) 1784 1785 1786@keras_export('keras.backend.any') 1787def any(x, axis=None, keepdims=False): 1788 """Bitwise reduction (logical OR). 1789 1790 Arguments: 1791 x: Tensor or variable. 1792 axis: axis along which to perform the reduction. 1793 keepdims: whether the drop or broadcast the reduction axes. 1794 1795 Returns: 1796 A uint8 tensor (0s and 1s). 1797 """ 1798 x = math_ops.cast(x, dtypes_module.bool) 1799 return math_ops.reduce_any(x, axis, keepdims) 1800 1801 1802@keras_export('keras.backend.all') 1803def all(x, axis=None, keepdims=False): 1804 """Bitwise reduction (logical AND). 1805 1806 Arguments: 1807 x: Tensor or variable. 1808 axis: axis along which to perform the reduction. 1809 keepdims: whether the drop or broadcast the reduction axes. 1810 1811 Returns: 1812 A uint8 tensor (0s and 1s). 1813 """ 1814 x = math_ops.cast(x, dtypes_module.bool) 1815 return math_ops.reduce_all(x, axis, keepdims) 1816 1817 1818@keras_export('keras.backend.argmax') 1819def argmax(x, axis=-1): 1820 """Returns the index of the maximum value along an axis. 1821 1822 Arguments: 1823 x: Tensor or variable. 1824 axis: axis along which to perform the reduction. 1825 1826 Returns: 1827 A tensor. 1828 """ 1829 return math_ops.argmax(x, axis) 1830 1831 1832@keras_export('keras.backend.argmin') 1833def argmin(x, axis=-1): 1834 """Returns the index of the minimum value along an axis. 1835 1836 Arguments: 1837 x: Tensor or variable. 1838 axis: axis along which to perform the reduction. 1839 1840 Returns: 1841 A tensor. 1842 """ 1843 return math_ops.argmin(x, axis) 1844 1845 1846@keras_export('keras.backend.square') 1847def square(x): 1848 """Element-wise square. 1849 1850 Arguments: 1851 x: Tensor or variable. 1852 1853 Returns: 1854 A tensor. 1855 """ 1856 return math_ops.square(x) 1857 1858 1859@keras_export('keras.backend.abs') 1860def abs(x): 1861 """Element-wise absolute value. 1862 1863 Arguments: 1864 x: Tensor or variable. 1865 1866 Returns: 1867 A tensor. 1868 """ 1869 return math_ops.abs(x) 1870 1871 1872@keras_export('keras.backend.sqrt') 1873def sqrt(x): 1874 """Element-wise square root. 1875 1876 Arguments: 1877 x: Tensor or variable. 1878 1879 Returns: 1880 A tensor. 1881 """ 1882 zero = _to_tensor(0., x.dtype.base_dtype) 1883 inf = _to_tensor(np.inf, x.dtype.base_dtype) 1884 x = clip_ops.clip_by_value(x, zero, inf) 1885 return math_ops.sqrt(x) 1886 1887 1888@keras_export('keras.backend.exp') 1889def exp(x): 1890 """Element-wise exponential. 1891 1892 Arguments: 1893 x: Tensor or variable. 1894 1895 Returns: 1896 A tensor. 1897 """ 1898 return math_ops.exp(x) 1899 1900 1901@keras_export('keras.backend.log') 1902def log(x): 1903 """Element-wise log. 1904 1905 Arguments: 1906 x: Tensor or variable. 1907 1908 Returns: 1909 A tensor. 1910 """ 1911 return math_ops.log(x) 1912 1913 1914def logsumexp(x, axis=None, keepdims=False): 1915 """Computes log(sum(exp(elements across dimensions of a tensor))). 1916 1917 This function is more numerically stable than log(sum(exp(x))). 1918 It avoids overflows caused by taking the exp of large inputs and 1919 underflows caused by taking the log of small inputs. 1920 1921 Arguments: 1922 x: A tensor or variable. 1923 axis: An integer, the axis to reduce over. 1924 keepdims: A boolean, whether to keep the dimensions or not. 1925 If `keepdims` is `False`, the rank of the tensor is reduced 1926 by 1. If `keepdims` is `True`, the reduced dimension is 1927 retained with length 1. 1928 1929 Returns: 1930 The reduced tensor. 1931 """ 1932 return math_ops.reduce_logsumexp(x, axis, keepdims) 1933 1934 1935@keras_export('keras.backend.round') 1936def round(x): 1937 """Element-wise rounding to the closest integer. 1938 1939 In case of tie, the rounding mode used is "half to even". 1940 1941 Arguments: 1942 x: Tensor or variable. 1943 1944 Returns: 1945 A tensor. 1946 """ 1947 return math_ops.round(x) 1948 1949 1950@keras_export('keras.backend.sign') 1951def sign(x): 1952 """Element-wise sign. 1953 1954 Arguments: 1955 x: Tensor or variable. 1956 1957 Returns: 1958 A tensor. 1959 """ 1960 return math_ops.sign(x) 1961 1962 1963@keras_export('keras.backend.pow') 1964def pow(x, a): 1965 """Element-wise exponentiation. 1966 1967 Arguments: 1968 x: Tensor or variable. 1969 a: Python integer. 1970 1971 Returns: 1972 A tensor. 1973 """ 1974 return math_ops.pow(x, a) 1975 1976 1977@keras_export('keras.backend.clip') 1978def clip(x, min_value, max_value): 1979 """Element-wise value clipping. 1980 1981 Arguments: 1982 x: Tensor or variable. 1983 min_value: Python float or integer. 1984 max_value: Python float or integer. 1985 1986 Returns: 1987 A tensor. 1988 """ 1989 if max_value is not None and max_value < min_value: 1990 max_value = min_value 1991 if max_value is None: 1992 max_value = np.inf 1993 min_value = _to_tensor(min_value, x.dtype.base_dtype) 1994 max_value = _to_tensor(max_value, x.dtype.base_dtype) 1995 return clip_ops.clip_by_value(x, min_value, max_value) 1996 1997 1998@keras_export('keras.backend.equal') 1999def equal(x, y): 2000 """Element-wise equality between two tensors. 2001 2002 Arguments: 2003 x: Tensor or variable. 2004 y: Tensor or variable. 2005 2006 Returns: 2007 A bool tensor. 2008 """ 2009 return math_ops.equal(x, y) 2010 2011 2012@keras_export('keras.backend.not_equal') 2013def not_equal(x, y): 2014 """Element-wise inequality between two tensors. 2015 2016 Arguments: 2017 x: Tensor or variable. 2018 y: Tensor or variable. 2019 2020 Returns: 2021 A bool tensor. 2022 """ 2023 return math_ops.not_equal(x, y) 2024 2025 2026@keras_export('keras.backend.greater') 2027def greater(x, y): 2028 """Element-wise truth value of (x > y). 2029 2030 Arguments: 2031 x: Tensor or variable. 2032 y: Tensor or variable. 2033 2034 Returns: 2035 A bool tensor. 2036 """ 2037 return math_ops.greater(x, y) 2038 2039 2040@keras_export('keras.backend.greater_equal') 2041def greater_equal(x, y): 2042 """Element-wise truth value of (x >= y). 2043 2044 Arguments: 2045 x: Tensor or variable. 2046 y: Tensor or variable. 2047 2048 Returns: 2049 A bool tensor. 2050 """ 2051 return math_ops.greater_equal(x, y) 2052 2053 2054@keras_export('keras.backend.less') 2055def less(x, y): 2056 """Element-wise truth value of (x < y). 2057 2058 Arguments: 2059 x: Tensor or variable. 2060 y: Tensor or variable. 2061 2062 Returns: 2063 A bool tensor. 2064 """ 2065 return math_ops.less(x, y) 2066 2067 2068@keras_export('keras.backend.less_equal') 2069def less_equal(x, y): 2070 """Element-wise truth value of (x <= y). 2071 2072 Arguments: 2073 x: Tensor or variable. 2074 y: Tensor or variable. 2075 2076 Returns: 2077 A bool tensor. 2078 """ 2079 return math_ops.less_equal(x, y) 2080 2081 2082@keras_export('keras.backend.maximum') 2083def maximum(x, y): 2084 """Element-wise maximum of two tensors. 2085 2086 Arguments: 2087 x: Tensor or variable. 2088 y: Tensor or variable. 2089 2090 Returns: 2091 A tensor. 2092 """ 2093 return math_ops.maximum(x, y) 2094 2095 2096@keras_export('keras.backend.minimum') 2097def minimum(x, y): 2098 """Element-wise minimum of two tensors. 2099 2100 Arguments: 2101 x: Tensor or variable. 2102 y: Tensor or variable. 2103 2104 Returns: 2105 A tensor. 2106 """ 2107 return math_ops.minimum(x, y) 2108 2109 2110@keras_export('keras.backend.sin') 2111def sin(x): 2112 """Computes sin of x element-wise. 2113 2114 Arguments: 2115 x: Tensor or variable. 2116 2117 Returns: 2118 A tensor. 2119 """ 2120 return math_ops.sin(x) 2121 2122 2123@keras_export('keras.backend.cos') 2124def cos(x): 2125 """Computes cos of x element-wise. 2126 2127 Arguments: 2128 x: Tensor or variable. 2129 2130 Returns: 2131 A tensor. 2132 """ 2133 return math_ops.cos(x) 2134 2135 2136def _regular_normalize_batch_in_training(x, 2137 gamma, 2138 beta, 2139 reduction_axes, 2140 epsilon=1e-3): 2141 """Non-fused version of `normalize_batch_in_training`. 2142 2143 Arguments: 2144 x: Input tensor or variable. 2145 gamma: Tensor by which to scale the input. 2146 beta: Tensor with which to center the input. 2147 reduction_axes: iterable of integers, 2148 axes over which to normalize. 2149 epsilon: Fuzz factor. 2150 2151 Returns: 2152 A tuple length of 3, `(normalized_tensor, mean, variance)`. 2153 """ 2154 mean, var = nn.moments(x, reduction_axes, None, None, False) 2155 normed = nn.batch_normalization(x, mean, var, beta, gamma, epsilon) 2156 return normed, mean, var 2157 2158 2159def _broadcast_normalize_batch_in_training(x, 2160 gamma, 2161 beta, 2162 reduction_axes, 2163 epsilon=1e-3): 2164 """Non-fused, broadcast version of `normalize_batch_in_training`. 2165 2166 Arguments: 2167 x: Input tensor or variable. 2168 gamma: Tensor by which to scale the input. 2169 beta: Tensor with which to center the input. 2170 reduction_axes: iterable of integers, 2171 axes over which to normalize. 2172 epsilon: Fuzz factor. 2173 2174 Returns: 2175 A tuple length of 3, `(normalized_tensor, mean, variance)`. 2176 """ 2177 mean, var = nn.moments(x, reduction_axes, None, None, False) 2178 target_shape = [] 2179 for axis in range(ndim(x)): 2180 if axis in reduction_axes: 2181 target_shape.append(1) 2182 else: 2183 target_shape.append(array_ops.shape(x)[axis]) 2184 target_shape = array_ops.stack(target_shape) 2185 2186 broadcast_mean = array_ops.reshape(mean, target_shape) 2187 broadcast_var = array_ops.reshape(var, target_shape) 2188 if gamma is None: 2189 broadcast_gamma = None 2190 else: 2191 broadcast_gamma = array_ops.reshape(gamma, target_shape) 2192 if beta is None: 2193 broadcast_beta = None 2194 else: 2195 broadcast_beta = array_ops.reshape(beta, target_shape) 2196 2197 normed = nn.batch_normalization(x, broadcast_mean, broadcast_var, 2198 broadcast_beta, broadcast_gamma, epsilon) 2199 return normed, mean, var 2200 2201 2202def _fused_normalize_batch_in_training(x, 2203 gamma, 2204 beta, 2205 reduction_axes, 2206 epsilon=1e-3): 2207 """Fused version of `normalize_batch_in_training`. 2208 2209 Arguments: 2210 x: Input tensor or variable. 2211 gamma: Tensor by which to scale the input. 2212 beta: Tensor with which to center the input. 2213 reduction_axes: iterable of integers, 2214 axes over which to normalize. 2215 epsilon: Fuzz factor. 2216 2217 Returns: 2218 A tuple length of 3, `(normalized_tensor, mean, variance)`. 2219 """ 2220 if list(reduction_axes) == [0, 1, 2]: 2221 normalization_axis = 3 2222 tf_data_format = 'NHWC' 2223 else: 2224 normalization_axis = 1 2225 tf_data_format = 'NCHW' 2226 2227 if gamma is None: 2228 gamma = constant_op.constant( 2229 1.0, dtype=x.dtype, shape=[x.shape[normalization_axis]]) 2230 if beta is None: 2231 beta = constant_op.constant( 2232 0.0, dtype=x.dtype, shape=[x.shape[normalization_axis]]) 2233 2234 return nn.fused_batch_norm( 2235 x, gamma, beta, epsilon=epsilon, data_format=tf_data_format) 2236 2237 2238@keras_export('keras.backend.normalize_batch_in_training') 2239def normalize_batch_in_training(x, gamma, beta, reduction_axes, epsilon=1e-3): 2240 """Computes mean and std for batch then apply batch_normalization on batch. 2241 2242 Arguments: 2243 x: Input tensor or variable. 2244 gamma: Tensor by which to scale the input. 2245 beta: Tensor with which to center the input. 2246 reduction_axes: iterable of integers, 2247 axes over which to normalize. 2248 epsilon: Fuzz factor. 2249 2250 Returns: 2251 A tuple length of 3, `(normalized_tensor, mean, variance)`. 2252 """ 2253 if ndim(x) == 4 and list(reduction_axes) in [[0, 1, 2], [0, 2, 3]]: 2254 if not _has_nchw_support() and list(reduction_axes) == [0, 2, 3]: 2255 return _broadcast_normalize_batch_in_training( 2256 x, gamma, beta, reduction_axes, epsilon=epsilon) 2257 return _fused_normalize_batch_in_training( 2258 x, gamma, beta, reduction_axes, epsilon=epsilon) 2259 else: 2260 if sorted(reduction_axes) == list(range(ndim(x)))[:-1]: 2261 return _regular_normalize_batch_in_training( 2262 x, gamma, beta, reduction_axes, epsilon=epsilon) 2263 else: 2264 return _broadcast_normalize_batch_in_training( 2265 x, gamma, beta, reduction_axes, epsilon=epsilon) 2266 2267 2268@keras_export('keras.backend.batch_normalization') 2269def batch_normalization(x, mean, var, beta, gamma, axis=-1, epsilon=1e-3): 2270 """Applies batch normalization on x given mean, var, beta and gamma. 2271 2272 I.e. returns: 2273 `output = (x - mean) / (sqrt(var) + epsilon) * gamma + beta` 2274 2275 Arguments: 2276 x: Input tensor or variable. 2277 mean: Mean of batch. 2278 var: Variance of batch. 2279 beta: Tensor with which to center the input. 2280 gamma: Tensor by which to scale the input. 2281 axis: Integer, the axis that should be normalized. 2282 (typically the features axis). 2283 epsilon: Fuzz factor. 2284 2285 Returns: 2286 A tensor. 2287 """ 2288 if ndim(x) == 4: 2289 # The CPU implementation of `fused_batch_norm` only supports NHWC 2290 if axis == 1 or axis == -3: 2291 tf_data_format = 'NCHW' 2292 elif axis == 3 or axis == -1: 2293 tf_data_format = 'NHWC' 2294 else: 2295 tf_data_format = None 2296 2297 if (tf_data_format == 'NHWC' or 2298 tf_data_format == 'NCHW' and _has_nchw_support()): 2299 # The mean / var / beta / gamma tensors may be broadcasted 2300 # so they may have extra axes of size 1, which should be squeezed. 2301 if ndim(mean) > 1: 2302 mean = array_ops.reshape(mean, [-1]) 2303 if ndim(var) > 1: 2304 var = array_ops.reshape(var, [-1]) 2305 if beta is None: 2306 beta = zeros_like(mean) 2307 elif ndim(beta) > 1: 2308 beta = array_ops.reshape(beta, [-1]) 2309 if gamma is None: 2310 gamma = ones_like(mean) 2311 elif ndim(gamma) > 1: 2312 gamma = array_ops.reshape(gamma, [-1]) 2313 y, _, _ = nn.fused_batch_norm( 2314 x, 2315 gamma, 2316 beta, 2317 epsilon=epsilon, 2318 mean=mean, 2319 variance=var, 2320 data_format=tf_data_format, 2321 is_training=False 2322 ) 2323 return y 2324 return nn.batch_normalization(x, mean, var, beta, gamma, epsilon) 2325 2326 2327# SHAPE OPERATIONS 2328 2329 2330@keras_export('keras.backend.concatenate') 2331def concatenate(tensors, axis=-1): 2332 """Concatenates a list of tensors alongside the specified axis. 2333 2334 Arguments: 2335 tensors: list of tensors to concatenate. 2336 axis: concatenation axis. 2337 2338 Returns: 2339 A tensor. 2340 """ 2341 if axis < 0: 2342 rank = ndim(tensors[0]) 2343 if rank: 2344 axis %= rank 2345 else: 2346 axis = 0 2347 2348 if py_all(is_sparse(x) for x in tensors): 2349 return sparse_ops.sparse_concat(axis, tensors) 2350 else: 2351 return array_ops.concat([to_dense(x) for x in tensors], axis) 2352 2353 2354@keras_export('keras.backend.reshape') 2355def reshape(x, shape): 2356 """Reshapes a tensor to the specified shape. 2357 2358 Arguments: 2359 x: Tensor or variable. 2360 shape: Target shape tuple. 2361 2362 Returns: 2363 A tensor. 2364 """ 2365 return array_ops.reshape(x, shape) 2366 2367 2368@keras_export('keras.backend.permute_dimensions') 2369def permute_dimensions(x, pattern): 2370 """Permutes axes in a tensor. 2371 2372 Arguments: 2373 x: Tensor or variable. 2374 pattern: A tuple of 2375 dimension indices, e.g. `(0, 2, 1)`. 2376 2377 Returns: 2378 A tensor. 2379 """ 2380 return array_ops.transpose(x, perm=pattern) 2381 2382 2383@keras_export('keras.backend.resize_images') 2384def resize_images(x, height_factor, width_factor, data_format, 2385 interpolation='nearest'): 2386 """Resizes the images contained in a 4D tensor. 2387 2388 Arguments: 2389 x: Tensor or variable to resize. 2390 height_factor: Positive integer. 2391 width_factor: Positive integer. 2392 data_format: One of `"channels_first"`, `"channels_last"`. 2393 interpolation: A string, one of `nearest` or `bilinear`. 2394 2395 Returns: 2396 A tensor. 2397 2398 Raises: 2399 ValueError: in case of incorrect value for 2400 `data_format` or `interpolation`. 2401 """ 2402 if data_format == 'channels_first': 2403 rows, cols = 2, 3 2404 elif data_format == 'channels_last': 2405 rows, cols = 1, 2 2406 else: 2407 raise ValueError('Invalid `data_format` argument: %s' % (data_format,)) 2408 2409 original_shape = int_shape(x) 2410 new_shape = array_ops.shape(x)[rows:cols + 1] 2411 new_shape *= constant_op.constant( 2412 np.array([height_factor, width_factor], dtype='int32')) 2413 2414 if data_format == 'channels_first': 2415 x = permute_dimensions(x, [0, 2, 3, 1]) 2416 if interpolation == 'nearest': 2417 x = image_ops.resize_nearest_neighbor(x, new_shape) 2418 elif interpolation == 'bilinear': 2419 x = image_ops.resize_bilinear(x, new_shape) 2420 else: 2421 raise ValueError('interpolation should be one ' 2422 'of "nearest" or "bilinear".') 2423 if data_format == 'channels_first': 2424 x = permute_dimensions(x, [0, 3, 1, 2]) 2425 2426 if original_shape[rows] is None: 2427 new_height = None 2428 else: 2429 new_height = original_shape[rows] * height_factor 2430 2431 if original_shape[cols] is None: 2432 new_width = None 2433 else: 2434 new_width = original_shape[cols] * width_factor 2435 2436 if data_format == 'channels_first': 2437 output_shape = (None, None, new_height, new_width) 2438 else: 2439 output_shape = (None, new_height, new_width, None) 2440 x.set_shape(output_shape) 2441 return x 2442 2443 2444@keras_export('keras.backend.resize_volumes') 2445def resize_volumes(x, depth_factor, height_factor, width_factor, data_format): 2446 """Resizes the volume contained in a 5D tensor. 2447 2448 Arguments: 2449 x: Tensor or variable to resize. 2450 depth_factor: Positive integer. 2451 height_factor: Positive integer. 2452 width_factor: Positive integer. 2453 data_format: One of `"channels_first"`, `"channels_last"`. 2454 2455 Returns: 2456 A tensor. 2457 2458 Raises: 2459 ValueError: if `data_format` is neither 2460 `channels_last` or `channels_first`. 2461 """ 2462 if data_format == 'channels_first': 2463 output = repeat_elements(x, depth_factor, axis=2) 2464 output = repeat_elements(output, height_factor, axis=3) 2465 output = repeat_elements(output, width_factor, axis=4) 2466 return output 2467 elif data_format == 'channels_last': 2468 output = repeat_elements(x, depth_factor, axis=1) 2469 output = repeat_elements(output, height_factor, axis=2) 2470 output = repeat_elements(output, width_factor, axis=3) 2471 return output 2472 else: 2473 raise ValueError('Invalid data_format: ' + str(data_format)) 2474 2475 2476@keras_export('keras.backend.repeat_elements') 2477def repeat_elements(x, rep, axis): 2478 """Repeats the elements of a tensor along an axis, like `np.repeat`. 2479 2480 If `x` has shape `(s1, s2, s3)` and `axis` is `1`, the output 2481 will have shape `(s1, s2 * rep, s3)`. 2482 2483 Arguments: 2484 x: Tensor or variable. 2485 rep: Python integer, number of times to repeat. 2486 axis: Axis along which to repeat. 2487 2488 Returns: 2489 A tensor. 2490 """ 2491 x_shape = x.shape.as_list() 2492 # For static axis 2493 if x_shape[axis] is not None: 2494 # slices along the repeat axis 2495 splits = array_ops.split(value=x, 2496 num_or_size_splits=x_shape[axis], 2497 axis=axis) 2498 # repeat each slice the given number of reps 2499 x_rep = [s for s in splits for _ in range(rep)] 2500 return concatenate(x_rep, axis) 2501 2502 # Here we use tf.tile to mimic behavior of np.repeat so that 2503 # we can handle dynamic shapes (that include None). 2504 # To do that, we need an auxiliary axis to repeat elements along 2505 # it and then merge them along the desired axis. 2506 2507 # Repeating 2508 auxiliary_axis = axis + 1 2509 x_shape = array_ops.shape(x) 2510 x_rep = array_ops.expand_dims(x, axis=auxiliary_axis) 2511 reps = np.ones(len(x.shape) + 1) 2512 reps[auxiliary_axis] = rep 2513 x_rep = array_ops.tile(x_rep, reps) 2514 2515 # Merging 2516 reps = np.delete(reps, auxiliary_axis) 2517 reps[axis] = rep 2518 reps = array_ops.constant(reps, dtype='int32') 2519 x_shape *= reps 2520 x_rep = array_ops.reshape(x_rep, x_shape) 2521 2522 # Fix shape representation 2523 x_shape = x.shape.as_list() 2524 x_rep.set_shape(x_shape) 2525 x_rep._keras_shape = tuple(x_shape) 2526 return x_rep 2527 2528 2529@keras_export('keras.backend.repeat') 2530def repeat(x, n): 2531 """Repeats a 2D tensor. 2532 2533 if `x` has shape (samples, dim) and `n` is `2`, 2534 the output will have shape `(samples, 2, dim)`. 2535 2536 Arguments: 2537 x: Tensor or variable. 2538 n: Python integer, number of times to repeat. 2539 2540 Returns: 2541 A tensor. 2542 """ 2543 assert ndim(x) == 2 2544 x = array_ops.expand_dims(x, 1) 2545 pattern = array_ops.stack([1, n, 1]) 2546 return array_ops.tile(x, pattern) 2547 2548 2549@keras_export('keras.backend.arange') 2550def arange(start, stop=None, step=1, dtype='int32'): 2551 """Creates a 1D tensor containing a sequence of integers. 2552 2553 The function arguments use the same convention as 2554 Theano's arange: if only one argument is provided, 2555 it is in fact the "stop" argument and "start" is 0. 2556 2557 The default type of the returned tensor is `'int32'` to 2558 match TensorFlow's default. 2559 2560 Arguments: 2561 start: Start value. 2562 stop: Stop value. 2563 step: Difference between two successive values. 2564 dtype: Integer dtype to use. 2565 2566 Returns: 2567 An integer tensor. 2568 2569 """ 2570 # Match the behavior of numpy and Theano by returning an empty sequence. 2571 if stop is None and start < 0: 2572 start = 0 2573 result = math_ops.range(start, limit=stop, delta=step, name='arange') 2574 if dtype != 'int32': 2575 result = cast(result, dtype) 2576 return result 2577 2578 2579@keras_export('keras.backend.tile') 2580def tile(x, n): 2581 """Creates a tensor by tiling `x` by `n`. 2582 2583 Arguments: 2584 x: A tensor or variable 2585 n: A list of integer. The length must be the same as the number of 2586 dimensions in `x`. 2587 2588 Returns: 2589 A tiled tensor. 2590 """ 2591 if isinstance(n, int): 2592 n = [n] 2593 return array_ops.tile(x, n) 2594 2595 2596@keras_export('keras.backend.flatten') 2597def flatten(x): 2598 """Flatten a tensor. 2599 2600 Arguments: 2601 x: A tensor or variable. 2602 2603 Returns: 2604 A tensor, reshaped into 1-D 2605 """ 2606 return array_ops.reshape(x, [-1]) 2607 2608 2609@keras_export('keras.backend.batch_flatten') 2610def batch_flatten(x): 2611 """Turn a nD tensor into a 2D tensor with same 0th dimension. 2612 2613 In other words, it flattens each data samples of a batch. 2614 2615 Arguments: 2616 x: A tensor or variable. 2617 2618 Returns: 2619 A tensor. 2620 """ 2621 x = array_ops.reshape(x, array_ops.stack([-1, prod(shape(x)[1:])])) 2622 return x 2623 2624 2625@keras_export('keras.backend.expand_dims') 2626def expand_dims(x, axis=-1): 2627 """Adds a 1-sized dimension at index "axis". 2628 2629 Arguments: 2630 x: A tensor or variable. 2631 axis: Position where to add a new axis. 2632 2633 Returns: 2634 A tensor with expanded dimensions. 2635 """ 2636 return array_ops.expand_dims(x, axis) 2637 2638 2639@keras_export('keras.backend.squeeze') 2640def squeeze(x, axis): 2641 """Removes a 1-dimension from the tensor at index "axis". 2642 2643 Arguments: 2644 x: A tensor or variable. 2645 axis: Axis to drop. 2646 2647 Returns: 2648 A tensor with the same data as `x` but reduced dimensions. 2649 """ 2650 return array_ops.squeeze(x, [axis]) 2651 2652 2653@keras_export('keras.backend.temporal_padding') 2654def temporal_padding(x, padding=(1, 1)): 2655 """Pads the middle dimension of a 3D tensor. 2656 2657 Arguments: 2658 x: Tensor or variable. 2659 padding: Tuple of 2 integers, how many zeros to 2660 add at the start and end of dim 1. 2661 2662 Returns: 2663 A padded 3D tensor. 2664 """ 2665 assert len(padding) == 2 2666 pattern = [[0, 0], [padding[0], padding[1]], [0, 0]] 2667 return array_ops.pad(x, pattern) 2668 2669 2670@keras_export('keras.backend.spatial_2d_padding') 2671def spatial_2d_padding(x, padding=((1, 1), (1, 1)), data_format=None): 2672 """Pads the 2nd and 3rd dimensions of a 4D tensor. 2673 2674 Arguments: 2675 x: Tensor or variable. 2676 padding: Tuple of 2 tuples, padding pattern. 2677 data_format: One of `channels_last` or `channels_first`. 2678 2679 Returns: 2680 A padded 4D tensor. 2681 2682 Raises: 2683 ValueError: if `data_format` is neither 2684 `channels_last` or `channels_first`. 2685 """ 2686 assert len(padding) == 2 2687 assert len(padding[0]) == 2 2688 assert len(padding[1]) == 2 2689 if data_format is None: 2690 data_format = image_data_format() 2691 if data_format not in {'channels_first', 'channels_last'}: 2692 raise ValueError('Unknown data_format: ' + str(data_format)) 2693 2694 if data_format == 'channels_first': 2695 pattern = [[0, 0], [0, 0], list(padding[0]), list(padding[1])] 2696 else: 2697 pattern = [[0, 0], list(padding[0]), list(padding[1]), [0, 0]] 2698 return array_ops.pad(x, pattern) 2699 2700 2701@keras_export('keras.backend.spatial_3d_padding') 2702def spatial_3d_padding(x, padding=((1, 1), (1, 1), (1, 1)), data_format=None): 2703 """Pads 5D tensor with zeros along the depth, height, width dimensions. 2704 2705 Pads these dimensions with respectively 2706 "padding[0]", "padding[1]" and "padding[2]" zeros left and right. 2707 2708 For 'channels_last' data_format, 2709 the 2nd, 3rd and 4th dimension will be padded. 2710 For 'channels_first' data_format, 2711 the 3rd, 4th and 5th dimension will be padded. 2712 2713 Arguments: 2714 x: Tensor or variable. 2715 padding: Tuple of 3 tuples, padding pattern. 2716 data_format: One of `channels_last` or `channels_first`. 2717 2718 Returns: 2719 A padded 5D tensor. 2720 2721 Raises: 2722 ValueError: if `data_format` is neither 2723 `channels_last` or `channels_first`. 2724 2725 """ 2726 assert len(padding) == 3 2727 assert len(padding[0]) == 2 2728 assert len(padding[1]) == 2 2729 assert len(padding[2]) == 2 2730 if data_format is None: 2731 data_format = image_data_format() 2732 if data_format not in {'channels_first', 'channels_last'}: 2733 raise ValueError('Unknown data_format: ' + str(data_format)) 2734 2735 if data_format == 'channels_first': 2736 pattern = [[0, 0], [0, 0], [padding[0][0], padding[0][1]], 2737 [padding[1][0], padding[1][1]], [padding[2][0], padding[2][1]]] 2738 else: 2739 pattern = [[0, 0], [padding[0][0], padding[0][1]], 2740 [padding[1][0], padding[1][1]], [padding[2][0], 2741 padding[2][1]], [0, 0]] 2742 return array_ops.pad(x, pattern) 2743 2744 2745@keras_export('keras.backend.stack') 2746def stack(x, axis=0): 2747 """Stacks a list of rank `R` tensors into a rank `R+1` tensor. 2748 2749 Arguments: 2750 x: List of tensors. 2751 axis: Axis along which to perform stacking. 2752 2753 Returns: 2754 A tensor. 2755 """ 2756 return array_ops.stack(x, axis=axis) 2757 2758 2759@keras_export('keras.backend.one_hot') 2760def one_hot(indices, num_classes): 2761 """Computes the one-hot representation of an integer tensor. 2762 2763 Arguments: 2764 indices: nD integer tensor of shape 2765 `(batch_size, dim1, dim2, ... dim(n-1))` 2766 num_classes: Integer, number of classes to consider. 2767 2768 Returns: 2769 (n + 1)D one hot representation of the input 2770 with shape `(batch_size, dim1, dim2, ... dim(n-1), num_classes)` 2771 2772 Returns: 2773 The one-hot tensor. 2774 """ 2775 return array_ops.one_hot(indices, depth=num_classes, axis=-1) 2776 2777 2778@keras_export('keras.backend.reverse') 2779def reverse(x, axes): 2780 """Reverse a tensor along the specified axes. 2781 2782 Arguments: 2783 x: Tensor to reverse. 2784 axes: Integer or iterable of integers. 2785 Axes to reverse. 2786 2787 Returns: 2788 A tensor. 2789 """ 2790 if isinstance(axes, int): 2791 axes = [axes] 2792 return array_ops.reverse(x, axes) 2793 2794 2795# VALUE MANIPULATION 2796 2797 2798@keras_export('keras.backend.get_value') 2799def get_value(x): 2800 """Returns the value of a variable. 2801 2802 Arguments: 2803 x: input variable. 2804 2805 Returns: 2806 A Numpy array. 2807 2808 Raises: 2809 RuntimeError: If this method is called inside defun. 2810 """ 2811 if context.executing_eagerly(): 2812 return x.numpy() 2813 elif not getattr(x, '_in_graph_mode', True): 2814 # This is a variable which was created in an eager context, but is being 2815 # evaluated from a Graph. 2816 with context.eager_mode(): 2817 return x.numpy() 2818 elif ops.inside_function(): 2819 raise RuntimeError('Cannot get value inside Tensorflow graph function.') 2820 return x.eval(session=get_session((x,))) 2821 2822 2823@keras_export('keras.backend.batch_get_value') 2824def batch_get_value(tensors): 2825 """Returns the value of more than one tensor variable. 2826 2827 Arguments: 2828 tensors: list of ops to run. 2829 2830 Returns: 2831 A list of Numpy arrays. 2832 2833 Raises: 2834 RuntimeError: If this method is called inside defun. 2835 """ 2836 if context.executing_eagerly(): 2837 return [x.numpy() for x in tensors] 2838 elif ops.inside_function(): # pylint: disable=protected-access 2839 raise RuntimeError('Cannot get value inside Tensorflow graph function.') 2840 if tensors: 2841 return get_session(tensors).run(tensors) 2842 else: 2843 return [] 2844 2845 2846@keras_export('keras.backend.set_value') 2847def set_value(x, value): 2848 """Sets the value of a variable, from a Numpy array. 2849 2850 Arguments: 2851 x: Tensor to set to a new value. 2852 value: Value to set the tensor to, as a Numpy array 2853 (of the same shape). 2854 """ 2855 value = np.asarray(value, dtype=dtype(x)) 2856 if ops.executing_eagerly_outside_functions(): 2857 x.assign(value) 2858 else: 2859 with get_graph().as_default(): 2860 tf_dtype = dtypes_module.as_dtype(x.dtype.name.split('_')[0]) 2861 if hasattr(x, '_assign_placeholder'): 2862 assign_placeholder = x._assign_placeholder 2863 assign_op = x._assign_op 2864 else: 2865 assign_placeholder = array_ops.placeholder(tf_dtype, shape=value.shape) 2866 assign_op = x.assign(assign_placeholder) 2867 x._assign_placeholder = assign_placeholder 2868 x._assign_op = assign_op 2869 get_session().run(assign_op, feed_dict={assign_placeholder: value}) 2870 2871 2872@keras_export('keras.backend.batch_set_value') 2873def batch_set_value(tuples): 2874 """Sets the values of many tensor variables at once. 2875 2876 Arguments: 2877 tuples: a list of tuples `(tensor, value)`. 2878 `value` should be a Numpy array. 2879 """ 2880 if ops.executing_eagerly_outside_functions(): 2881 for x, value in tuples: 2882 x.assign(np.asarray(value, dtype=dtype(x))) 2883 else: 2884 with get_graph().as_default(): 2885 if tuples: 2886 assign_ops = [] 2887 feed_dict = {} 2888 for x, value in tuples: 2889 value = np.asarray(value, dtype=dtype(x)) 2890 tf_dtype = dtypes_module.as_dtype(x.dtype.name.split('_')[0]) 2891 if hasattr(x, '_assign_placeholder'): 2892 assign_placeholder = x._assign_placeholder 2893 assign_op = x._assign_op 2894 else: 2895 assign_placeholder = array_ops.placeholder(tf_dtype, 2896 shape=value.shape) 2897 assign_op = x.assign(assign_placeholder) 2898 x._assign_placeholder = assign_placeholder 2899 x._assign_op = assign_op 2900 assign_ops.append(assign_op) 2901 feed_dict[assign_placeholder] = value 2902 get_session().run(assign_ops, feed_dict=feed_dict) 2903 2904 2905@keras_export('keras.backend.print_tensor') 2906def print_tensor(x, message=''): 2907 """Prints `message` and the tensor value when evaluated. 2908 2909 Note that `print_tensor` returns a new tensor identical to `x` 2910 which should be used in the following code. Otherwise the 2911 print operation is not taken into account during evaluation. 2912 2913 Example: 2914 2915 ```python 2916 >>> x = K.print_tensor(x, message="x is: ") 2917 ``` 2918 2919 Arguments: 2920 x: Tensor to print. 2921 message: Message to print jointly with the tensor. 2922 2923 Returns: 2924 The same tensor `x`, unchanged. 2925 """ 2926 return logging_ops.Print(x, [x], message) 2927 2928 2929# GRAPH MANIPULATION 2930 2931 2932class GraphExecutionFunction(object): 2933 """Runs a computation graph. 2934 2935 It's possible to pass arguments to `tf.Session.run()` via `session_kwargs`. 2936 In particular additional operations via `fetches` argument and additional 2937 tensor substitutions via `feed_dict` arguments. Note that given 2938 substitutions are merged with substitutions from `inputs`. Even though 2939 `feed_dict` is passed once in the constructor (called in `model.compile()`) 2940 we can modify the values in the dictionary. Through this feed_dict we can 2941 provide additional substitutions besides Keras inputs. 2942 2943 Arguments: 2944 inputs: Feed placeholders to the computation graph. 2945 outputs: Output tensors to fetch. 2946 updates: Additional update ops to be run at function call. 2947 name: A name to help users identify what this function does. 2948 session_kwargs: Arguments to `tf.Session.run()`: 2949 `fetches`, `feed_dict`, `options`, `run_metadata`. 2950 """ 2951 2952 def __init__(self, inputs, outputs, updates=None, name=None, 2953 **session_kwargs): 2954 updates = updates or [] 2955 if not isinstance(updates, (list, tuple)): 2956 raise TypeError('`updates` in a Keras backend function ' 2957 'should be a list or tuple.') 2958 self.inputs = nest.flatten(inputs) 2959 self._outputs_structure = outputs 2960 self.outputs = cast_variables_to_tensor(nest.flatten(outputs)) 2961 # TODO(b/127668432): Consider using autograph to generate these 2962 # dependencies in call. 2963 # Index 0 = total loss or model output for `predict`. 2964 with ops.control_dependencies([self.outputs[0]]): 2965 updates_ops = [] 2966 for update in updates: 2967 if isinstance(update, tuple): 2968 p, new_p = update 2969 updates_ops.append(state_ops.assign(p, new_p)) 2970 else: 2971 # assumed already an op 2972 updates_ops.append(update) 2973 self.updates_op = control_flow_ops.group(*updates_ops) 2974 self.name = name 2975 # additional tensor substitutions 2976 self.feed_dict = session_kwargs.pop('feed_dict', None) 2977 # additional operations 2978 self.fetches = session_kwargs.pop('fetches', []) 2979 if not isinstance(self.fetches, list): 2980 self.fetches = [self.fetches] 2981 self.run_options = session_kwargs.pop('options', None) 2982 self.run_metadata = session_kwargs.pop('run_metadata', None) 2983 # The main use case of `fetches` being passed to a model is the ability 2984 # to run custom updates 2985 # This requires us to wrap fetches in `identity` ops. 2986 self.fetches = [array_ops.identity(x) for x in self.fetches] 2987 self.session_kwargs = session_kwargs 2988 # This mapping keeps track of the function that should receive the 2989 # output from a fetch in `fetches`: { fetch: function(fetch_output) } 2990 # A Callback can use this to register a function with access to the 2991 # output values for a fetch it added. 2992 self.fetch_callbacks = dict() 2993 2994 if session_kwargs: 2995 raise ValueError('Some keys in session_kwargs are not supported at this ' 2996 'time: %s' % (session_kwargs.keys(),)) 2997 2998 self._callable_fn = None 2999 self._feed_arrays = None 3000 self._feed_symbols = None 3001 self._symbol_vals = None 3002 self._fetches = None 3003 self._session = None 3004 3005 def _make_callable(self, feed_arrays, feed_symbols, symbol_vals, session): 3006 """Generates a callable that runs the graph. 3007 3008 Arguments: 3009 feed_arrays: List of input tensors to be fed Numpy arrays at runtime. 3010 feed_symbols: List of input tensors to be fed symbolic tensors at runtime. 3011 symbol_vals: List of symbolic tensors to be fed to `feed_symbols`. 3012 session: Session to use to generate the callable. 3013 3014 Returns: 3015 Function that runs the graph according to the above options. 3016 """ 3017 # Prepare callable options. 3018 callable_opts = config_pb2.CallableOptions() 3019 # Handle external-data feed. 3020 for x in feed_arrays: 3021 callable_opts.feed.append(x.name) 3022 if self.feed_dict: 3023 for key in sorted(self.feed_dict.keys()): 3024 callable_opts.feed.append(key.name) 3025 # Handle symbolic feed. 3026 for x, y in zip(feed_symbols, symbol_vals): 3027 connection = callable_opts.tensor_connection.add() 3028 if x.dtype != y.dtype: 3029 y = math_ops.cast(y, dtype=x.dtype) 3030 from_tensor = ops._as_graph_element(y) 3031 if from_tensor is None: 3032 from_tensor = y 3033 connection.from_tensor = from_tensor.name # Data tensor 3034 connection.to_tensor = x.name # Placeholder 3035 # Handle fetches. 3036 for x in self.outputs + self.fetches: 3037 callable_opts.fetch.append(x.name) 3038 # Handle updates. 3039 callable_opts.target.append(self.updates_op.name) 3040 # Handle run_options. 3041 if self.run_options: 3042 callable_opts.run_options.CopyFrom(self.run_options) 3043 # Create callable. 3044 callable_fn = session._make_callable_from_options(callable_opts) 3045 # Cache parameters corresponding to the generated callable, so that 3046 # we can detect future mismatches and refresh the callable. 3047 self._callable_fn = callable_fn 3048 self._feed_arrays = feed_arrays 3049 self._feed_symbols = feed_symbols 3050 self._symbol_vals = symbol_vals 3051 self._fetches = list(self.fetches) 3052 self._session = session 3053 3054 def _call_fetch_callbacks(self, fetches_output): 3055 for fetch, output in zip(self._fetches, fetches_output): 3056 if fetch in self.fetch_callbacks: 3057 self.fetch_callbacks[fetch](output) 3058 3059 def __call__(self, inputs): 3060 inputs = nest.flatten(inputs) 3061 3062 session = get_session(inputs) 3063 feed_arrays = [] 3064 array_vals = [] 3065 feed_symbols = [] 3066 symbol_vals = [] 3067 for tensor, value in zip(self.inputs, inputs): 3068 if value is None: 3069 continue 3070 if is_sparse(tensor): 3071 sparse_coo = value.tocoo() 3072 indices = np.concatenate((np.expand_dims(sparse_coo.row, 1), 3073 np.expand_dims(sparse_coo.col, 1)), 1) 3074 value = (indices, sparse_coo.data, sparse_coo.shape) 3075 if tensor_util.is_tensor(value): 3076 # Case: feeding symbolic tensor. 3077 feed_symbols.append(tensor) 3078 symbol_vals.append(value) 3079 else: 3080 # Case: feeding Numpy array. 3081 feed_arrays.append(tensor) 3082 # We need to do array conversion and type casting at this level, since 3083 # `callable_fn` only supports exact matches. 3084 tensor_type = dtypes_module.as_dtype(tensor.dtype) 3085 array_vals.append(np.asarray(value, 3086 dtype=tensor_type.as_numpy_dtype)) 3087 3088 if self.feed_dict: 3089 for key in sorted(self.feed_dict.keys()): 3090 array_vals.append( 3091 np.asarray(self.feed_dict[key], dtype=key.dtype.base_dtype.name)) 3092 3093 # Refresh callable if anything has changed. 3094 if (self._callable_fn is None or feed_arrays != self._feed_arrays or 3095 symbol_vals != self._symbol_vals or 3096 feed_symbols != self._feed_symbols or self.fetches != self._fetches or 3097 session != self._session): 3098 self._make_callable(feed_arrays, feed_symbols, symbol_vals, session) 3099 3100 fetched = self._callable_fn(*array_vals, 3101 run_metadata=self.run_metadata) 3102 self._call_fetch_callbacks(fetched[-len(self._fetches):]) 3103 return nest.pack_sequence_as(self._outputs_structure, 3104 fetched[:len(self.outputs)]) 3105 3106 3107class EagerExecutionFunction(object): 3108 """Helper class for constructing a TF graph function from the Keras graph. 3109 3110 Arguments: 3111 inputs: Feed placeholders to the computation graph. 3112 outputs: Output tensors to fetch. 3113 updates: Additional update ops to be run at function call. 3114 name: A name to help users identify what this function does. 3115 session_kwargs: Unsupported. 3116 """ 3117 3118 def __init__(self, inputs, outputs, updates=None, name=None): 3119 self.name = name 3120 self._outputs_structure = outputs 3121 inputs = nest.flatten(inputs) 3122 outputs = nest.flatten(outputs) 3123 3124 updates = updates or [] 3125 if not isinstance(updates, (list, tuple)): 3126 raise TypeError('`updates` in a Keras backend function ' 3127 'should be a list or tuple.') 3128 3129 if updates and not outputs: 3130 # Edge case; never happens in practice 3131 raise ValueError('Cannot create a Keras backend function with updates' 3132 ' but no outputs during eager execution.') 3133 3134 graphs = {i.graph for i in nest.flatten([inputs, outputs, updates]) 3135 if hasattr(i, 'graph')} 3136 if len(graphs) > 1: 3137 raise ValueError('Cannot create an execution function which is comprised ' 3138 'of elements from multiple graphs.') 3139 3140 source_graph = graphs.pop() 3141 global_graph = get_graph() 3142 3143 updates_ops = [] 3144 legacy_update_ops = [] 3145 for update in updates: 3146 # For legacy reasons it is allowed to pass an update as a tuple 3147 # `(variable, new_value)` (this maps to an assign op). Otherwise it 3148 # is assumed to already be an op -- we cannot control its execution 3149 # order. 3150 if isinstance(update, tuple): 3151 legacy_update_ops.append(update) 3152 else: 3153 if hasattr(update, 'op'): 3154 update = update.op 3155 updates_ops.append(update) 3156 3157 with _scratch_graph() as exec_graph: 3158 global_graph = get_graph() 3159 if source_graph not in (exec_graph, global_graph): 3160 raise ValueError('Unknown graph. Aborting.') 3161 3162 if source_graph is global_graph and exec_graph is not global_graph: 3163 init_tensors = ( 3164 outputs + updates_ops + [p for [p, _] in legacy_update_ops] + 3165 [p_new for [_, p_new] in legacy_update_ops 3166 if isinstance(p_new, ops.Tensor)]) 3167 lifted_map = lift_to_graph.lift_to_graph( 3168 init_tensors=init_tensors, graph=exec_graph, sources=inputs, 3169 add_sources=True, handle_captures=True, base_graph=source_graph) 3170 3171 inputs = [lifted_map[i] for i in inputs] 3172 outputs = [lifted_map[i] for i in outputs] 3173 updates_ops = [lifted_map[i] for i in updates_ops] 3174 legacy_update_ops = [(lifted_map[p], lifted_map.get(p_new, p_new)) 3175 for p, p_new in legacy_update_ops] 3176 3177 # Consolidate updates 3178 with exec_graph.as_default(): 3179 outputs = cast_variables_to_tensor(outputs) 3180 with ops.control_dependencies(outputs): 3181 for p, p_new in legacy_update_ops: 3182 updates_ops.append(state_ops.assign(p, p_new)) 3183 3184 self.inputs, self.outputs = inputs, outputs 3185 with ops.control_dependencies(updates_ops): 3186 self.outputs[0] = array_ops.identity(self.outputs[0]) 3187 3188 exec_graph.inputs = self.inputs + list(exec_graph.captures.values()) 3189 exec_graph.outputs = self.outputs 3190 graph_fn = eager_function.ConcreteFunction(exec_graph) 3191 3192 graph_fn._num_positional_args = len(self.inputs) 3193 graph_fn._arg_keywords = [] 3194 self._graph_fn = graph_fn 3195 3196 # Handle placeholders with default 3197 # (treated as required placeholder by graph functions) 3198 self._placeholder_default_values = {} 3199 with exec_graph.as_default(): 3200 for x in self.inputs: 3201 if x.op.type == 'PlaceholderWithDefault': 3202 self._placeholder_default_values[x] = tensor_util.constant_value( 3203 x.op.inputs[0]) 3204 3205 def __call__(self, inputs): 3206 inputs = nest.flatten(inputs) 3207 converted_inputs = [] 3208 for tensor, value in zip(self.inputs, inputs): 3209 if value is None: 3210 # Assume `value` is a placeholder with default 3211 value = self._placeholder_default_values.get(tensor, None) 3212 if value is None: 3213 raise ValueError( 3214 'You must feed a value for placeholder %s' % (tensor,)) 3215 if not isinstance(value, ops.Tensor): 3216 value = ops.convert_to_tensor(value, dtype=tensor.dtype) 3217 if value.dtype != tensor.dtype: 3218 # Temporary workaround due to `convert_to_tensor` not casting floats. 3219 # See b/119637405 3220 value = math_ops.cast(value, tensor.dtype) 3221 converted_inputs.append(value) 3222 outputs = self._graph_fn(*converted_inputs) 3223 return nest.pack_sequence_as(self._outputs_structure, 3224 [x.numpy() for x in outputs]) 3225 3226 3227@keras_export('keras.backend.function') 3228def function(inputs, outputs, updates=None, name=None, **kwargs): 3229 """Instantiates a Keras function. 3230 3231 Arguments: 3232 inputs: List of placeholder tensors. 3233 outputs: List of output tensors. 3234 updates: List of update ops. 3235 name: String, name of function. 3236 **kwargs: Passed to `tf.Session.run`. 3237 3238 Returns: 3239 Output values as Numpy arrays. 3240 3241 Raises: 3242 ValueError: if invalid kwargs are passed in or if in eager execution. 3243 """ 3244 if ops.executing_eagerly_outside_functions(): 3245 if kwargs: 3246 raise ValueError('Session keyword arguments are not support during ' 3247 'eager execution. You passed: %s' % (kwargs,)) 3248 return EagerExecutionFunction(inputs, outputs, updates=updates, name=name) 3249 3250 if kwargs: 3251 for key in kwargs: 3252 if (key not in tf_inspect.getfullargspec(session_module.Session.run)[0] 3253 and key not in ['inputs', 'outputs', 'updates', 'name']): 3254 msg = ('Invalid argument "%s" passed to K.function with TensorFlow ' 3255 'backend') % key 3256 raise ValueError(msg) 3257 return GraphExecutionFunction(inputs, outputs, updates=updates, **kwargs) 3258 3259 3260@keras_export('keras.backend.gradients') 3261def gradients(loss, variables): 3262 """Returns the gradients of `loss` w.r.t. `variables`. 3263 3264 Arguments: 3265 loss: Scalar tensor to minimize. 3266 variables: List of variables. 3267 3268 Returns: 3269 A gradients tensor. 3270 """ 3271 return gradients_module.gradients( 3272 loss, variables, colocate_gradients_with_ops=True) 3273 3274 3275@keras_export('keras.backend.stop_gradient') 3276def stop_gradient(variables): 3277 """Returns `variables` but with zero gradient w.r.t. every other variable. 3278 3279 Arguments: 3280 variables: Tensor or list of tensors to consider constant with respect 3281 to any other variable. 3282 3283 3284 Returns: 3285 A single tensor or a list of tensors (depending on the passed argument) 3286 that has no gradient with respect to any other variable. 3287 """ 3288 if isinstance(variables, (list, tuple)): 3289 return map(array_ops.stop_gradient, variables) 3290 return array_ops.stop_gradient(variables) 3291 3292 3293# CONTROL FLOW 3294 3295 3296@keras_export('keras.backend.rnn') 3297def rnn(step_function, 3298 inputs, 3299 initial_states, 3300 go_backwards=False, 3301 mask=None, 3302 constants=None, 3303 unroll=False, 3304 input_length=None, 3305 time_major=False, 3306 zero_output_for_mask=False): 3307 """Iterates over the time dimension of a tensor. 3308 3309 Arguments: 3310 step_function: RNN step function. 3311 Args; 3312 input; Tensor with shape `(samples, ...)` (no time dimension), 3313 representing input for the batch of samples at a certain 3314 time step. 3315 states; List of tensors. 3316 Returns; 3317 output; Tensor with shape `(samples, output_dim)` 3318 (no time dimension). 3319 new_states; List of tensors, same length and shapes 3320 as 'states'. The first state in the list must be the 3321 output tensor at the previous timestep. 3322 inputs: Tensor of temporal data of shape `(samples, time, ...)` 3323 (at least 3D), or nested tensors, and each of which has shape 3324 `(samples, time, ...)`. 3325 initial_states: Tensor with shape `(samples, state_size)` 3326 (no time dimension), containing the initial values for the states used 3327 in the step function. In the case that state_size is in a nested 3328 shape, the shape of initial_states will also follow the nested 3329 structure. 3330 go_backwards: Boolean. If True, do the iteration over the time 3331 dimension in reverse order and return the reversed sequence. 3332 mask: Binary tensor with shape `(samples, time, 1)`, 3333 with a zero for every element that is masked. 3334 constants: List of constant values passed at each step. 3335 unroll: Whether to unroll the RNN or to use a symbolic `while_loop`. 3336 input_length: If specified, assume time dimension is of this length. 3337 time_major: Boolean. If true, the inputs and outputs will be in shape 3338 `(timesteps, batch, ...)`, whereas in the False case, it will be 3339 `(batch, timesteps, ...)`. Using `time_major = True` is a bit more 3340 efficient because it avoids transposes at the beginning and end of the 3341 RNN calculation. However, most TensorFlow data is batch-major, so by 3342 default this function accepts input and emits output in batch-major 3343 form. 3344 zero_output_for_mask: Boolean. If True, the output for masked timestep 3345 will be zeros, whereas in the False case, output from previous 3346 timestep is returned. 3347 Returns: 3348 A tuple, `(last_output, outputs, new_states)`. 3349 last_output: the latest output of the rnn, of shape `(samples, ...)` 3350 outputs: tensor with shape `(samples, time, ...)` where each 3351 entry `outputs[s, t]` is the output of the step function 3352 at time `t` for sample `s`. 3353 new_states: list of tensors, latest states returned by 3354 the step function, of shape `(samples, ...)`. 3355 3356 Raises: 3357 ValueError: if input dimension is less than 3. 3358 ValueError: if `unroll` is `True` but input timestep is not a fixed 3359 number. 3360 ValueError: if `mask` is provided (not `None`) but states is not provided 3361 (`len(states)` == 0). 3362 """ 3363 3364 def swap_batch_timestep(input_t): 3365 # Swap the batch and timestep dim for the incoming tensor. 3366 axes = list(range(len(input_t.shape))) 3367 axes[0], axes[1] = 1, 0 3368 return array_ops.transpose(input_t, axes) 3369 3370 if not time_major: 3371 inputs = nest.map_structure(swap_batch_timestep, inputs) 3372 3373 flatted_inputs = nest.flatten(inputs) 3374 time_steps = flatted_inputs[0].shape[0] 3375 batch = flatted_inputs[0].shape[1] 3376 time_steps_t = array_ops.shape(flatted_inputs[0])[0] 3377 3378 for input_ in flatted_inputs: 3379 input_.get_shape().with_rank_at_least(3) 3380 3381 if mask is not None: 3382 if mask.dtype != dtypes_module.bool: 3383 mask = math_ops.cast(mask, dtypes_module.bool) 3384 if len(mask.shape) == 2: 3385 mask = expand_dims(mask) 3386 if not time_major: 3387 mask = swap_batch_timestep(mask) 3388 3389 if constants is None: 3390 constants = [] 3391 3392 # tf.where needs its condition tensor to be the same shape as its two 3393 # result tensors, but in our case the condition (mask) tensor is 3394 # (nsamples, 1), and inputs are (nsamples, ndimensions) or even more. 3395 # So we need to broadcast the mask to match the shape of inputs. 3396 # That's what the tile call does, it just repeats the mask along its 3397 # second dimension n times. 3398 def _expand_mask(mask_t, input_t, fixed_dim=1): 3399 assert not nest.is_sequence(mask_t) 3400 assert not nest.is_sequence(input_t) 3401 rank_diff = len(input_t.shape) - len(mask_t.shape) 3402 for _ in range(rank_diff): 3403 mask_t = array_ops.expand_dims(mask_t, -1) 3404 multiples = [1] * fixed_dim + input_t.shape.as_list()[fixed_dim:] 3405 return array_ops.tile(mask_t, multiples) 3406 3407 if unroll: 3408 if not time_steps: 3409 raise ValueError('Unrolling requires a fixed number of timesteps.') 3410 states = tuple(initial_states) 3411 successive_states = [] 3412 successive_outputs = [] 3413 3414 # Process the input tensors. The input tensor need to be split on the 3415 # time_step dim, and reverse if go_backwards is True. In the case of nested 3416 # input, the input is flattened and then transformed individually. 3417 # The result of this will be a tuple of lists, each of the item in tuple is 3418 # list of the tensor with shape (batch, feature) 3419 def _process_single_input_t(input_t): 3420 input_t = array_ops.unstack(input_t) # unstack for time_step dim 3421 if go_backwards: 3422 input_t.reverse() 3423 return input_t 3424 3425 if nest.is_sequence(inputs): 3426 processed_input = nest.map_structure(_process_single_input_t, inputs) 3427 else: 3428 processed_input = (_process_single_input_t(inputs),) 3429 3430 def _get_input_tensor(time): 3431 inp = [t_[time] for t_ in processed_input] 3432 return nest.pack_sequence_as(inputs, inp) 3433 3434 if mask is not None: 3435 mask_list = array_ops.unstack(mask) 3436 if go_backwards: 3437 mask_list.reverse() 3438 3439 for i in range(time_steps): 3440 inp = _get_input_tensor(i) 3441 mask_t = mask_list[i] 3442 output, new_states = step_function(inp, 3443 tuple(states) + tuple(constants)) 3444 tiled_mask_t = _expand_mask(mask_t, output) 3445 3446 if not successive_outputs: 3447 prev_output = zeros_like(output) 3448 else: 3449 prev_output = successive_outputs[-1] 3450 3451 output = array_ops.where(tiled_mask_t, output, prev_output) 3452 3453 return_states = [] 3454 for state, new_state in zip(states, new_states): 3455 # (see earlier comment for tile explanation) 3456 tiled_mask_t = _expand_mask(mask_t, new_state) 3457 return_states.append(array_ops.where(tiled_mask_t, new_state, state)) 3458 states = return_states 3459 successive_outputs.append(output) 3460 successive_states.append(states) 3461 last_output = successive_outputs[-1] 3462 new_states = successive_states[-1] 3463 outputs = array_ops.stack(successive_outputs) 3464 3465 if zero_output_for_mask: 3466 last_output = array_ops.where( 3467 _expand_mask(mask_list[-1], last_output), 3468 last_output, 3469 zeros_like(last_output)) 3470 outputs = array_ops.where( 3471 _expand_mask(mask, outputs, fixed_dim=2), 3472 outputs, 3473 zeros_like(outputs)) 3474 3475 else: 3476 for i in range(time_steps): 3477 inp = _get_input_tensor(i) 3478 output, states = step_function(inp, tuple(states) + tuple(constants)) 3479 successive_outputs.append(output) 3480 successive_states.append(states) 3481 last_output = successive_outputs[-1] 3482 new_states = successive_states[-1] 3483 outputs = array_ops.stack(successive_outputs) 3484 3485 else: 3486 states = tuple(initial_states) 3487 3488 # Create input tensor array, if the inputs is nested tensors, then it will 3489 # be flattened first, and tensor array will be created one per flattened 3490 # tensor. 3491 input_ta = tuple( 3492 tensor_array_ops.TensorArray( 3493 dtype=inp.dtype, 3494 size=time_steps_t, 3495 tensor_array_name='input_ta_%s' % i) 3496 for i, inp in enumerate(flatted_inputs)) 3497 input_ta = tuple( 3498 ta.unstack(input_) if not go_backwards else ta 3499 .unstack(reverse(input_, 0)) 3500 for ta, input_ in zip(input_ta, flatted_inputs)) 3501 3502 # Get the time(0) input and compute the output for that, the output will be 3503 # used to determine the dtype of output tensor array. Don't read from 3504 # input_ta due to TensorArray clear_after_read default to True. 3505 input_time_zero = nest.pack_sequence_as(inputs, 3506 [inp[0] for inp in flatted_inputs]) 3507 # output_time_zero is used to determine the cell output shape and its dtype. 3508 # the value is discarded. 3509 output_time_zero, _ = step_function(input_time_zero, 3510 initial_states + constants) 3511 output_ta = tuple( 3512 tensor_array_ops.TensorArray( 3513 dtype=out.dtype, 3514 size=time_steps_t, 3515 tensor_array_name='output_ta_%s' % i) 3516 for i, out in enumerate(nest.flatten(output_time_zero))) 3517 3518 time = constant_op.constant(0, dtype='int32', name='time') 3519 3520 while_loop_kwargs = { 3521 'cond': lambda time, *_: time < time_steps_t, 3522 'maximum_iterations': input_length, 3523 'parallel_iterations': 32, 3524 'swap_memory': True, 3525 } 3526 3527 if mask is not None: 3528 if not states: 3529 raise ValueError('No initial states provided! ' 3530 'When using masking in an RNN, you should ' 3531 'provide initial states ' 3532 '(and your step function should return ' 3533 'as its first state at time `t` ' 3534 'the output at time `t-1`).') 3535 if go_backwards: 3536 mask = reverse(mask, 0) 3537 3538 mask_ta = tensor_array_ops.TensorArray( 3539 dtype=dtypes_module.bool, 3540 size=time_steps_t, 3541 tensor_array_name='mask_ta') 3542 mask_ta = mask_ta.unstack(mask) 3543 3544 # Mask for the T output will be base on the output of T - 1. In the case 3545 # T = 0, a zero filled tensor will be used. 3546 flat_zero_output = tuple(array_ops.zeros_like(o) 3547 for o in nest.flatten(output_time_zero)) 3548 def _step(time, output_ta_t, prev_output, *states): 3549 """RNN step function. 3550 3551 Arguments: 3552 time: Current timestep value. 3553 output_ta_t: TensorArray. 3554 prev_output: tuple of outputs from time - 1. 3555 *states: List of states. 3556 3557 Returns: 3558 Tuple: `(time + 1, output_ta_t, output) + tuple(new_states)` 3559 """ 3560 current_input = tuple(ta.read(time) for ta in input_ta) 3561 # maybe set shape. 3562 current_input = nest.pack_sequence_as(inputs, current_input) 3563 mask_t = mask_ta.read(time) 3564 output, new_states = step_function(current_input, 3565 tuple(states) + tuple(constants)) 3566 # mask output 3567 flat_output = nest.flatten(output) 3568 flat_mask_output = (flat_zero_output if zero_output_for_mask 3569 else nest.flatten(prev_output)) 3570 tiled_mask_t = tuple(_expand_mask(mask_t, o) for o in flat_output) 3571 flat_new_output = tuple( 3572 array_ops.where(m, o, zo) for m, o, zo in zip( 3573 tiled_mask_t, flat_output, flat_mask_output)) 3574 3575 # mask states 3576 flat_state = nest.flatten(states) 3577 flat_new_state = nest.flatten(new_states) 3578 for state, new_state in zip(flat_state, flat_new_state): 3579 new_state.set_shape(state.shape) 3580 tiled_mask_t = tuple(_expand_mask(mask_t, s) for s in flat_state) 3581 flat_final_state = tuple( 3582 array_ops.where(m, s, ps) 3583 for m, s, ps in zip(tiled_mask_t, flat_new_state, flat_state)) 3584 new_states = nest.pack_sequence_as(new_states, flat_final_state) 3585 3586 output_ta_t = tuple( 3587 ta.write(time, out) 3588 for ta, out in zip(output_ta_t, flat_new_output)) 3589 return (time + 1, output_ta_t, 3590 tuple(flat_new_output)) + tuple(new_states) 3591 3592 final_outputs = control_flow_ops.while_loop( 3593 body=_step, 3594 loop_vars=(time, output_ta, flat_zero_output) + states, 3595 **while_loop_kwargs) 3596 # Skip final_outputs[2] which is the output for final timestep. 3597 new_states = final_outputs[3:] 3598 else: 3599 def _step(time, output_ta_t, *states): 3600 """RNN step function. 3601 3602 Arguments: 3603 time: Current timestep value. 3604 output_ta_t: TensorArray. 3605 *states: List of states. 3606 3607 Returns: 3608 Tuple: `(time + 1,output_ta_t) + tuple(new_states)` 3609 """ 3610 current_input = tuple(ta.read(time) for ta in input_ta) 3611 current_input = nest.pack_sequence_as(inputs, current_input) 3612 output, new_states = step_function(current_input, 3613 tuple(states) + tuple(constants)) 3614 flat_state = nest.flatten(states) 3615 flat_new_state = nest.flatten(new_states) 3616 for state, new_state in zip(flat_state, flat_new_state): 3617 new_state.set_shape(state.shape) 3618 3619 flat_output = nest.flatten(output) 3620 output_ta_t = tuple( 3621 ta.write(time, out) for ta, out in zip(output_ta_t, flat_output)) 3622 new_states = nest.pack_sequence_as(initial_states, flat_new_state) 3623 return (time + 1, output_ta_t) + tuple(new_states) 3624 3625 final_outputs = control_flow_ops.while_loop( 3626 body=_step, 3627 loop_vars=(time, output_ta) + states, 3628 **while_loop_kwargs) 3629 new_states = final_outputs[2:] 3630 3631 output_ta = final_outputs[1] 3632 3633 outputs = tuple(o.stack() for o in output_ta) 3634 last_output = tuple(o[-1] for o in outputs) 3635 3636 outputs = nest.pack_sequence_as(output_time_zero, outputs) 3637 last_output = nest.pack_sequence_as(output_time_zero, last_output) 3638 3639 # static shape inference 3640 def set_shape(output_): 3641 shape = output_.shape.as_list() 3642 shape[0] = time_steps 3643 shape[1] = batch 3644 output_.set_shape(shape) 3645 return output_ 3646 3647 outputs = nest.map_structure(set_shape, outputs) 3648 3649 if not time_major: 3650 outputs = nest.map_structure(swap_batch_timestep, outputs) 3651 3652 return last_output, outputs, new_states 3653 3654 3655@keras_export('keras.backend.switch') 3656def switch(condition, then_expression, else_expression): 3657 """Switches between two operations depending on a scalar value. 3658 3659 Note that both `then_expression` and `else_expression` 3660 should be symbolic tensors of the *same shape*. 3661 3662 Arguments: 3663 condition: tensor (`int` or `bool`). 3664 then_expression: either a tensor, or a callable that returns a tensor. 3665 else_expression: either a tensor, or a callable that returns a tensor. 3666 3667 Returns: 3668 The selected tensor. 3669 3670 Raises: 3671 ValueError: If rank of `condition` is greater than rank of expressions. 3672 """ 3673 if condition.dtype != dtypes_module.bool: 3674 condition = math_ops.cast(condition, 'bool') 3675 cond_ndim = ndim(condition) 3676 if not cond_ndim: 3677 if not callable(then_expression): 3678 3679 def then_expression_fn(): 3680 return then_expression 3681 else: 3682 then_expression_fn = then_expression 3683 if not callable(else_expression): 3684 3685 def else_expression_fn(): 3686 return else_expression 3687 else: 3688 else_expression_fn = else_expression 3689 x = control_flow_ops.cond(condition, then_expression_fn, else_expression_fn) 3690 else: 3691 # tf.where needs its condition tensor 3692 # to be the same shape as its two 3693 # result tensors 3694 if callable(then_expression): 3695 then_expression = then_expression() 3696 if callable(else_expression): 3697 else_expression = else_expression() 3698 expr_ndim = ndim(then_expression) 3699 if cond_ndim > expr_ndim: 3700 raise ValueError('Rank of `condition` should be less than or' 3701 ' equal to rank of `then_expression` and ' 3702 '`else_expression`. ndim(condition)=' + str(cond_ndim) + 3703 ', ndim(then_expression)' 3704 '=' + str(expr_ndim)) 3705 if cond_ndim > 1: 3706 ndim_diff = expr_ndim - cond_ndim 3707 cond_shape = array_ops.concat( 3708 [array_ops.shape(condition), [1] * ndim_diff], axis=0) 3709 condition = array_ops.reshape(condition, cond_shape) 3710 expr_shape = array_ops.shape(then_expression) 3711 shape_diff = expr_shape - cond_shape 3712 tile_shape = array_ops.where(shape_diff > 0, expr_shape, 3713 array_ops.ones_like(expr_shape)) 3714 condition = array_ops.tile(condition, tile_shape) 3715 x = array_ops.where(condition, then_expression, else_expression) 3716 return x 3717 3718 3719@keras_export('keras.backend.in_train_phase') 3720def in_train_phase(x, alt, training=None): 3721 """Selects `x` in train phase, and `alt` otherwise. 3722 3723 Note that `alt` should have the *same shape* as `x`. 3724 3725 Arguments: 3726 x: What to return in train phase 3727 (tensor or callable that returns a tensor). 3728 alt: What to return otherwise 3729 (tensor or callable that returns a tensor). 3730 training: Optional scalar tensor 3731 (or Python boolean, or Python integer) 3732 specifying the learning phase. 3733 3734 Returns: 3735 Either `x` or `alt` based on the `training` flag. 3736 the `training` flag defaults to `K.learning_phase()`. 3737 """ 3738 if training is None: 3739 training = learning_phase() 3740 3741 if training == 1 or training is True: 3742 if callable(x): 3743 return x() 3744 else: 3745 return x 3746 3747 elif training == 0 or training is False: 3748 if callable(alt): 3749 return alt() 3750 else: 3751 return alt 3752 3753 # else: assume learning phase is a placeholder tensor. 3754 x = switch(training, x, alt) 3755 return x 3756 3757 3758@keras_export('keras.backend.in_test_phase') 3759def in_test_phase(x, alt, training=None): 3760 """Selects `x` in test phase, and `alt` otherwise. 3761 3762 Note that `alt` should have the *same shape* as `x`. 3763 3764 Arguments: 3765 x: What to return in test phase 3766 (tensor or callable that returns a tensor). 3767 alt: What to return otherwise 3768 (tensor or callable that returns a tensor). 3769 training: Optional scalar tensor 3770 (or Python boolean, or Python integer) 3771 specifying the learning phase. 3772 3773 Returns: 3774 Either `x` or `alt` based on `K.learning_phase`. 3775 """ 3776 return in_train_phase(alt, x, training=training) 3777 3778 3779# NN OPERATIONS 3780 3781 3782@keras_export('keras.backend.relu') 3783def relu(x, alpha=0., max_value=None, threshold=0): 3784 """Rectified linear unit. 3785 3786 With default values, it returns element-wise `max(x, 0)`. 3787 3788 Otherwise, it follows: 3789 `f(x) = max_value` for `x >= max_value`, 3790 `f(x) = x` for `threshold <= x < max_value`, 3791 `f(x) = alpha * (x - threshold)` otherwise. 3792 3793 Arguments: 3794 x: A tensor or variable. 3795 alpha: A scalar, slope of negative section (default=`0.`). 3796 max_value: float. Saturation threshold. 3797 threshold: float. Threshold value for thresholded activation. 3798 3799 Returns: 3800 A tensor. 3801 """ 3802 3803 if alpha != 0.: 3804 if max_value is None and threshold == 0: 3805 return nn.leaky_relu(x, alpha=alpha) 3806 3807 if threshold != 0: 3808 negative_part = nn.relu(-x + threshold) 3809 else: 3810 negative_part = nn.relu(-x) 3811 3812 clip_max = max_value is not None 3813 3814 if threshold != 0: 3815 # computes x for x > threshold else 0 3816 x = x * math_ops.cast(math_ops.greater(x, threshold), floatx()) 3817 elif max_value == 6: 3818 # if no threshold, then can use nn.relu6 native TF op for performance 3819 x = nn.relu6(x) 3820 clip_max = False 3821 else: 3822 x = nn.relu(x) 3823 3824 if clip_max: 3825 max_value = _to_tensor(max_value, x.dtype.base_dtype) 3826 zero = _to_tensor(0., x.dtype.base_dtype) 3827 x = clip_ops.clip_by_value(x, zero, max_value) 3828 3829 if alpha != 0.: 3830 alpha = _to_tensor(alpha, x.dtype.base_dtype) 3831 x -= alpha * negative_part 3832 return x 3833 3834 3835@keras_export('keras.backend.elu') 3836def elu(x, alpha=1.): 3837 """Exponential linear unit. 3838 3839 Arguments: 3840 x: A tensor or variable to compute the activation function for. 3841 alpha: A scalar, slope of negative section. 3842 3843 Returns: 3844 A tensor. 3845 """ 3846 res = nn.elu(x) 3847 if alpha == 1: 3848 return res 3849 else: 3850 return array_ops.where(x > 0, res, alpha * res) 3851 3852 3853@keras_export('keras.backend.softmax') 3854def softmax(x, axis=-1): 3855 """Softmax of a tensor. 3856 3857 Arguments: 3858 x: A tensor or variable. 3859 axis: The dimension softmax would be performed on. 3860 The default is -1 which indicates the last dimension. 3861 3862 Returns: 3863 A tensor. 3864 """ 3865 return nn.softmax(x, axis=axis) 3866 3867 3868@keras_export('keras.backend.softplus') 3869def softplus(x): 3870 """Softplus of a tensor. 3871 3872 Arguments: 3873 x: A tensor or variable. 3874 3875 Returns: 3876 A tensor. 3877 """ 3878 return nn.softplus(x) 3879 3880 3881@keras_export('keras.backend.softsign') 3882def softsign(x): 3883 """Softsign of a tensor. 3884 3885 Arguments: 3886 x: A tensor or variable. 3887 3888 Returns: 3889 A tensor. 3890 """ 3891 return nn.softsign(x) 3892 3893 3894@keras_export('keras.backend.categorical_crossentropy') 3895def categorical_crossentropy(target, output, from_logits=False, axis=-1): 3896 """Categorical crossentropy between an output tensor and a target tensor. 3897 3898 Arguments: 3899 target: A tensor of the same shape as `output`. 3900 output: A tensor resulting from a softmax 3901 (unless `from_logits` is True, in which 3902 case `output` is expected to be the logits). 3903 from_logits: Boolean, whether `output` is the 3904 result of a softmax, or is a tensor of logits. 3905 axis: Int specifying the channels axis. `axis=-1` corresponds to data 3906 format `channels_last', and `axis=1` corresponds to data format 3907 `channels_first`. 3908 3909 Returns: 3910 Output tensor. 3911 3912 Raises: 3913 ValueError: if `axis` is neither -1 nor one of the axes of `output`. 3914 """ 3915 if not from_logits: 3916 if (isinstance(output, (ops.EagerTensor, variables_module.Variable)) or 3917 output.op.type != 'Softmax'): 3918 axis = axis % len(output.shape) 3919 # scale preds so that the class probas of each sample sum to 1 3920 output = output / math_ops.reduce_sum(output, axis, True) 3921 # Compute cross entropy from probabilities. 3922 epsilon_ = _to_tensor(epsilon(), output.dtype.base_dtype) 3923 output = clip_ops.clip_by_value(output, epsilon_, 1. - epsilon_) 3924 return -math_ops.reduce_sum(target * math_ops.log(output), axis) 3925 else: 3926 # When softmax activation function is used for output operation, we 3927 # use logits from the softmax function directly to compute loss in order 3928 # to prevent collapsing zero when training. 3929 # See b/117284466 3930 assert len(output.op.inputs) == 1 3931 output = output.op.inputs[0] 3932 return nn.softmax_cross_entropy_with_logits_v2(labels=target, logits=output) 3933 3934 3935@keras_export('keras.backend.sparse_categorical_crossentropy') 3936def sparse_categorical_crossentropy(target, output, from_logits=False, axis=-1): 3937 """Categorical crossentropy with integer targets. 3938 3939 Arguments: 3940 target: An integer tensor. 3941 output: A tensor resulting from a softmax 3942 (unless `from_logits` is True, in which 3943 case `output` is expected to be the logits). 3944 from_logits: Boolean, whether `output` is the 3945 result of a softmax, or is a tensor of logits. 3946 axis: Int specifying the channels axis. `axis=-1` corresponds to data 3947 format `channels_last', and `axis=1` corresponds to data format 3948 `channels_first`. 3949 3950 Returns: 3951 Output tensor. 3952 3953 Raises: 3954 ValueError: if `axis` is neither -1 nor one of the axes of `output`. 3955 """ 3956 if not from_logits: 3957 if (isinstance(output, (ops.EagerTensor, variables_module.Variable)) or 3958 output.op.type != 'Softmax'): 3959 epsilon_ = _to_tensor(epsilon(), output.dtype.base_dtype) 3960 output = clip_ops.clip_by_value(output, epsilon_, 1 - epsilon_) 3961 output = math_ops.log(output) 3962 else: 3963 # When softmax activation function is used for output operation, we 3964 # use logits from the softmax function directly to compute loss in order 3965 # to prevent collapsing zero when training. 3966 # See b/117284466 3967 assert len(output.op.inputs) == 1 3968 output = output.op.inputs[0] 3969 3970 rank = len(output.shape) 3971 axis = axis % rank 3972 if axis != rank - 1: 3973 permutation = list(range(axis)) + list(range(axis + 1, rank)) + [axis] 3974 output = array_ops.transpose(output, perm=permutation) 3975 3976 output_shape = output.shape 3977 targets = cast(flatten(target), 'int64') 3978 logits = array_ops.reshape(output, [-1, int(output_shape[-1])]) 3979 res = nn.sparse_softmax_cross_entropy_with_logits( 3980 labels=targets, logits=logits) 3981 if len(output_shape) >= 3: 3982 # If our output includes timesteps or spatial dimensions we need to reshape 3983 return array_ops.reshape(res, array_ops.shape(output)[:-1]) 3984 else: 3985 return res 3986 3987 3988@keras_export('keras.backend.binary_crossentropy') 3989def binary_crossentropy(target, output, from_logits=False): 3990 """Binary crossentropy between an output tensor and a target tensor. 3991 3992 Arguments: 3993 target: A tensor with the same shape as `output`. 3994 output: A tensor. 3995 from_logits: Whether `output` is expected to be a logits tensor. 3996 By default, we consider that `output` 3997 encodes a probability distribution. 3998 3999 Returns: 4000 A tensor. 4001 """ 4002 if not from_logits: 4003 if (isinstance(output, (ops.EagerTensor, variables_module.Variable)) or 4004 output.op.type != 'Sigmoid'): 4005 epsilon_ = _to_tensor(epsilon(), output.dtype.base_dtype) 4006 output = clip_ops.clip_by_value(output, epsilon_, 1. - epsilon_) 4007 4008 # Compute cross entropy from probabilities. 4009 bce = target * math_ops.log(output + epsilon()) 4010 bce += (1 - target) * math_ops.log(1 - output + epsilon()) 4011 return -bce 4012 else: 4013 # When sigmoid activation function is used for output operation, we 4014 # use logits from the sigmoid function directly to compute loss in order 4015 # to prevent collapsing zero when training. 4016 assert len(output.op.inputs) == 1 4017 output = output.op.inputs[0] 4018 return nn.sigmoid_cross_entropy_with_logits(labels=target, logits=output) 4019 4020 4021@keras_export('keras.backend.sigmoid') 4022def sigmoid(x): 4023 """Element-wise sigmoid. 4024 4025 Arguments: 4026 x: A tensor or variable. 4027 4028 Returns: 4029 A tensor. 4030 """ 4031 return nn.sigmoid(x) 4032 4033 4034@keras_export('keras.backend.hard_sigmoid') 4035def hard_sigmoid(x): 4036 """Segment-wise linear approximation of sigmoid. 4037 4038 Faster than sigmoid. 4039 Returns `0.` if `x < -2.5`, `1.` if `x > 2.5`. 4040 In `-2.5 <= x <= 2.5`, returns `0.2 * x + 0.5`. 4041 4042 Arguments: 4043 x: A tensor or variable. 4044 4045 Returns: 4046 A tensor. 4047 """ 4048 x = (0.2 * x) + 0.5 4049 zero = _to_tensor(0., x.dtype.base_dtype) 4050 one = _to_tensor(1., x.dtype.base_dtype) 4051 x = clip_ops.clip_by_value(x, zero, one) 4052 return x 4053 4054 4055@keras_export('keras.backend.tanh') 4056def tanh(x): 4057 """Element-wise tanh. 4058 4059 Arguments: 4060 x: A tensor or variable. 4061 4062 Returns: 4063 A tensor. 4064 """ 4065 return nn.tanh(x) 4066 4067 4068@keras_export('keras.backend.dropout') 4069def dropout(x, level, noise_shape=None, seed=None): 4070 """Sets entries in `x` to zero at random, while scaling the entire tensor. 4071 4072 Arguments: 4073 x: tensor 4074 level: fraction of the entries in the tensor 4075 that will be set to 0. 4076 noise_shape: shape for randomly generated keep/drop flags, 4077 must be broadcastable to the shape of `x` 4078 seed: random seed to ensure determinism. 4079 4080 Returns: 4081 A tensor. 4082 """ 4083 if seed is None: 4084 seed = np.random.randint(10e6) 4085 return nn.dropout_v2(x, rate=level, noise_shape=noise_shape, seed=seed) 4086 4087 4088@keras_export('keras.backend.l2_normalize') 4089def l2_normalize(x, axis=None): 4090 """Normalizes a tensor wrt the L2 norm alongside the specified axis. 4091 4092 Arguments: 4093 x: Tensor or variable. 4094 axis: axis along which to perform normalization. 4095 4096 Returns: 4097 A tensor. 4098 """ 4099 return nn.l2_normalize(x, axis=axis) 4100 4101 4102@keras_export('keras.backend.in_top_k') 4103def in_top_k(predictions, targets, k): 4104 """Returns whether the `targets` are in the top `k` `predictions`. 4105 4106 Arguments: 4107 predictions: A tensor of shape `(batch_size, classes)` and type `float32`. 4108 targets: A 1D tensor of length `batch_size` and type `int32` or `int64`. 4109 k: An `int`, number of top elements to consider. 4110 4111 Returns: 4112 A 1D tensor of length `batch_size` and type `bool`. 4113 `output[i]` is `True` if `predictions[i, targets[i]]` is within top-`k` 4114 values of `predictions[i]`. 4115 """ 4116 return nn.in_top_k(predictions, targets, k) 4117 4118 4119# CONVOLUTIONS 4120 4121 4122def _preprocess_conv1d_input(x, data_format): 4123 """Transpose and cast the input before the conv1d. 4124 4125 Arguments: 4126 x: input tensor. 4127 data_format: string, `"channels_last"` or `"channels_first"`. 4128 4129 Returns: 4130 A tensor. 4131 """ 4132 tf_data_format = 'NWC' # to pass TF Conv2dNative operations 4133 if data_format == 'channels_first': 4134 if not _has_nchw_support(): 4135 x = array_ops.transpose(x, (0, 2, 1)) # NCW -> NWC 4136 else: 4137 tf_data_format = 'NCW' 4138 return x, tf_data_format 4139 4140 4141def _preprocess_conv2d_input(x, data_format, force_transpose=False): 4142 """Transpose and cast the input before the conv2d. 4143 4144 Arguments: 4145 x: input tensor. 4146 data_format: string, `"channels_last"` or `"channels_first"`. 4147 force_transpose: Boolean. If True, the input will always be transposed 4148 from NCHW to NHWC if `data_format` is `"channels_first"`. 4149 If False, the transposition only occurs on CPU (GPU ops are 4150 assumed to support NCHW). 4151 4152 Returns: 4153 A tensor. 4154 """ 4155 tf_data_format = 'NHWC' 4156 if data_format == 'channels_first': 4157 if not _has_nchw_support() or force_transpose: 4158 x = array_ops.transpose(x, (0, 2, 3, 1)) # NCHW -> NHWC 4159 else: 4160 tf_data_format = 'NCHW' 4161 return x, tf_data_format 4162 4163 4164def _preprocess_conv3d_input(x, data_format): 4165 """Transpose and cast the input before the conv3d. 4166 4167 Arguments: 4168 x: input tensor. 4169 data_format: string, `"channels_last"` or `"channels_first"`. 4170 4171 Returns: 4172 A tensor. 4173 """ 4174 tf_data_format = 'NDHWC' 4175 if data_format == 'channels_first': 4176 if not _has_nchw_support(): 4177 x = array_ops.transpose(x, (0, 2, 3, 4, 1)) 4178 else: 4179 tf_data_format = 'NCDHW' 4180 return x, tf_data_format 4181 4182 4183def _preprocess_padding(padding): 4184 """Convert keras' padding to TensorFlow's padding. 4185 4186 Arguments: 4187 padding: string, one of 'same' , 'valid' 4188 4189 Returns: 4190 a string, one of 'SAME', 'VALID'. 4191 4192 Raises: 4193 ValueError: if invalid `padding'` 4194 """ 4195 if padding == 'same': 4196 padding = 'SAME' 4197 elif padding == 'valid': 4198 padding = 'VALID' 4199 else: 4200 raise ValueError('Invalid padding: ' + str(padding)) 4201 return padding 4202 4203 4204@keras_export('keras.backend.conv1d') 4205def conv1d(x, 4206 kernel, 4207 strides=1, 4208 padding='valid', 4209 data_format=None, 4210 dilation_rate=1): 4211 """1D convolution. 4212 4213 Arguments: 4214 x: Tensor or variable. 4215 kernel: kernel tensor. 4216 strides: stride integer. 4217 padding: string, `"same"`, `"causal"` or `"valid"`. 4218 data_format: string, one of "channels_last", "channels_first". 4219 dilation_rate: integer dilate rate. 4220 4221 Returns: 4222 A tensor, result of 1D convolution. 4223 4224 Raises: 4225 ValueError: if `data_format` is neither `channels_last` or 4226 `channels_first`. 4227 """ 4228 if data_format is None: 4229 data_format = image_data_format() 4230 if data_format not in {'channels_first', 'channels_last'}: 4231 raise ValueError('Unknown data_format: ' + str(data_format)) 4232 4233 kernel_shape = kernel.shape.as_list() 4234 if padding == 'causal': 4235 # causal (dilated) convolution: 4236 left_pad = dilation_rate * (kernel_shape[0] - 1) 4237 x = temporal_padding(x, (left_pad, 0)) 4238 padding = 'valid' 4239 padding = _preprocess_padding(padding) 4240 4241 x, tf_data_format = _preprocess_conv1d_input(x, data_format) 4242 x = nn.convolution( 4243 input=x, 4244 filter=kernel, 4245 dilation_rate=dilation_rate, 4246 strides=strides, 4247 padding=padding, 4248 data_format=tf_data_format) 4249 if data_format == 'channels_first' and tf_data_format == 'NWC': 4250 x = array_ops.transpose(x, (0, 2, 1)) # NWC -> NCW 4251 return x 4252 4253 4254@keras_export('keras.backend.conv2d') 4255def conv2d(x, 4256 kernel, 4257 strides=(1, 1), 4258 padding='valid', 4259 data_format=None, 4260 dilation_rate=(1, 1)): 4261 """2D convolution. 4262 4263 Arguments: 4264 x: Tensor or variable. 4265 kernel: kernel tensor. 4266 strides: strides tuple. 4267 padding: string, `"same"` or `"valid"`. 4268 data_format: `"channels_last"` or `"channels_first"`. 4269 Whether to use Theano or TensorFlow data format 4270 for inputs/kernels/outputs. 4271 dilation_rate: tuple of 2 integers. 4272 4273 Returns: 4274 A tensor, result of 2D convolution. 4275 4276 Raises: 4277 ValueError: if `data_format` is neither `channels_last` or 4278 `channels_first`. 4279 """ 4280 if data_format is None: 4281 data_format = image_data_format() 4282 if data_format not in {'channels_first', 'channels_last'}: 4283 raise ValueError('Unknown data_format: ' + str(data_format)) 4284 4285 x, tf_data_format = _preprocess_conv2d_input(x, data_format) 4286 padding = _preprocess_padding(padding) 4287 x = nn.convolution( 4288 input=x, 4289 filter=kernel, 4290 dilation_rate=dilation_rate, 4291 strides=strides, 4292 padding=padding, 4293 data_format=tf_data_format) 4294 if data_format == 'channels_first' and tf_data_format == 'NHWC': 4295 x = array_ops.transpose(x, (0, 3, 1, 2)) # NHWC -> NCHW 4296 return x 4297 4298 4299@keras_export('keras.backend.conv2d_transpose') 4300def conv2d_transpose(x, 4301 kernel, 4302 output_shape, 4303 strides=(1, 1), 4304 padding='valid', 4305 data_format=None, 4306 dilation_rate=(1, 1)): 4307 """2D deconvolution (i.e. 4308 4309 transposed convolution). 4310 4311 Arguments: 4312 x: Tensor or variable. 4313 kernel: kernel tensor. 4314 output_shape: 1D int tensor for the output shape. 4315 strides: strides tuple. 4316 padding: string, `"same"` or `"valid"`. 4317 data_format: string, `"channels_last"` or `"channels_first"`. 4318 Whether to use Theano or TensorFlow/CNTK data format 4319 for inputs/kernels/outputs. 4320 dilation_rate: Tuple of 2 integers. 4321 4322 Returns: 4323 A tensor, result of transposed 2D convolution. 4324 4325 Raises: 4326 ValueError: if `data_format` is neither `channels_last` or 4327 `channels_first`. 4328 """ 4329 if data_format is None: 4330 data_format = image_data_format() 4331 if data_format not in {'channels_first', 'channels_last'}: 4332 raise ValueError('Unknown data_format: ' + str(data_format)) 4333 if isinstance(output_shape, (tuple, list)): 4334 output_shape = array_ops.stack(output_shape) 4335 4336 # `atrous_conv2d_transpose` only supports NHWC format, even on GPU. 4337 if data_format == 'channels_first' and dilation_rate != (1, 1): 4338 force_transpose = True 4339 else: 4340 force_transpose = False 4341 4342 x, tf_data_format = _preprocess_conv2d_input(x, data_format, force_transpose) 4343 4344 if data_format == 'channels_first' and tf_data_format == 'NHWC': 4345 output_shape = (output_shape[0], output_shape[2], output_shape[3], 4346 output_shape[1]) 4347 if output_shape[0] is None: 4348 output_shape = (array_ops.shape(x)[0],) + tuple(output_shape[1:]) 4349 output_shape = array_ops.stack(list(output_shape)) 4350 4351 padding = _preprocess_padding(padding) 4352 if tf_data_format == 'NHWC': 4353 strides = (1,) + strides + (1,) 4354 else: 4355 strides = (1, 1) + strides 4356 4357 if dilation_rate == (1, 1): 4358 x = nn.conv2d_transpose(x, kernel, output_shape, strides, 4359 padding=padding, 4360 data_format=tf_data_format) 4361 else: 4362 assert dilation_rate[0] == dilation_rate[1] 4363 x = nn.atrous_conv2d_transpose( 4364 x, 4365 kernel, 4366 output_shape, 4367 rate=dilation_rate[0], 4368 padding=padding) 4369 if data_format == 'channels_first' and tf_data_format == 'NHWC': 4370 x = array_ops.transpose(x, (0, 3, 1, 2)) # NHWC -> NCHW 4371 return x 4372 4373 4374def separable_conv1d(x, 4375 depthwise_kernel, 4376 pointwise_kernel, 4377 strides=1, 4378 padding='valid', 4379 data_format=None, 4380 dilation_rate=1): 4381 """1D convolution with separable filters. 4382 4383 Arguments: 4384 x: input tensor 4385 depthwise_kernel: convolution kernel for the depthwise convolution. 4386 pointwise_kernel: kernel for the 1x1 convolution. 4387 strides: stride integer. 4388 padding: string, `"same"` or `"valid"`. 4389 data_format: string, `"channels_last"` or `"channels_first"`. 4390 dilation_rate: integer dilation rate. 4391 4392 Returns: 4393 Output tensor. 4394 4395 Raises: 4396 ValueError: if `data_format` is neither `channels_last` or 4397 `channels_first`. 4398 """ 4399 if data_format is None: 4400 data_format = image_data_format() 4401 if data_format not in {'channels_first', 'channels_last'}: 4402 raise ValueError('Unknown data_format: ' + str(data_format)) 4403 4404 if isinstance(strides, int): 4405 strides = (strides,) 4406 if isinstance(dilation_rate, int): 4407 dilation_rate = (dilation_rate,) 4408 4409 x, tf_data_format = _preprocess_conv1d_input(x, data_format) 4410 padding = _preprocess_padding(padding) 4411 if not isinstance(strides, tuple): 4412 strides = tuple(strides) 4413 if tf_data_format == 'NWC': 4414 spatial_start_dim = 1 4415 strides = (1,) + strides * 2 + (1,) 4416 else: 4417 spatial_start_dim = 2 4418 strides = (1, 1) + strides * 2 4419 x = array_ops.expand_dims(x, spatial_start_dim) 4420 depthwise_kernel = array_ops.expand_dims(depthwise_kernel, 0) 4421 pointwise_kernel = array_ops.expand_dims(pointwise_kernel, 0) 4422 dilation_rate = (1,) + dilation_rate 4423 4424 x = nn.separable_conv2d( 4425 x, 4426 depthwise_kernel, 4427 pointwise_kernel, 4428 strides=strides, 4429 padding=padding, 4430 rate=dilation_rate, 4431 data_format=tf_data_format) 4432 4433 x = array_ops.squeeze(x, [spatial_start_dim]) 4434 4435 if data_format == 'channels_first' and tf_data_format == 'NWC': 4436 x = array_ops.transpose(x, (0, 2, 1)) # NWC -> NCW 4437 4438 return x 4439 4440 4441@keras_export('keras.backend.separable_conv2d') 4442def separable_conv2d(x, 4443 depthwise_kernel, 4444 pointwise_kernel, 4445 strides=(1, 1), 4446 padding='valid', 4447 data_format=None, 4448 dilation_rate=(1, 1)): 4449 """2D convolution with separable filters. 4450 4451 Arguments: 4452 x: input tensor 4453 depthwise_kernel: convolution kernel for the depthwise convolution. 4454 pointwise_kernel: kernel for the 1x1 convolution. 4455 strides: strides tuple (length 2). 4456 padding: string, `"same"` or `"valid"`. 4457 data_format: string, `"channels_last"` or `"channels_first"`. 4458 dilation_rate: tuple of integers, 4459 dilation rates for the separable convolution. 4460 4461 Returns: 4462 Output tensor. 4463 4464 Raises: 4465 ValueError: if `data_format` is neither `channels_last` or 4466 `channels_first`. 4467 ValueError: if `strides` is not a tuple of 2 integers. 4468 """ 4469 if data_format is None: 4470 data_format = image_data_format() 4471 if data_format not in {'channels_first', 'channels_last'}: 4472 raise ValueError('Unknown data_format: ' + str(data_format)) 4473 if len(strides) != 2: 4474 raise ValueError('`strides` must be a tuple of 2 integers.') 4475 4476 x, tf_data_format = _preprocess_conv2d_input(x, data_format) 4477 padding = _preprocess_padding(padding) 4478 if not isinstance(strides, tuple): 4479 strides = tuple(strides) 4480 if tf_data_format == 'NHWC': 4481 strides = (1,) + strides + (1,) 4482 else: 4483 strides = (1, 1) + strides 4484 4485 x = nn.separable_conv2d( 4486 x, 4487 depthwise_kernel, 4488 pointwise_kernel, 4489 strides=strides, 4490 padding=padding, 4491 rate=dilation_rate, 4492 data_format=tf_data_format) 4493 if data_format == 'channels_first' and tf_data_format == 'NHWC': 4494 x = array_ops.transpose(x, (0, 3, 1, 2)) # NHWC -> NCHW 4495 return x 4496 4497 4498def depthwise_conv2d(x, 4499 depthwise_kernel, 4500 strides=(1, 1), 4501 padding='valid', 4502 data_format=None, 4503 dilation_rate=(1, 1)): 4504 """2D convolution with separable filters. 4505 4506 Arguments: 4507 x: input tensor 4508 depthwise_kernel: convolution kernel for the depthwise convolution. 4509 strides: strides tuple (length 2). 4510 padding: string, `"same"` or `"valid"`. 4511 data_format: string, `"channels_last"` or `"channels_first"`. 4512 dilation_rate: tuple of integers, 4513 dilation rates for the separable convolution. 4514 4515 Returns: 4516 Output tensor. 4517 4518 Raises: 4519 ValueError: if `data_format` is neither `channels_last` or 4520 `channels_first`. 4521 """ 4522 if data_format is None: 4523 data_format = image_data_format() 4524 if data_format not in {'channels_first', 'channels_last'}: 4525 raise ValueError('Unknown data_format: ' + str(data_format)) 4526 4527 x, tf_data_format = _preprocess_conv2d_input(x, data_format) 4528 padding = _preprocess_padding(padding) 4529 if tf_data_format == 'NHWC': 4530 strides = (1,) + strides + (1,) 4531 else: 4532 strides = (1, 1) + strides 4533 4534 x = nn.depthwise_conv2d( 4535 x, 4536 depthwise_kernel, 4537 strides=strides, 4538 padding=padding, 4539 rate=dilation_rate, 4540 data_format=tf_data_format) 4541 if data_format == 'channels_first' and tf_data_format == 'NHWC': 4542 x = array_ops.transpose(x, (0, 3, 1, 2)) # NHWC -> NCHW 4543 return x 4544 4545 4546@keras_export('keras.backend.conv3d') 4547def conv3d(x, 4548 kernel, 4549 strides=(1, 1, 1), 4550 padding='valid', 4551 data_format=None, 4552 dilation_rate=(1, 1, 1)): 4553 """3D convolution. 4554 4555 Arguments: 4556 x: Tensor or variable. 4557 kernel: kernel tensor. 4558 strides: strides tuple. 4559 padding: string, `"same"` or `"valid"`. 4560 data_format: string, `"channels_last"` or `"channels_first"`. 4561 Whether to use Theano or TensorFlow/CNTK data format 4562 for inputs/kernels/outputs. 4563 dilation_rate: tuple of 3 integers. 4564 4565 Returns: 4566 A tensor, result of 3D convolution. 4567 4568 Raises: 4569 ValueError: if `data_format` is neither `channels_last` or 4570 `channels_first`. 4571 """ 4572 if data_format is None: 4573 data_format = image_data_format() 4574 if data_format not in {'channels_first', 'channels_last'}: 4575 raise ValueError('Unknown data_format: ' + str(data_format)) 4576 4577 x, tf_data_format = _preprocess_conv3d_input(x, data_format) 4578 padding = _preprocess_padding(padding) 4579 x = nn.convolution( 4580 input=x, 4581 filter=kernel, 4582 dilation_rate=dilation_rate, 4583 strides=strides, 4584 padding=padding, 4585 data_format=tf_data_format) 4586 if data_format == 'channels_first' and tf_data_format == 'NDHWC': 4587 x = array_ops.transpose(x, (0, 4, 1, 2, 3)) 4588 return x 4589 4590 4591def conv3d_transpose(x, 4592 kernel, 4593 output_shape, 4594 strides=(1, 1, 1), 4595 padding='valid', 4596 data_format=None): 4597 """3D deconvolution (i.e. 4598 4599 transposed convolution). 4600 4601 Arguments: 4602 x: input tensor. 4603 kernel: kernel tensor. 4604 output_shape: 1D int tensor for the output shape. 4605 strides: strides tuple. 4606 padding: string, "same" or "valid". 4607 data_format: string, `"channels_last"` or `"channels_first"`. 4608 Whether to use Theano or TensorFlow/CNTK data format 4609 for inputs/kernels/outputs. 4610 4611 Returns: 4612 A tensor, result of transposed 3D convolution. 4613 4614 Raises: 4615 ValueError: if `data_format` is neither `channels_last` or 4616 `channels_first`. 4617 """ 4618 if data_format is None: 4619 data_format = image_data_format() 4620 if data_format not in {'channels_first', 'channels_last'}: 4621 raise ValueError('Unknown data_format: ' + str(data_format)) 4622 if isinstance(output_shape, (tuple, list)): 4623 output_shape = array_ops.stack(output_shape) 4624 4625 x, tf_data_format = _preprocess_conv3d_input(x, data_format) 4626 4627 if data_format == 'channels_first' and tf_data_format == 'NDHWC': 4628 output_shape = (output_shape[0], output_shape[2], output_shape[3], 4629 output_shape[4], output_shape[1]) 4630 if output_shape[0] is None: 4631 output_shape = (array_ops.shape(x)[0],) + tuple(output_shape[1:]) 4632 output_shape = array_ops.stack(list(output_shape)) 4633 4634 padding = _preprocess_padding(padding) 4635 if tf_data_format == 'NDHWC': 4636 strides = (1,) + strides + (1,) 4637 else: 4638 strides = (1, 1) + strides 4639 4640 x = nn.conv3d_transpose( 4641 x, 4642 kernel, 4643 output_shape, 4644 strides, 4645 padding=padding, 4646 data_format=tf_data_format) 4647 if data_format == 'channels_first' and tf_data_format == 'NDHWC': 4648 x = array_ops.transpose(x, (0, 4, 1, 2, 3)) 4649 return x 4650 4651 4652@keras_export('keras.backend.pool2d') 4653def pool2d(x, 4654 pool_size, 4655 strides=(1, 1), 4656 padding='valid', 4657 data_format=None, 4658 pool_mode='max'): 4659 """2D Pooling. 4660 4661 Arguments: 4662 x: Tensor or variable. 4663 pool_size: tuple of 2 integers. 4664 strides: tuple of 2 integers. 4665 padding: string, `"same"` or `"valid"`. 4666 data_format: string, `"channels_last"` or `"channels_first"`. 4667 pool_mode: string, `"max"` or `"avg"`. 4668 4669 Returns: 4670 A tensor, result of 2D pooling. 4671 4672 Raises: 4673 ValueError: if `data_format` is neither `"channels_last"` or 4674 `"channels_first"`. 4675 ValueError: if `pool_size` is not a tuple of 2 integers. 4676 ValueError: if `strides` is not a tuple of 2 integers. 4677 ValueError: if `pool_mode` is neither `"max"` or `"avg"`. 4678 """ 4679 if data_format is None: 4680 data_format = image_data_format() 4681 if data_format not in {'channels_first', 'channels_last'}: 4682 raise ValueError('Unknown data_format: ' + str(data_format)) 4683 if len(pool_size) != 2: 4684 raise ValueError('`pool_size` must be a tuple of 2 integers.') 4685 if len(strides) != 2: 4686 raise ValueError('`strides` must be a tuple of 2 integers.') 4687 4688 x, tf_data_format = _preprocess_conv2d_input(x, data_format) 4689 padding = _preprocess_padding(padding) 4690 if tf_data_format == 'NHWC': 4691 strides = (1,) + strides + (1,) 4692 pool_size = (1,) + pool_size + (1,) 4693 else: 4694 strides = (1, 1) + strides 4695 pool_size = (1, 1) + pool_size 4696 4697 if pool_mode == 'max': 4698 x = nn.max_pool( 4699 x, pool_size, strides, padding=padding, data_format=tf_data_format) 4700 elif pool_mode == 'avg': 4701 x = nn.avg_pool( 4702 x, pool_size, strides, padding=padding, data_format=tf_data_format) 4703 else: 4704 raise ValueError('Invalid pooling mode: ' + str(pool_mode)) 4705 4706 if data_format == 'channels_first' and tf_data_format == 'NHWC': 4707 x = array_ops.transpose(x, (0, 3, 1, 2)) # NHWC -> NCHW 4708 return x 4709 4710 4711@keras_export('keras.backend.pool3d') 4712def pool3d(x, 4713 pool_size, 4714 strides=(1, 1, 1), 4715 padding='valid', 4716 data_format=None, 4717 pool_mode='max'): 4718 """3D Pooling. 4719 4720 Arguments: 4721 x: Tensor or variable. 4722 pool_size: tuple of 3 integers. 4723 strides: tuple of 3 integers. 4724 padding: string, `"same"` or `"valid"`. 4725 data_format: string, `"channels_last"` or `"channels_first"`. 4726 pool_mode: string, `"max"` or `"avg"`. 4727 4728 Returns: 4729 A tensor, result of 3D pooling. 4730 4731 Raises: 4732 ValueError: if `data_format` is neither `"channels_last"` or 4733 `"channels_first"`. 4734 ValueError: if `pool_mode` is neither `"max"` or `"avg"`. 4735 """ 4736 if data_format is None: 4737 data_format = image_data_format() 4738 if data_format not in {'channels_first', 'channels_last'}: 4739 raise ValueError('Unknown data_format: ' + str(data_format)) 4740 4741 x, tf_data_format = _preprocess_conv3d_input(x, data_format) 4742 padding = _preprocess_padding(padding) 4743 if tf_data_format == 'NDHWC': 4744 strides = (1,) + strides + (1,) 4745 pool_size = (1,) + pool_size + (1,) 4746 else: 4747 strides = (1, 1) + strides 4748 pool_size = (1, 1) + pool_size 4749 4750 if pool_mode == 'max': 4751 x = nn.max_pool3d( 4752 x, pool_size, strides, padding=padding, data_format=tf_data_format) 4753 elif pool_mode == 'avg': 4754 x = nn.avg_pool3d( 4755 x, pool_size, strides, padding=padding, data_format=tf_data_format) 4756 else: 4757 raise ValueError('Invalid pooling mode: ' + str(pool_mode)) 4758 4759 if data_format == 'channels_first' and tf_data_format == 'NDHWC': 4760 x = array_ops.transpose(x, (0, 4, 1, 2, 3)) 4761 return x 4762 4763 4764def local_conv(inputs, 4765 kernel, 4766 kernel_size, 4767 strides, 4768 output_shape, 4769 data_format=None): 4770 """Apply N-D convolution with un-shared weights. 4771 4772 Arguments: 4773 inputs: (N+2)-D tensor with shape 4774 (batch_size, channels_in, d_in1, ..., d_inN) 4775 if data_format='channels_first', or 4776 (batch_size, d_in1, ..., d_inN, channels_in) 4777 if data_format='channels_last'. 4778 kernel: the unshared weight for N-D convolution, 4779 with shape (output_items, feature_dim, channels_out), where 4780 feature_dim = np.prod(kernel_size) * channels_in, 4781 output_items = np.prod(output_shape). 4782 kernel_size: a tuple of N integers, specifying the 4783 spatial dimensions of the N-D convolution window. 4784 strides: a tuple of N integers, specifying the strides 4785 of the convolution along the spatial dimensions. 4786 output_shape: a tuple of (d_out1, ..., d_outN) specifying the spatial 4787 dimensionality of the output. 4788 data_format: string, "channels_first" or "channels_last". 4789 4790 Returns: 4791 An (N+2)-D tensor with shape: 4792 (batch_size, channels_out) + output_shape 4793 if data_format='channels_first', or: 4794 (batch_size,) + output_shape + (channels_out,) 4795 if data_format='channels_last'. 4796 4797 Raises: 4798 ValueError: if `data_format` is neither 4799 `channels_last` nor `channels_first`. 4800 """ 4801 if data_format is None: 4802 data_format = image_data_format() 4803 if data_format not in {'channels_first', 'channels_last'}: 4804 raise ValueError('Unknown data_format: ' + str(data_format)) 4805 4806 kernel_shape = int_shape(kernel) 4807 feature_dim = kernel_shape[1] 4808 channels_out = kernel_shape[-1] 4809 ndims = len(output_shape) 4810 spatial_dimensions = list(range(ndims)) 4811 4812 xs = [] 4813 output_axes_ticks = [range(axis_max) for axis_max in output_shape] 4814 for position in itertools.product(*output_axes_ticks): 4815 slices = [slice(None)] 4816 4817 if data_format == 'channels_first': 4818 slices.append(slice(None)) 4819 4820 slices.extend([slice(position[d] * strides[d], 4821 position[d] * strides[d] + kernel_size[d]) 4822 for d in spatial_dimensions]) 4823 4824 if data_format == 'channels_last': 4825 slices.append(slice(None)) 4826 4827 xs.append(reshape(inputs[slices], (1, -1, feature_dim))) 4828 4829 x_aggregate = concatenate(xs, axis=0) 4830 output = batch_dot(x_aggregate, kernel) 4831 output = reshape(output, output_shape + (-1, channels_out)) 4832 4833 if data_format == 'channels_first': 4834 permutation = [ndims, ndims + 1] + spatial_dimensions 4835 else: 4836 permutation = [ndims] + spatial_dimensions + [ndims + 1] 4837 4838 return permute_dimensions(output, permutation) 4839 4840 4841@keras_export('keras.backend.local_conv1d') 4842def local_conv1d(inputs, kernel, kernel_size, strides, data_format=None): 4843 """Apply 1D conv with un-shared weights. 4844 4845 Arguments: 4846 inputs: 3D tensor with shape: 4847 (batch_size, steps, input_dim) 4848 if data_format is "channels_last" or 4849 (batch_size, input_dim, steps) 4850 if data_format is "channels_first". 4851 kernel: the unshared weight for convolution, 4852 with shape (output_length, feature_dim, filters). 4853 kernel_size: a tuple of a single integer, 4854 specifying the length of the 1D convolution window. 4855 strides: a tuple of a single integer, 4856 specifying the stride length of the convolution. 4857 data_format: the data format, channels_first or channels_last. 4858 4859 Returns: 4860 A 3d tensor with shape: 4861 (batch_size, output_length, filters) 4862 if data_format='channels_first' 4863 or 3D tensor with shape: 4864 (batch_size, filters, output_length) 4865 if data_format='channels_last'. 4866 """ 4867 output_shape = (kernel.shape[0],) 4868 return local_conv(inputs, 4869 kernel, 4870 kernel_size, 4871 strides, 4872 output_shape, 4873 data_format) 4874 4875 4876@keras_export('keras.backend.local_conv2d') 4877def local_conv2d(inputs, 4878 kernel, 4879 kernel_size, 4880 strides, 4881 output_shape, 4882 data_format=None): 4883 """Apply 2D conv with un-shared weights. 4884 4885 Arguments: 4886 inputs: 4D tensor with shape: 4887 (batch_size, filters, new_rows, new_cols) 4888 if data_format='channels_first' 4889 or 4D tensor with shape: 4890 (batch_size, new_rows, new_cols, filters) 4891 if data_format='channels_last'. 4892 kernel: the unshared weight for convolution, 4893 with shape (output_items, feature_dim, filters). 4894 kernel_size: a tuple of 2 integers, specifying the 4895 width and height of the 2D convolution window. 4896 strides: a tuple of 2 integers, specifying the strides 4897 of the convolution along the width and height. 4898 output_shape: a tuple with (output_row, output_col). 4899 data_format: the data format, channels_first or channels_last. 4900 4901 Returns: 4902 A 4D tensor with shape: 4903 (batch_size, filters, new_rows, new_cols) 4904 if data_format='channels_first' 4905 or 4D tensor with shape: 4906 (batch_size, new_rows, new_cols, filters) 4907 if data_format='channels_last'. 4908 """ 4909 return local_conv(inputs, 4910 kernel, 4911 kernel_size, 4912 strides, 4913 output_shape, 4914 data_format) 4915 4916 4917@keras_export('keras.backend.bias_add') 4918def bias_add(x, bias, data_format=None): 4919 """Adds a bias vector to a tensor. 4920 4921 Arguments: 4922 x: Tensor or variable. 4923 bias: Bias tensor to add. 4924 data_format: string, `"channels_last"` or `"channels_first"`. 4925 4926 Returns: 4927 Output tensor. 4928 4929 Raises: 4930 ValueError: In one of the two cases below: 4931 1. invalid `data_format` argument. 4932 2. invalid bias shape. 4933 the bias should be either a vector or 4934 a tensor with ndim(x) - 1 dimension 4935 """ 4936 if data_format is None: 4937 data_format = image_data_format() 4938 if data_format not in {'channels_first', 'channels_last'}: 4939 raise ValueError('Unknown data_format: ' + str(data_format)) 4940 bias_shape = int_shape(bias) 4941 if len(bias_shape) != 1 and len(bias_shape) != ndim(x) - 1: 4942 raise ValueError( 4943 'Unexpected bias dimensions %d, expect to be 1 or %d dimensions' % 4944 (len(bias_shape), ndim(x))) 4945 # pylint: disable=g-no-augmented-assignment 4946 if ndim(x) == 5: 4947 if data_format == 'channels_first': 4948 if len(bias_shape) == 1: 4949 x = x + reshape(bias, (1, bias_shape[0], 1, 1, 1)) 4950 else: 4951 x = x + reshape(bias, (1, bias_shape[3]) + bias_shape[:3]) 4952 elif data_format == 'channels_last': 4953 if len(bias_shape) == 1: 4954 x = x + reshape(bias, (1, 1, 1, bias_shape[0])) 4955 else: 4956 x = x + reshape(bias, (1,) + bias_shape) 4957 elif ndim(x) == 4: 4958 if data_format == 'channels_first': 4959 if len(bias_shape) == 1: 4960 if _has_nchw_support(): 4961 x = nn.bias_add(x, bias, data_format='NCHW') 4962 else: 4963 x = x + reshape(bias, (1, bias_shape[0], 1, 1)) 4964 else: 4965 x = x + reshape(bias, (1, bias_shape[2]) + bias_shape[:2]) 4966 elif data_format == 'channels_last': 4967 if len(bias_shape) == 1: 4968 x = nn.bias_add(x, bias, data_format='NHWC') 4969 else: 4970 x = x + reshape(bias, (1,) + bias_shape) 4971 elif ndim(x) == 3: 4972 if data_format == 'channels_first': 4973 if len(bias_shape) == 1: 4974 x = x + reshape(bias, (1, bias_shape[0], 1)) 4975 else: 4976 x = x + reshape(bias, (1, bias_shape[1], bias_shape[0])) 4977 elif data_format == 'channels_last': 4978 if len(bias_shape) == 1: 4979 x = x + reshape(bias, (1, 1, bias_shape[0])) 4980 else: 4981 x = x + reshape(bias, (1,) + bias_shape) 4982 else: 4983 x = nn.bias_add(x, bias) 4984 # pylint: enable=g-no-augmented-assignment 4985 return x 4986 4987 4988# RANDOMNESS 4989 4990 4991@keras_export('keras.backend.random_normal') 4992def random_normal(shape, mean=0.0, stddev=1.0, dtype=None, seed=None): 4993 """Returns a tensor with normal distribution of values. 4994 4995 Arguments: 4996 shape: A tuple of integers, the shape of tensor to create. 4997 mean: A float, mean of the normal distribution to draw samples. 4998 stddev: A float, standard deviation of the normal distribution 4999 to draw samples. 5000 dtype: String, dtype of returned tensor. 5001 seed: Integer, random seed. 5002 5003 Returns: 5004 A tensor. 5005 """ 5006 if dtype is None: 5007 dtype = floatx() 5008 if seed is None: 5009 seed = np.random.randint(10e6) 5010 return random_ops.random_normal( 5011 shape, mean=mean, stddev=stddev, dtype=dtype, seed=seed) 5012 5013 5014@keras_export('keras.backend.random_uniform') 5015def random_uniform(shape, minval=0.0, maxval=1.0, dtype=None, seed=None): 5016 """Returns a tensor with uniform distribution of values. 5017 5018 Arguments: 5019 shape: A tuple of integers, the shape of tensor to create. 5020 minval: A float, lower boundary of the uniform distribution 5021 to draw samples. 5022 maxval: A float, upper boundary of the uniform distribution 5023 to draw samples. 5024 dtype: String, dtype of returned tensor. 5025 seed: Integer, random seed. 5026 5027 Returns: 5028 A tensor. 5029 """ 5030 if dtype is None: 5031 dtype = floatx() 5032 if seed is None: 5033 seed = np.random.randint(10e6) 5034 return random_ops.random_uniform( 5035 shape, minval=minval, maxval=maxval, dtype=dtype, seed=seed) 5036 5037 5038@keras_export('keras.backend.random_binomial') 5039def random_binomial(shape, p=0.0, dtype=None, seed=None): 5040 """Returns a tensor with random binomial distribution of values. 5041 5042 Arguments: 5043 shape: A tuple of integers, the shape of tensor to create. 5044 p: A float, `0. <= p <= 1`, probability of binomial distribution. 5045 dtype: String, dtype of returned tensor. 5046 seed: Integer, random seed. 5047 5048 Returns: 5049 A tensor. 5050 """ 5051 if dtype is None: 5052 dtype = floatx() 5053 if seed is None: 5054 seed = np.random.randint(10e6) 5055 return array_ops.where( 5056 random_ops.random_uniform(shape, dtype=dtype, seed=seed) <= p, 5057 array_ops.ones(shape, dtype=dtype), array_ops.zeros(shape, dtype=dtype)) 5058 5059 5060@keras_export('keras.backend.truncated_normal') 5061def truncated_normal(shape, mean=0.0, stddev=1.0, dtype=None, seed=None): 5062 """Returns a tensor with truncated random normal distribution of values. 5063 5064 The generated values follow a normal distribution 5065 with specified mean and standard deviation, 5066 except that values whose magnitude is more than 5067 two standard deviations from the mean are dropped and re-picked. 5068 5069 Arguments: 5070 shape: A tuple of integers, the shape of tensor to create. 5071 mean: Mean of the values. 5072 stddev: Standard deviation of the values. 5073 dtype: String, dtype of returned tensor. 5074 seed: Integer, random seed. 5075 5076 Returns: 5077 A tensor. 5078 """ 5079 if dtype is None: 5080 dtype = floatx() 5081 if seed is None: 5082 seed = np.random.randint(10e6) 5083 return random_ops.truncated_normal( 5084 shape, mean, stddev, dtype=dtype, seed=seed) 5085 5086 5087# CTC 5088# TensorFlow has a native implementation, but it uses sparse tensors 5089# and therefore requires a wrapper for Keras. The functions below convert 5090# dense to sparse tensors and also wraps up the beam search code that is 5091# in TensorFlow's CTC implementation 5092 5093 5094@keras_export('keras.backend.ctc_label_dense_to_sparse') 5095def ctc_label_dense_to_sparse(labels, label_lengths): 5096 """Converts CTC labels from dense to sparse. 5097 5098 Arguments: 5099 labels: dense CTC labels. 5100 label_lengths: length of the labels. 5101 5102 Returns: 5103 A sparse tensor representation of the labels. 5104 """ 5105 label_shape = array_ops.shape(labels) 5106 num_batches_tns = array_ops.stack([label_shape[0]]) 5107 max_num_labels_tns = array_ops.stack([label_shape[1]]) 5108 5109 def range_less_than(_, current_input): 5110 return array_ops.expand_dims( 5111 math_ops.range(label_shape[1]), 0) < array_ops.fill( 5112 max_num_labels_tns, current_input) 5113 5114 init = math_ops.cast( 5115 array_ops.fill([1, label_shape[1]], 0), dtypes_module.bool) 5116 dense_mask = functional_ops.scan( 5117 range_less_than, label_lengths, initializer=init, parallel_iterations=1) 5118 dense_mask = dense_mask[:, 0, :] 5119 5120 label_array = array_ops.reshape( 5121 array_ops.tile(math_ops.range(0, label_shape[1]), num_batches_tns), 5122 label_shape) 5123 label_ind = array_ops.boolean_mask(label_array, dense_mask) 5124 5125 batch_array = array_ops.transpose( 5126 array_ops.reshape( 5127 array_ops.tile(math_ops.range(0, label_shape[0]), max_num_labels_tns), 5128 reverse(label_shape, 0))) 5129 batch_ind = array_ops.boolean_mask(batch_array, dense_mask) 5130 indices = array_ops.transpose( 5131 array_ops.reshape(concatenate([batch_ind, label_ind], axis=0), [2, -1])) 5132 5133 vals_sparse = array_ops.gather_nd(labels, indices) 5134 5135 return sparse_tensor.SparseTensor( 5136 math_ops.cast(indices, dtypes_module.int64), vals_sparse, 5137 math_ops.cast(label_shape, dtypes_module.int64)) 5138 5139 5140@keras_export('keras.backend.ctc_batch_cost') 5141def ctc_batch_cost(y_true, y_pred, input_length, label_length): 5142 """Runs CTC loss algorithm on each batch element. 5143 5144 Arguments: 5145 y_true: tensor `(samples, max_string_length)` 5146 containing the truth labels. 5147 y_pred: tensor `(samples, time_steps, num_categories)` 5148 containing the prediction, or output of the softmax. 5149 input_length: tensor `(samples, 1)` containing the sequence length for 5150 each batch item in `y_pred`. 5151 label_length: tensor `(samples, 1)` containing the sequence length for 5152 each batch item in `y_true`. 5153 5154 Returns: 5155 Tensor with shape (samples,1) containing the 5156 CTC loss of each element. 5157 """ 5158 label_length = math_ops.cast( 5159 array_ops.squeeze(label_length, axis=-1), dtypes_module.int32) 5160 input_length = math_ops.cast( 5161 array_ops.squeeze(input_length, axis=-1), dtypes_module.int32) 5162 sparse_labels = math_ops.cast( 5163 ctc_label_dense_to_sparse(y_true, label_length), dtypes_module.int32) 5164 5165 y_pred = math_ops.log(array_ops.transpose(y_pred, perm=[1, 0, 2]) + epsilon()) 5166 5167 return array_ops.expand_dims( 5168 ctc.ctc_loss( 5169 inputs=y_pred, labels=sparse_labels, sequence_length=input_length), 1) 5170 5171 5172@keras_export('keras.backend.ctc_decode') 5173def ctc_decode(y_pred, input_length, greedy=True, beam_width=100, top_paths=1): 5174 """Decodes the output of a softmax. 5175 5176 Can use either greedy search (also known as best path) 5177 or a constrained dictionary search. 5178 5179 Arguments: 5180 y_pred: tensor `(samples, time_steps, num_categories)` 5181 containing the prediction, or output of the softmax. 5182 input_length: tensor `(samples, )` containing the sequence length for 5183 each batch item in `y_pred`. 5184 greedy: perform much faster best-path search if `true`. 5185 This does not use a dictionary. 5186 beam_width: if `greedy` is `false`: a beam search decoder will be used 5187 with a beam of this width. 5188 top_paths: if `greedy` is `false`, 5189 how many of the most probable paths will be returned. 5190 5191 Returns: 5192 Tuple: 5193 List: if `greedy` is `true`, returns a list of one element that 5194 contains the decoded sequence. 5195 If `false`, returns the `top_paths` most probable 5196 decoded sequences. 5197 Important: blank labels are returned as `-1`. 5198 Tensor `(top_paths, )` that contains 5199 the log probability of each decoded sequence. 5200 """ 5201 y_pred = math_ops.log(array_ops.transpose(y_pred, perm=[1, 0, 2]) + epsilon()) 5202 input_length = math_ops.cast(input_length, dtypes_module.int32) 5203 5204 if greedy: 5205 (decoded, log_prob) = ctc.ctc_greedy_decoder( 5206 inputs=y_pred, sequence_length=input_length) 5207 else: 5208 (decoded, log_prob) = ctc.ctc_beam_search_decoder( 5209 inputs=y_pred, 5210 sequence_length=input_length, 5211 beam_width=beam_width, 5212 top_paths=top_paths) 5213 decoded_dense = [ 5214 sparse_ops.sparse_to_dense( 5215 st.indices, st.dense_shape, st.values, default_value=-1) 5216 for st in decoded 5217 ] 5218 return (decoded_dense, log_prob) 5219 5220 5221# HIGH ORDER FUNCTIONS 5222 5223 5224@keras_export('keras.backend.map_fn') 5225def map_fn(fn, elems, name=None, dtype=None): 5226 """Map the function fn over the elements elems and return the outputs. 5227 5228 Arguments: 5229 fn: Callable that will be called upon each element in elems 5230 elems: tensor 5231 name: A string name for the map node in the graph 5232 dtype: Output data type. 5233 5234 Returns: 5235 Tensor with dtype `dtype`. 5236 """ 5237 return map_fn_lib.map_fn(fn, elems, name=name, dtype=dtype) 5238 5239 5240@keras_export('keras.backend.foldl') 5241def foldl(fn, elems, initializer=None, name=None): 5242 """Reduce elems using fn to combine them from left to right. 5243 5244 Arguments: 5245 fn: Callable that will be called upon each element in elems and an 5246 accumulator, for instance `lambda acc, x: acc + x` 5247 elems: tensor 5248 initializer: The first value used (`elems[0]` in case of None) 5249 name: A string name for the foldl node in the graph 5250 5251 Returns: 5252 Tensor with same type and shape as `initializer`. 5253 """ 5254 return functional_ops.foldl(fn, elems, initializer=initializer, name=name) 5255 5256 5257@keras_export('keras.backend.foldr') 5258def foldr(fn, elems, initializer=None, name=None): 5259 """Reduce elems using fn to combine them from right to left. 5260 5261 Arguments: 5262 fn: Callable that will be called upon each element in elems and an 5263 accumulator, for instance `lambda acc, x: acc + x` 5264 elems: tensor 5265 initializer: The first value used (`elems[-1]` in case of None) 5266 name: A string name for the foldr node in the graph 5267 5268 Returns: 5269 Same type and shape as initializer 5270 """ 5271 return functional_ops.foldr(fn, elems, initializer=initializer, name=name) 5272 5273# Load Keras default configuration from config file if present. 5274# Set Keras base dir path given KERAS_HOME env variable, if applicable. 5275# Otherwise either ~/.keras or /tmp. 5276if 'KERAS_HOME' in os.environ: 5277 _keras_dir = os.environ.get('KERAS_HOME') 5278else: 5279 _keras_base_dir = os.path.expanduser('~') 5280 _keras_dir = os.path.join(_keras_base_dir, '.keras') 5281_config_path = os.path.expanduser(os.path.join(_keras_dir, 'keras.json')) 5282if os.path.exists(_config_path): 5283 try: 5284 _config = json.load(open(_config_path)) 5285 except ValueError: 5286 _config = {} 5287 _floatx = _config.get('floatx', floatx()) 5288 assert _floatx in {'float16', 'float32', 'float64'} 5289 _epsilon = _config.get('epsilon', epsilon()) 5290 assert isinstance(_epsilon, float) 5291 _image_data_format = _config.get('image_data_format', image_data_format()) 5292 assert _image_data_format in {'channels_last', 'channels_first'} 5293 set_floatx(_floatx) 5294 set_epsilon(_epsilon) 5295 set_image_data_format(_image_data_format) 5296 5297# Save config file. 5298if not os.path.exists(_keras_dir): 5299 try: 5300 os.makedirs(_keras_dir) 5301 except OSError: 5302 # Except permission denied and potential race conditions 5303 # in multi-threaded environments. 5304 pass 5305 5306if not os.path.exists(_config_path): 5307 _config = { 5308 'floatx': floatx(), 5309 'epsilon': epsilon(), 5310 'backend': 'tensorflow', 5311 'image_data_format': image_data_format() 5312 } 5313 try: 5314 with open(_config_path, 'w') as f: 5315 f.write(json.dumps(_config, indent=4)) 5316 except IOError: 5317 # Except permission denied. 5318 pass 5319 5320 5321def in_multi_worker_mode(): 5322 """Whether we are operating in a Multi-Worker setting.""" 5323 tf_config = json.loads(os.environ.get('TF_CONFIG', '{}')) 5324 cluster_spec = server_lib.ClusterSpec(tf_config.get('cluster', {})) 5325 return tf_config and 'master' not in cluster_spec.jobs 5326 5327 5328def configure_and_create_distributed_session(distribution_strategy): 5329 """Configure session config and create a session with it.""" 5330 5331 def _create_session(distribution_strategy): 5332 """Create the Distributed Strategy session.""" 5333 session_config = get_default_session_config() 5334 5335 # If a session already exists, merge in its config; in the case there is a 5336 # conflict, take values of the existing config. 5337 global _SESSION 5338 if getattr(_SESSION, 'session', None) and _SESSION.session._config: 5339 session_config.MergeFrom(_SESSION.session._config) 5340 5341 if is_tpu_strategy(distribution_strategy): 5342 # TODO(priyag, yuefengz): Remove this workaround when Distribute 5343 # Coordinator is integrated with keras and we can create a session from 5344 # there. 5345 distribution_strategy.configure(session_config) 5346 master = distribution_strategy.extended._tpu_cluster_resolver.master() # pylint: disable=protected-access 5347 session = session_module.Session(config=session_config, target=master) 5348 else: 5349 worker_context = dc_context.get_current_worker_context() 5350 if worker_context: 5351 dc_session_config = worker_context.session_config 5352 # Merge the default session config to the one from distribute 5353 # coordinator, which is fine for now since they don't have 5354 # conflicting configurations. 5355 dc_session_config.MergeFrom(session_config) 5356 session = session_module.Session( 5357 config=dc_session_config, target=worker_context.master_target) 5358 else: 5359 distribution_strategy.configure(session_config) 5360 session = session_module.Session(config=session_config) 5361 5362 set_session(session) 5363 5364 if in_multi_worker_mode(): 5365 dc.run_distribute_coordinator( 5366 _create_session, 5367 distribution_strategy, 5368 mode=dc.CoordinatorMode.INDEPENDENT_WORKER) 5369 else: 5370 _create_session(distribution_strategy) 5371 5372 5373def is_tpu_strategy(strategy): 5374 """We're executing TPU Strategy.""" 5375 return strategy is not None and strategy.__class__.__name__ == 'TPUStrategy' 5376 5377 5378def cast_variables_to_tensor(tensors): 5379 5380 def _cast_variables_to_tensor(tensor): 5381 if isinstance(tensor, variables_module.Variable): 5382 return array_ops.identity(tensor) 5383 return tensor 5384 5385 return nest.map_structure(_cast_variables_to_tensor, tensors) 5386