Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow/python/ops/linalg_ops.py: 31%
176 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
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"""Operations for linear algebra."""
17import numpy as np
19from tensorflow.python.framework import dtypes
20from tensorflow.python.framework import ops
21from tensorflow.python.ops import array_ops
22from tensorflow.python.ops import cond
23from tensorflow.python.ops import gen_array_ops
24from tensorflow.python.ops import gen_linalg_ops
25from tensorflow.python.ops import linalg_ops_impl
26from tensorflow.python.ops import map_fn
27from tensorflow.python.ops import math_ops
28# pylint: disable=wildcard-import
29from tensorflow.python.ops.gen_linalg_ops import *
30# pylint: enable=wildcard-import
31from tensorflow.python.util import deprecation
32from tensorflow.python.util import dispatch
33from tensorflow.python.util.tf_export import tf_export
35# Names below are lower_case.
36# pylint: disable=invalid-name
39def _RegularizedGramianCholesky(matrix, l2_regularizer, first_kind):
40 r"""Computes Cholesky factorization of regularized gramian matrix.
42 Below we will use the following notation for each pair of matrix and
43 right-hand sides in the batch:
45 `matrix`=\\(A \in \Re^{m \times n}\\),
46 `output`=\\(C \in \Re^{\min(m, n) \times \min(m,n)}\\),
47 `l2_regularizer`=\\(\lambda\\).
49 If `first_kind` is True, returns the Cholesky factorization \\(L\\) such that
50 \\(L L^H = A^H A + \lambda I\\).
51 If `first_kind` is False, returns the Cholesky factorization \\(L\\) such that
52 \\(L L^H = A A^H + \lambda I\\).
54 Args:
55 matrix: `Tensor` of shape `[..., M, N]`.
56 l2_regularizer: 0-D `double` `Tensor`. Ignored if `fast=False`.
57 first_kind: bool. Controls what gramian matrix to factor.
58 Returns:
59 output: `Tensor` of shape `[..., min(M,N), min(M,N)]` whose inner-most 2
60 dimensions contain the Cholesky factors \\(L\\) described above.
61 """
63 gramian = math_ops.matmul(
64 matrix, matrix, adjoint_a=first_kind, adjoint_b=not first_kind)
65 if isinstance(l2_regularizer, ops.Tensor) or l2_regularizer != 0:
66 matrix_shape = array_ops.shape(matrix)
67 batch_shape = matrix_shape[:-2]
68 if first_kind:
69 small_dim = matrix_shape[-1]
70 else:
71 small_dim = matrix_shape[-2]
72 identity = eye(small_dim, batch_shape=batch_shape, dtype=matrix.dtype)
73 small_dim_static = matrix.shape[-1 if first_kind else -2]
74 identity.set_shape(
75 matrix.shape[:-2].concatenate([small_dim_static, small_dim_static]))
76 gramian += l2_regularizer * identity
77 return gen_linalg_ops.cholesky(gramian)
80@tf_export(
81 'linalg.triangular_solve',
82 v1=['linalg.triangular_solve', 'matrix_triangular_solve'])
83@dispatch.add_dispatch_support
84def matrix_triangular_solve(matrix, rhs, lower=True, adjoint=False, name=None):
85 """Solve systems of linear equations with upper or lower triangular matrices.
87 `matrix` is a tensor of shape `[..., M, M]` whose inner-most 2 dimensions form
88 square matrices. If `lower` is `True` then the strictly upper triangular part
89 of each inner-most matrix is assumed to be zero and not accessed. If `lower`
90 is `False` then the strictly lower triangular part of each inner-most matrix
91 is assumed to be zero and not accessed. `rhs` is a tensor of shape
92 `[..., M, N]`.
94 The output is a tensor of shape `[..., M, N]`. If `adjoint` is `True` then the
95 innermost matrices in output satisfy matrix equations `
96 sum_k matrix[..., i, k] * output[..., k, j] = rhs[..., i, j]`.
97 If `adjoint` is `False` then the
98 innermost matrices in output satisfy matrix equations
99 `sum_k adjoint(matrix[..., i, k]) * output[..., k, j] = rhs[..., i, j]`.
101 Example:
103 >>> a = tf.constant([[3, 0, 0, 0],
104 ... [2, 1, 0, 0],
105 ... [1, 0, 1, 0],
106 ... [1, 1, 1, 1]], dtype=tf.float32)
108 >>> b = tf.constant([[4], [2], [4], [2]], dtype=tf.float32)
109 >>> x = tf.linalg.triangular_solve(a, b, lower=True)
110 >>> x
111 <tf.Tensor: shape=(4, 1), dtype=float32, numpy=
112 array([[ 1.3333334 ],
113 [-0.66666675],
114 [ 2.6666665 ],
115 [-1.3333331 ]], dtype=float32)>
116 >>> tf.matmul(a, x)
117 <tf.Tensor: shape=(4, 1), dtype=float32, numpy=
118 array([[4.],
119 [2.],
120 [4.],
121 [2.]], dtype=float32)>
123 Args:
124 matrix: A `Tensor`. Must be one of the following types: `float64`,
125 `float32`, `half`, `complex64`, `complex128`. Shape is `[..., M, M]`.
126 rhs: A `Tensor`. Must have the same type as `matrix`. Shape is `[..., M,
127 N]`.
128 lower: An optional `bool`. Defaults to `True`. Boolean indicating whether
129 the innermost matrices in matrix are lower or upper triangular.
130 adjoint: An optional `bool`. Defaults to `False`. Boolean indicating whether
131 to solve with matrix or its (block-wise) adjoint.
132 name: A name for the operation (optional).
134 Returns:
135 A `Tensor`. Has the same type as matrix, and shape is `[..., M, N]`.
137 """
138 with ops.name_scope(name, 'triangular_solve', [matrix, rhs]):
139 return gen_linalg_ops.matrix_triangular_solve(
140 matrix, rhs, lower=lower, adjoint=adjoint)
143@tf_export(
144 'linalg.cholesky_solve', v1=['linalg.cholesky_solve', 'cholesky_solve'])
145@dispatch.add_dispatch_support
146@deprecation.deprecated_endpoints('cholesky_solve')
147def cholesky_solve(chol, rhs, name=None):
148 """Solves systems of linear eqns `A X = RHS`, given Cholesky factorizations.
150 Specifically, returns `X` from `A X = RHS`, where `A = L L^T`, `L` is the
151 `chol` arg and `RHS` is the `rhs` arg.
153 ```python
154 # Solve 10 separate 2x2 linear systems:
155 A = ... # shape 10 x 2 x 2
156 RHS = ... # shape 10 x 2 x 1
157 chol = tf.linalg.cholesky(A) # shape 10 x 2 x 2
158 X = tf.linalg.cholesky_solve(chol, RHS) # shape 10 x 2 x 1
159 # tf.matmul(A, X) ~ RHS
160 X[3, :, 0] # Solution to the linear system A[3, :, :] x = RHS[3, :, 0]
162 # Solve five linear systems (K = 5) for every member of the length 10 batch.
163 A = ... # shape 10 x 2 x 2
164 RHS = ... # shape 10 x 2 x 5
165 ...
166 X[3, :, 2] # Solution to the linear system A[3, :, :] x = RHS[3, :, 2]
167 ```
169 Args:
170 chol: A `Tensor`. Must be `float32` or `float64`, shape is `[..., M, M]`.
171 Cholesky factorization of `A`, e.g. `chol = tf.linalg.cholesky(A)`.
172 For that reason, only the lower triangular parts (including the diagonal)
173 of the last two dimensions of `chol` are used. The strictly upper part is
174 assumed to be zero and not accessed.
175 rhs: A `Tensor`, same type as `chol`, shape is `[..., M, K]`.
176 name: A name to give this `Op`. Defaults to `cholesky_solve`.
178 Returns:
179 Solution to `A x = rhs`, shape `[..., M, K]`.
180 """
181 # To solve C C^* x = rhs, we
182 # 1. Solve C y = rhs for y, thus y = C^* x
183 # 2. Solve C^* x = y for x
184 with ops.name_scope(name, 'cholesky_solve', [chol, rhs]):
185 y = gen_linalg_ops.matrix_triangular_solve(
186 chol, rhs, adjoint=False, lower=True)
187 x = gen_linalg_ops.matrix_triangular_solve(
188 chol, y, adjoint=True, lower=True)
189 return x
192@tf_export('eye', 'linalg.eye')
193@dispatch.add_dispatch_support
194def eye(num_rows,
195 num_columns=None,
196 batch_shape=None,
197 dtype=dtypes.float32,
198 name=None):
199 """Construct an identity matrix, or a batch of matrices.
201 See also `tf.ones`, `tf.zeros`, `tf.fill`, `tf.one_hot`.
203 ```python
204 # Construct one identity matrix.
205 tf.eye(2)
206 ==> [[1., 0.],
207 [0., 1.]]
209 # Construct a batch of 3 identity matrices, each 2 x 2.
210 # batch_identity[i, :, :] is a 2 x 2 identity matrix, i = 0, 1, 2.
211 batch_identity = tf.eye(2, batch_shape=[3])
213 # Construct one 2 x 3 "identity" matrix
214 tf.eye(2, num_columns=3)
215 ==> [[ 1., 0., 0.],
216 [ 0., 1., 0.]]
217 ```
219 Args:
220 num_rows: Non-negative `int32` scalar `Tensor` giving the number of rows
221 in each batch matrix.
222 num_columns: Optional non-negative `int32` scalar `Tensor` giving the number
223 of columns in each batch matrix. Defaults to `num_rows`.
224 batch_shape: A list or tuple of Python integers or a 1-D `int32` `Tensor`.
225 If provided, the returned `Tensor` will have leading batch dimensions of
226 this shape.
227 dtype: The type of an element in the resulting `Tensor`
228 name: A name for this `Op`. Defaults to "eye".
230 Returns:
231 A `Tensor` of shape `batch_shape + [num_rows, num_columns]`
232 """
233 return linalg_ops_impl.eye(num_rows,
234 num_columns=num_columns,
235 batch_shape=batch_shape,
236 dtype=dtype,
237 name=name)
240@tf_export('linalg.lstsq', v1=['linalg.lstsq', 'matrix_solve_ls'])
241@dispatch.add_dispatch_support
242@deprecation.deprecated_endpoints('matrix_solve_ls')
243def matrix_solve_ls(matrix, rhs, l2_regularizer=0.0, fast=True, name=None):
244 r"""Solves one or more linear least-squares problems.
246 `matrix` is a tensor of shape `[..., M, N]` whose inner-most 2 dimensions
247 form `M`-by-`N` matrices. Rhs is a tensor of shape `[..., M, K]` whose
248 inner-most 2 dimensions form `M`-by-`K` matrices. The computed output is a
249 `Tensor` of shape `[..., N, K]` whose inner-most 2 dimensions form `M`-by-`K`
250 matrices that solve the equations
251 `matrix[..., :, :] * output[..., :, :] = rhs[..., :, :]` in the least squares
252 sense.
254 Below we will use the following notation for each pair of matrix and
255 right-hand sides in the batch:
257 `matrix`=\\(A \in \Re^{m \times n}\\),
258 `rhs`=\\(B \in \Re^{m \times k}\\),
259 `output`=\\(X \in \Re^{n \times k}\\),
260 `l2_regularizer`=\\(\lambda\\).
262 If `fast` is `True`, then the solution is computed by solving the normal
263 equations using Cholesky decomposition. Specifically, if \\(m \ge n\\) then
264 \\(X = (A^T A + \lambda I)^{-1} A^T B\\), which solves the least-squares
265 problem \\(X = \mathrm{argmin}_{Z \in \Re^{n \times k}} ||A Z - B||_F^2 +
266 \lambda ||Z||_F^2\\). If \\(m \lt n\\) then `output` is computed as
267 \\(X = A^T (A A^T + \lambda I)^{-1} B\\), which (for \\(\lambda = 0\\)) is
268 the minimum-norm solution to the under-determined linear system, i.e.
269 \\(X = \mathrm{argmin}_{Z \in \Re^{n \times k}} ||Z||_F^2 \\), subject to
270 \\(A Z = B\\). Notice that the fast path is only numerically stable when
271 \\(A\\) is numerically full rank and has a condition number
272 \\(\mathrm{cond}(A) \lt \frac{1}{\sqrt{\epsilon_{mach}}}\\) or\\(\lambda\\)
273 is sufficiently large.
275 If `fast` is `False` an algorithm based on the numerically robust complete
276 orthogonal decomposition is used. This computes the minimum-norm
277 least-squares solution, even when \\(A\\) is rank deficient. This path is
278 typically 6-7 times slower than the fast path. If `fast` is `False` then
279 `l2_regularizer` is ignored.
281 Args:
282 matrix: `Tensor` of shape `[..., M, N]`.
283 rhs: `Tensor` of shape `[..., M, K]`.
284 l2_regularizer: 0-D `double` `Tensor`. Ignored if `fast=False`.
285 fast: bool. Defaults to `True`.
286 name: string, optional name of the operation.
288 Returns:
289 output: `Tensor` of shape `[..., N, K]` whose inner-most 2 dimensions form
290 `M`-by-`K` matrices that solve the equations
291 `matrix[..., :, :] * output[..., :, :] = rhs[..., :, :]` in the least
292 squares sense.
294 Raises:
295 NotImplementedError: linalg.lstsq is currently disabled for complex128
296 and l2_regularizer != 0 due to poor accuracy.
297 """
299 # pylint: disable=long-lambda
300 def _use_composite_impl(fast, tensor_shape):
301 """Determines whether to use the composite or specialized CPU kernel.
303 When the total size of the tensor is larger than the cache size and the
304 batch size is large compared to the smallest matrix dimension, then the
305 composite implementation is inefficient since it has to read the entire
306 tensor from memory multiple times. In this case we fall back to the
307 original CPU kernel, which does all the computational steps on each
308 matrix separately.
310 Only fast mode is supported by the composite impl, so `False` is returned
311 if `fast` is `False`.
313 Args:
314 fast: bool indicating if fast mode in the solver was requested.
315 tensor_shape: The shape of the tensor.
317 Returns:
318 True if the composite impl should be used. False otherwise.
319 """
320 if fast is False:
321 return False
322 batch_shape = tensor_shape[:-2]
323 matrix_shape = tensor_shape[-2:]
324 if not tensor_shape.is_fully_defined():
325 return True
326 tensor_size = tensor_shape.num_elements() * matrix.dtype.size
327 is_io_bound = batch_shape.num_elements() > np.min(matrix_shape)
328 L2_CACHE_SIZE_GUESSTIMATE = 256000
329 if tensor_size > L2_CACHE_SIZE_GUESSTIMATE and is_io_bound:
330 return False
331 else:
332 return True
334 def _overdetermined(matrix, rhs, l2_regularizer):
335 """Computes (A^H*A + l2_regularizer)^{-1} * A^H * rhs."""
336 chol = _RegularizedGramianCholesky(
337 matrix, l2_regularizer=l2_regularizer, first_kind=True)
338 return cholesky_solve(chol, math_ops.matmul(matrix, rhs, adjoint_a=True))
340 def _underdetermined(matrix, rhs, l2_regularizer):
341 """Computes A^H * (A*A^H + l2_regularizer)^{-1} * rhs."""
342 chol = _RegularizedGramianCholesky(
343 matrix, l2_regularizer=l2_regularizer, first_kind=False)
344 return math_ops.matmul(matrix, cholesky_solve(chol, rhs), adjoint_a=True)
346 def _composite_impl(matrix, rhs, l2_regularizer):
347 """Composite implementation of matrix_solve_ls that supports GPU."""
348 with ops.name_scope(name, 'matrix_solve_ls', [matrix, rhs, l2_regularizer]):
349 matrix_shape = matrix.get_shape()[-2:]
350 if matrix_shape.is_fully_defined():
351 if matrix_shape[-2] >= matrix_shape[-1]:
352 return _overdetermined(matrix, rhs, l2_regularizer)
353 else:
354 return _underdetermined(matrix, rhs, l2_regularizer)
355 else:
356 # We have to defer determining the shape to runtime and use
357 # conditional execution of the appropriate graph.
358 matrix_shape = array_ops.shape(matrix)[-2:]
359 return cond.cond(
360 matrix_shape[-2] >= matrix_shape[-1],
361 lambda: _overdetermined(matrix, rhs, l2_regularizer),
362 lambda: _underdetermined(matrix, rhs, l2_regularizer))
364 matrix = ops.convert_to_tensor(matrix, name='matrix')
365 if matrix.dtype == dtypes.complex128 and l2_regularizer != 0:
366 # TODO(rmlarsen): Investigate and fix accuracy bug.
367 raise NotImplementedError('matrix_solve_ls is currently disabled for '
368 'complex128 and l2_regularizer != 0 due to '
369 'poor accuracy.')
370 tensor_shape = matrix.get_shape()
371 if _use_composite_impl(fast, tensor_shape):
372 return _composite_impl(matrix, rhs, l2_regularizer)
373 else:
374 return gen_linalg_ops.matrix_solve_ls(
375 matrix, rhs, l2_regularizer, fast=fast, name=name)
378@tf_export('linalg.eig', 'eig', v1=[])
379@dispatch.add_dispatch_support
380def eig(tensor, name=None):
381 """Computes the eigen decomposition of a batch of matrices.
383 The eigenvalues
384 and eigenvectors for a non-Hermitian matrix in general are complex. The
385 eigenvectors are not guaranteed to be linearly independent.
387 Computes the eigenvalues and right eigenvectors of the innermost
388 N-by-N matrices in `tensor` such that
389 `tensor[...,:,:] * v[..., :,i] = e[..., i] * v[...,:,i]`, for i=0...N-1.
391 Args:
392 tensor: `Tensor` of shape `[..., N, N]`. Only the lower triangular part of
393 each inner inner matrix is referenced.
394 name: string, optional name of the operation.
396 Returns:
397 e: Eigenvalues. Shape is `[..., N]`. The eigenvalues are not necessarily
398 ordered.
399 v: Eigenvectors. Shape is `[..., N, N]`. The columns of the inner most
400 matrices contain eigenvectors of the corresponding matrices in `tensor`
401 """
402 if tensor.dtype == dtypes.float32 or tensor.dtype == dtypes.complex64:
403 out_dtype = dtypes.complex64
404 elif tensor.dtype == dtypes.float64 or tensor.dtype == dtypes.complex128:
405 out_dtype = dtypes.complex128
406 e, v = gen_linalg_ops.eig(tensor, Tout=out_dtype, compute_v=True, name=name)
407 return e, v
410@tf_export('linalg.eigvals', 'eigvals', v1=[])
411@dispatch.add_dispatch_support
412def eigvals(tensor, name=None):
413 """Computes the eigenvalues of one or more matrices.
415 Note: If your program backpropagates through this function, you should replace
416 it with a call to tf.linalg.eig (possibly ignoring the second output) to
417 avoid computing the eigen decomposition twice. This is because the
418 eigenvectors are used to compute the gradient w.r.t. the eigenvalues. See
419 _SelfAdjointEigV2Grad in linalg_grad.py.
421 Args:
422 tensor: `Tensor` of shape `[..., N, N]`.
423 name: string, optional name of the operation.
425 Returns:
426 e: Eigenvalues. Shape is `[..., N]`. The vector `e[..., :]` contains the `N`
427 eigenvalues of `tensor[..., :, :]`.
428 """
429 if tensor.dtype == dtypes.float32 or tensor.dtype == dtypes.complex64:
430 out_dtype = dtypes.complex64
431 elif tensor.dtype == dtypes.float64 or tensor.dtype == dtypes.complex128:
432 out_dtype = dtypes.complex128
433 e, _ = gen_linalg_ops.eig(tensor, Tout=out_dtype, compute_v=False, name=name)
434 return e
437@tf_export('linalg.eigh', v1=['linalg.eigh', 'self_adjoint_eig'])
438@dispatch.add_dispatch_support
439@deprecation.deprecated_endpoints('self_adjoint_eig')
440def self_adjoint_eig(tensor, name=None):
441 """Computes the eigen decomposition of a batch of self-adjoint matrices.
443 Computes the eigenvalues and eigenvectors of the innermost N-by-N matrices
444 in `tensor` such that
445 `tensor[...,:,:] * v[..., :,i] = e[..., i] * v[...,:,i]`, for i=0...N-1.
447 Args:
448 tensor: `Tensor` of shape `[..., N, N]`. Only the lower triangular part of
449 each inner inner matrix is referenced.
450 name: string, optional name of the operation.
452 Returns:
453 e: Eigenvalues. Shape is `[..., N]`. Sorted in non-decreasing order.
454 v: Eigenvectors. Shape is `[..., N, N]`. The columns of the inner most
455 matrices contain eigenvectors of the corresponding matrices in `tensor`
456 """
457 e, v = gen_linalg_ops.self_adjoint_eig_v2(tensor, compute_v=True, name=name)
458 return e, v
461@tf_export('linalg.eigvalsh', v1=['linalg.eigvalsh', 'self_adjoint_eigvals'])
462@dispatch.add_dispatch_support
463@deprecation.deprecated_endpoints('self_adjoint_eigvals')
464def self_adjoint_eigvals(tensor, name=None):
465 """Computes the eigenvalues of one or more self-adjoint matrices.
467 Note: If your program backpropagates through this function, you should replace
468 it with a call to tf.linalg.eigh (possibly ignoring the second output) to
469 avoid computing the eigen decomposition twice. This is because the
470 eigenvectors are used to compute the gradient w.r.t. the eigenvalues. See
471 _SelfAdjointEigV2Grad in linalg_grad.py.
473 Args:
474 tensor: `Tensor` of shape `[..., N, N]`.
475 name: string, optional name of the operation.
477 Returns:
478 e: Eigenvalues. Shape is `[..., N]`. The vector `e[..., :]` contains the `N`
479 eigenvalues of `tensor[..., :, :]`.
480 """
481 e, _ = gen_linalg_ops.self_adjoint_eig_v2(tensor, compute_v=False, name=name)
482 return e
485@tf_export('linalg.svd', v1=['linalg.svd', 'svd'])
486@dispatch.add_dispatch_support
487@deprecation.deprecated_endpoints('svd')
488def svd(tensor, full_matrices=False, compute_uv=True, name=None):
489 r"""Computes the singular value decompositions of one or more matrices.
491 Computes the SVD of each inner matrix in `tensor` such that
492 `tensor[..., :, :] = u[..., :, :] * diag(s[..., :, :]) *
493 transpose(conj(v[..., :, :]))`
495 ```python
496 # a is a tensor.
497 # s is a tensor of singular values.
498 # u is a tensor of left singular vectors.
499 # v is a tensor of right singular vectors.
500 s, u, v = svd(a)
501 s = svd(a, compute_uv=False)
502 ```
504 Args:
505 tensor: `Tensor` of shape `[..., M, N]`. Let `P` be the minimum of `M` and
506 `N`.
507 full_matrices: If true, compute full-sized `u` and `v`. If false
508 (the default), compute only the leading `P` singular vectors.
509 Ignored if `compute_uv` is `False`.
510 compute_uv: If `True` then left and right singular vectors will be
511 computed and returned in `u` and `v`, respectively. Otherwise, only the
512 singular values will be computed, which can be significantly faster.
513 name: string, optional name of the operation.
515 Returns:
516 s: Singular values. Shape is `[..., P]`. The values are sorted in reverse
517 order of magnitude, so s[..., 0] is the largest value, s[..., 1] is the
518 second largest, etc.
519 u: Left singular vectors. If `full_matrices` is `False` (default) then
520 shape is `[..., M, P]`; if `full_matrices` is `True` then shape is
521 `[..., M, M]`. Not returned if `compute_uv` is `False`.
522 v: Right singular vectors. If `full_matrices` is `False` (default) then
523 shape is `[..., N, P]`. If `full_matrices` is `True` then shape is
524 `[..., N, N]`. Not returned if `compute_uv` is `False`.
526 @compatibility(numpy)
527 Mostly equivalent to numpy.linalg.svd, except that
528 * The order of output arguments here is `s`, `u`, `v` when `compute_uv` is
529 `True`, as opposed to `u`, `s`, `v` for numpy.linalg.svd.
530 * full_matrices is `False` by default as opposed to `True` for
531 numpy.linalg.svd.
532 * tf.linalg.svd uses the standard definition of the SVD
533 \\(A = U \Sigma V^H\\), such that the left singular vectors of `a` are
534 the columns of `u`, while the right singular vectors of `a` are the
535 columns of `v`. On the other hand, numpy.linalg.svd returns the adjoint
536 \\(V^H\\) as the third output argument.
537 ```python
538 import tensorflow as tf
539 import numpy as np
540 s, u, v = tf.linalg.svd(a)
541 tf_a_approx = tf.matmul(u, tf.matmul(tf.linalg.diag(s), v, adjoint_b=True))
542 u, s, v_adj = np.linalg.svd(a, full_matrices=False)
543 np_a_approx = np.dot(u, np.dot(np.diag(s), v_adj))
544 # tf_a_approx and np_a_approx should be numerically close.
545 ```
546 @end_compatibility
547 """
548 s, u, v = gen_linalg_ops.svd(
549 tensor, compute_uv=compute_uv, full_matrices=full_matrices, name=name)
550 if compute_uv:
551 return math_ops.real(s), u, v
552 else:
553 return math_ops.real(s)
556# pylint: disable=redefined-builtin
557@tf_export('norm', 'linalg.norm', v1=[])
558@dispatch.add_dispatch_support
559def norm_v2(tensor,
560 ord='euclidean',
561 axis=None,
562 keepdims=None,
563 name=None):
564 r"""Computes the norm of vectors, matrices, and tensors.
566 This function can compute several different vector norms (the 1-norm, the
567 Euclidean or 2-norm, the inf-norm, and in general the p-norm for p > 0) and
568 matrix norms (Frobenius, 1-norm, 2-norm and inf-norm).
570 Args:
571 tensor: `Tensor` of types `float32`, `float64`, `complex64`, `complex128`
572 ord: Order of the norm. Supported values are `'fro'`, `'euclidean'`,
573 `1`, `2`, `np.inf` and any positive real number yielding the corresponding
574 p-norm. Default is `'euclidean'` which is equivalent to Frobenius norm if
575 `tensor` is a matrix and equivalent to 2-norm for vectors.
576 Some restrictions apply:
577 a) The Frobenius norm `'fro'` is not defined for vectors,
578 b) If axis is a 2-tuple (matrix norm), only `'euclidean'`, '`fro'`, `1`,
579 `2`, `np.inf` are supported.
580 See the description of `axis` on how to compute norms for a batch of
581 vectors or matrices stored in a tensor.
582 axis: If `axis` is `None` (the default), the input is considered a vector
583 and a single vector norm is computed over the entire set of values in the
584 tensor, i.e. `norm(tensor, ord=ord)` is equivalent to
585 `norm(reshape(tensor, [-1]), ord=ord)`.
586 If `axis` is a Python integer, the input is considered a batch of vectors,
587 and `axis` determines the axis in `tensor` over which to compute vector
588 norms.
589 If `axis` is a 2-tuple of Python integers it is considered a batch of
590 matrices and `axis` determines the axes in `tensor` over which to compute
591 a matrix norm.
592 Negative indices are supported. Example: If you are passing a tensor that
593 can be either a matrix or a batch of matrices at runtime, pass
594 `axis=[-2,-1]` instead of `axis=None` to make sure that matrix norms are
595 computed.
596 keepdims: If True, the axis indicated in `axis` are kept with size 1.
597 Otherwise, the dimensions in `axis` are removed from the output shape.
598 name: The name of the op.
600 Returns:
601 output: A `Tensor` of the same type as tensor, containing the vector or
602 matrix norms. If `keepdims` is True then the rank of output is equal to
603 the rank of `tensor`. Otherwise, if `axis` is none the output is a scalar,
604 if `axis` is an integer, the rank of `output` is one less than the rank
605 of `tensor`, if `axis` is a 2-tuple the rank of `output` is two less
606 than the rank of `tensor`.
608 Raises:
609 ValueError: If `ord` or `axis` is invalid.
611 @compatibility(numpy)
612 Mostly equivalent to numpy.linalg.norm.
613 Not supported: ord <= 0, 2-norm for matrices, nuclear norm.
614 Other differences:
615 a) If axis is `None`, treats the flattened `tensor` as a vector
616 regardless of rank.
617 b) Explicitly supports 'euclidean' norm as the default, including for
618 higher order tensors.
619 @end_compatibility
620 """
621 return norm(tensor=tensor,
622 ord=ord,
623 axis=axis,
624 keepdims=keepdims,
625 name=name)
628# pylint: disable=redefined-builtin
629@tf_export(v1=['norm', 'linalg.norm'])
630@dispatch.add_dispatch_support
631@deprecation.deprecated_args(
632 None, 'keep_dims is deprecated, use keepdims instead', 'keep_dims')
633def norm(tensor,
634 ord='euclidean',
635 axis=None,
636 keepdims=None,
637 name=None,
638 keep_dims=None):
639 r"""Computes the norm of vectors, matrices, and tensors.
641 This function can compute several different vector norms (the 1-norm, the
642 Euclidean or 2-norm, the inf-norm, and in general the p-norm for p > 0) and
643 matrix norms (Frobenius, 1-norm, 2-norm and inf-norm).
645 Args:
646 tensor: `Tensor` of types `float32`, `float64`, `complex64`, `complex128`
647 ord: Order of the norm. Supported values are 'fro', 'euclidean',
648 `1`, `2`, `np.inf` and any positive real number yielding the corresponding
649 p-norm. Default is 'euclidean' which is equivalent to Frobenius norm if
650 `tensor` is a matrix and equivalent to 2-norm for vectors.
651 Some restrictions apply:
652 a) The Frobenius norm `fro` is not defined for vectors,
653 b) If axis is a 2-tuple (matrix norm), only 'euclidean', 'fro', `1`,
654 `2`, `np.inf` are supported.
655 See the description of `axis` on how to compute norms for a batch of
656 vectors or matrices stored in a tensor.
657 axis: If `axis` is `None` (the default), the input is considered a vector
658 and a single vector norm is computed over the entire set of values in the
659 tensor, i.e. `norm(tensor, ord=ord)` is equivalent to
660 `norm(reshape(tensor, [-1]), ord=ord)`.
661 If `axis` is a Python integer, the input is considered a batch of vectors,
662 and `axis` determines the axis in `tensor` over which to compute vector
663 norms.
664 If `axis` is a 2-tuple of Python integers it is considered a batch of
665 matrices and `axis` determines the axes in `tensor` over which to compute
666 a matrix norm.
667 Negative indices are supported. Example: If you are passing a tensor that
668 can be either a matrix or a batch of matrices at runtime, pass
669 `axis=[-2,-1]` instead of `axis=None` to make sure that matrix norms are
670 computed.
671 keepdims: If True, the axis indicated in `axis` are kept with size 1.
672 Otherwise, the dimensions in `axis` are removed from the output shape.
673 name: The name of the op.
674 keep_dims: Deprecated alias for `keepdims`.
676 Returns:
677 output: A `Tensor` of the same type as tensor, containing the vector or
678 matrix norms. If `keepdims` is True then the rank of output is equal to
679 the rank of `tensor`. Otherwise, if `axis` is none the output is a scalar,
680 if `axis` is an integer, the rank of `output` is one less than the rank
681 of `tensor`, if `axis` is a 2-tuple the rank of `output` is two less
682 than the rank of `tensor`.
684 Raises:
685 ValueError: If `ord` or `axis` is invalid.
687 @compatibility(numpy)
688 Mostly equivalent to numpy.linalg.norm.
689 Not supported: ord <= 0, 2-norm for matrices, nuclear norm.
690 Other differences:
691 a) If axis is `None`, treats the flattened `tensor` as a vector
692 regardless of rank.
693 b) Explicitly supports 'euclidean' norm as the default, including for
694 higher order tensors.
695 @end_compatibility
696 """
697 keepdims = deprecation.deprecated_argument_lookup('keepdims', keepdims,
698 'keep_dims', keep_dims)
699 if keepdims is None:
700 keepdims = False
702 is_matrix_norm = ((isinstance(axis, tuple) or isinstance(axis, list)) and
703 len(axis) == 2)
704 if is_matrix_norm:
705 axis = tuple(axis)
706 if (not isinstance(axis[0], int) or not isinstance(axis[1], int) or
707 axis[0] == axis[1]):
708 raise ValueError(
709 "'axis' must be None, an integer, or a tuple of 2 "
710 f"unique integers, got {axis}")
711 supported_matrix_norms = ['euclidean', 'fro', 1, 2, np.inf]
712 if ord not in supported_matrix_norms:
713 raise ValueError(f"'ord' must be a supported matrix norm in "
714 f"{supported_matrix_norms}, got {ord}")
715 else:
716 if not (isinstance(axis, int) or axis is None):
717 raise ValueError(
718 "'axis' must be None, an integer, or a "
719 f"tuple of 2 unique integers, got {axis}")
721 supported_vector_norms = ['euclidean', 1, 2, np.inf]
722 if (not np.isreal(ord) or ord <= 0) and ord not in supported_vector_norms:
723 raise ValueError(f"'ord' must be a supported vector norm, got {ord}")
724 if axis is not None:
725 axis = (axis,)
727 with ops.name_scope(name, 'norm', [tensor]):
728 tensor = ops.convert_to_tensor(tensor)
730 if ord in ['fro', 'euclidean', 2, 2.0]:
731 if is_matrix_norm and ord in [2, 2.0]:
732 rank = array_ops.rank(tensor)
733 positive_axis = map_fn.map_fn(
734 lambda i: cond.cond(
735 i >= 0,
736 lambda: i,
737 lambda: i + rank),
738 ops.convert_to_tensor(axis))
739 axes = math_ops.range(rank)
740 perm_before = array_ops.concat([
741 gen_array_ops.list_diff(axes, positive_axis, dtypes.int32)[0],
742 positive_axis
743 ],
744 axis=0)
745 perm_after = map_fn.map_fn(
746 lambda i: math_ops.cast(
747 array_ops.squeeze(
748 array_ops.where_v2(math_ops.equal(perm_before, i))),
749 dtype=dtypes.int32), axes)
750 permed = array_ops.transpose(tensor, perm=perm_before)
751 matrix_2_norm = array_ops.expand_dims(
752 math_ops.reduce_max(
753 math_ops.abs(gen_linalg_ops.svd(permed, compute_uv=False)[0]),
754 axis=-1,
755 keepdims=True),
756 axis=-1)
757 result = array_ops.transpose(matrix_2_norm, perm=perm_after)
758 else:
759 # NOTE: we unfortunately cannot use tf.math.reduce_euclidean_norm, since
760 # this introduces a new op that is not supported in XLA, and breaks
761 # many existing TPU workloads (e.g. ResNet).
762 result = math_ops.sqrt(
763 math_ops.reduce_sum(
764 tensor * math_ops.conj(tensor), axis, keepdims=True))
765 else:
766 result = math_ops.abs(tensor)
767 if ord == 1:
768 sum_axis = None if axis is None else axis[0]
769 result = math_ops.reduce_sum(result, sum_axis, keepdims=True)
770 if is_matrix_norm:
771 result = math_ops.reduce_max(result, axis[-1], keepdims=True)
772 elif ord == np.inf:
773 if is_matrix_norm:
774 result = math_ops.reduce_sum(result, axis[1], keepdims=True)
775 max_axis = None if axis is None else axis[0]
776 result = math_ops.reduce_max(result, max_axis, keepdims=True)
777 else:
778 # General p-norms (positive p only)
779 result = math_ops.pow(
780 math_ops.reduce_sum(math_ops.pow(result, ord), axis, keepdims=True),
781 1.0 / ord)
782 if not keepdims:
783 result = array_ops.squeeze(result, axis)
784 return result
787# pylint: enable=invalid-name,redefined-builtin