def benchmarkMatrixInverseOp(self): for adjoint in False, True: for shape in self.shapes: with ops.Graph().as_default(), \ session.Session(config=benchmark.benchmark_config()) as sess, \ ops.device("/cpu:0"): matrix = self._GenerateMatrix(shape) inv = linalg_ops.matrix_inverse(matrix, adjoint=adjoint) variables.global_variables_initializer().run() self.run_op_benchmark( sess, control_flow_ops.group(inv), min_iters=25, name="matrix_inverse_cpu_{shape}_adjoint_{adjoint}".format( shape=shape, adjoint=adjoint)) if test.is_gpu_available(True): with ops.Graph().as_default(), \ session.Session(config=benchmark.benchmark_config()) as sess, \ ops.device("/gpu:0"): matrix = self._GenerateMatrix(shape) inv = linalg_ops.matrix_inverse(matrix, adjoint=adjoint) variables.global_variables_initializer().run() self.run_op_benchmark( sess, control_flow_ops.group(inv), min_iters=25, name="matrix_inverse_gpu_{shape}_adjoint_{adjoint}".format( shape=shape, adjoint=adjoint))
def benchmarkMatrixInverseOp(self): for adjoint in False, True: for size in self.sizes: data = self._GenerateData(size) with ops.Graph().as_default(), \ session.Session() as sess, \ ops.device("/cpu:0"): inv = linalg_ops.matrix_inverse(data, adjoint=adjoint) self.run_op_benchmark( sess, control_flow_ops.group(inv), min_iters=25, name="matrix_inverse_cpu_{size}_{adjoint}".format( size=size, adjoint="adjoint" if adjoint else "noadjoint")) if test.is_gpu_available(True): with ops.Graph().as_default(), \ session.Session() as sess, \ ops.device("/gpu:0"): inv = linalg_ops.matrix_inverse(data, adjoint=adjoint) self.run_op_benchmark( sess, control_flow_ops.group(inv), min_iters=25, name="matrix_inverse_gpu_{size}_{adjoint}".format( size=size, adjoint="adjoint" if adjoint else "noadjoint"))
def benchmarkMatrixInverseOp(self): for adjoint in False, True: for shape in self.shapes: with ops.Graph().as_default(), \ session.Session(config=benchmark.benchmark_config()) as sess, \ ops.device("/cpu:0"): matrix = self._GenerateMatrix(shape) inv = linalg_ops.matrix_inverse(matrix, adjoint=adjoint) self.evaluate(variables.global_variables_initializer()) self.run_op_benchmark( sess, control_flow_ops.group(inv), min_iters=25, name="matrix_inverse_cpu_{shape}_adjoint_{adjoint}". format(shape=shape, adjoint=adjoint)) if test.is_gpu_available(True): with ops.Graph().as_default(), \ session.Session(config=benchmark.benchmark_config()) as sess, \ ops.device("/gpu:0"): matrix = self._GenerateMatrix(shape) inv = linalg_ops.matrix_inverse(matrix, adjoint=adjoint) self.evaluate(variables.global_variables_initializer()) self.run_op_benchmark( sess, control_flow_ops.group(inv), min_iters=25, name="matrix_inverse_gpu_{shape}_adjoint_{adjoint}" .format(shape=shape, adjoint=adjoint))
def testNotInvertible(self): # The input should be invertible. with self.cached_session(): with self.assertRaisesOpError("Input is not invertible."): # All rows of the matrix below add to zero. tensor3 = constant_op.constant([[1., 0., -1.], [-1., 1., 0.], [0., -1., 1.]]) linalg_ops.matrix_inverse(tensor3).eval()
def testNotInvertible(self): # The input should be invertible. with self.test_session(): with self.assertRaisesOpError("Input is not invertible."): # All rows of the matrix below add to zero. tensor3 = constant_op.constant([[1., 0., -1.], [-1., 1., 0.], [0., -1., 1.]]) linalg_ops.matrix_inverse(tensor3).eval()
def testConcurrentExecutesWithoutError(self): with self.session(use_gpu=True) as sess: all_ops = [] for adjoint_ in True, False: matrix1 = random_ops.random_normal([5, 5], seed=42) matrix2 = random_ops.random_normal([5, 5], seed=42) inv1 = linalg_ops.matrix_inverse(matrix1, adjoint=adjoint_) inv2 = linalg_ops.matrix_inverse(matrix2, adjoint=adjoint_) all_ops += [inv1, inv2] inv = sess.run(all_ops) self.assertAllEqual(inv[0], inv[1]) self.assertAllEqual(inv[2], inv[3])
def testConcurrentExecutesWithoutError(self): with self.session() as sess: all_ops = [] for adjoint_ in True, False: matrix1 = random_ops.random_normal([5, 5], seed=42) matrix2 = random_ops.random_normal([5, 5], seed=42) inv1 = linalg_ops.matrix_inverse(matrix1, adjoint=adjoint_) inv2 = linalg_ops.matrix_inverse(matrix2, adjoint=adjoint_) all_ops += [inv1, inv2] inv = self.evaluate(all_ops) self.assertAllEqual(inv[0], inv[1]) self.assertAllEqual(inv[2], inv[3])
def _image_projective_transform_grad(op, grad): """Computes the gradient for ImageProjectiveTransform.""" images = op.inputs[0] transforms = op.inputs[1] interpolation = op.get_attr("interpolation") image_or_images = ops.convert_to_tensor(images, name="images") transform_or_transforms = ops.convert_to_tensor( transforms, name="transforms", dtype=dtypes.float32) if image_or_images.dtype.base_dtype not in _IMAGE_DTYPES: raise TypeError("Invalid dtype %s." % image_or_images.dtype) if len(transform_or_transforms.get_shape()) == 1: transforms = transform_or_transforms[None] elif len(transform_or_transforms.get_shape()) == 2: transforms = transform_or_transforms else: raise TypeError("Transforms should have rank 1 or 2.") # Invert transformations transforms = flat_transforms_to_matrices(transforms=transforms) inverse = linalg_ops.matrix_inverse(transforms) transforms = matrices_to_flat_transforms(inverse) output = gen_image_ops.image_projective_transform_v2( images=grad, transforms=transforms, output_shape=array_ops.shape(image_or_images)[1:3], interpolation=interpolation) return [output, None, None]
def _MatrixDeterminantGrad(op, grad): """Gradient for MatrixDeterminant.""" a = op.inputs[0] c = op.outputs[0] a_adj_inv = linalg_ops.matrix_inverse(a, adjoint=True) multipliers = array_ops.reshape(grad * c, array_ops.concat(0, [array_ops.shape(c), [1, 1]])) return multipliers * a_adj_inv
def _LogMatrixDeterminantGrad(op, _, grad_b): """Gradient for LogMatrixDeterminant.""" a = op.inputs[0] c = op.outputs[1] a_adj_inv = linalg_ops.matrix_inverse(a, adjoint=True) multipliers = array_ops.reshape( grad_b, array_ops.concat([array_ops.shape(c), [1, 1]], 0)) return multipliers * a_adj_inv
def _MatrixDeterminantGrad(op, grad): """Gradient for MatrixDeterminant.""" a = op.inputs[0] c = op.outputs[0] a_adj_inv = linalg_ops.matrix_inverse(a, adjoint=True) multipliers = array_ops.reshape( grad * c, array_ops.concat([array_ops.shape(c), [1, 1]], 0)) return multipliers * a_adj_inv
def _MatrixDeterminantGrad(op, grad): """Gradient for MatrixDeterminant. Returns: gradient Args: op: op grad: grad """ a = op.inputs[0] c = op.outputs[0] ainv = linalg_ops.matrix_inverse(a) return grad * c * array_ops.transpose(ainv)
def _verifyInverse(self, x, np_type): for adjoint in False, True: y = x.astype(np_type) with self.test_session(use_gpu=True): # Verify that x^{-1} * x == Identity matrix. inv = linalg_ops.matrix_inverse(y, adjoint=adjoint) tf_ans = math_ops.matmul(inv, y, adjoint_b=adjoint) np_ans = np.identity(y.shape[-1]) if x.ndim > 2: tiling = list(y.shape) tiling[-2:] = [1, 1] np_ans = np.tile(np_ans, tiling) out = tf_ans.eval() self.assertAllClose(np_ans, out) self.assertShapeEqual(y, tf_ans)
def _verifyInverse(self, x, np_type): for adjoint in False, True: y = x.astype(np_type) with self.cached_session(use_gpu=True): # Verify that x^{-1} * x == Identity matrix. inv = linalg_ops.matrix_inverse(y, adjoint=adjoint) tf_ans = test_util.matmul_without_tf32(inv, y, adjoint_b=adjoint) np_ans = np.identity(y.shape[-1]) if x.ndim > 2: tiling = list(y.shape) tiling[-2:] = [1, 1] np_ans = np.tile(np_ans, tiling) out = self.evaluate(tf_ans) self.assertAllClose(np_ans, out, rtol=1e-4, atol=1e-3) self.assertShapeEqual(y, tf_ans)
def _apply_dense(self, H, var, error): Q = self.get_slot(var, "Q") # Process noise P = self.get_slot(var, "P") # Covariance matrix S = self._Rt + math_ops.matmul(math_ops.matmul(H, P), H, transpose_b=True) Sinv = linalg_ops.matrix_inverse(S, name="Sinv") K = math_ops.matmul(math_ops.matmul(P, H, transpose_b=True), Sinv) #debugP = math_ops.trace(P)/math_ops.cast(gen_array_ops.shape(P)[0], dtype=np.float32) #debugK = math_ops.sqrt(math_ops.reduce_sum(math_ops.square(K))/math_ops.cast(gen_array_ops.shape(K)[1], dtype=np.float32)) #K = Print(K, [debugP, debugK], message="P, K : ") dW = math_ops.matmul(K, error) update_weights = state_ops.assign_add(var, gen_array_ops.reshape(dW, gen_array_ops.shape(var)), use_locking=self._use_locking) update_P = state_ops.assign_add(P, Q - math_ops.matmul(math_ops.matmul(K, S), K, transpose_b=True), use_locking=self._use_locking) return control_flow_ops.group(*[update_weights, update_P])
def _verifyInverse(self, x, np_type): for adjoint in False, True: y = x.astype(np_type) with self.session() as sess: # Verify that x^{-1} * x == Identity matrix. p = array_ops.placeholder(dtypes.as_dtype(y.dtype), y.shape, name="x") with self.test_scope(): inv = linalg_ops.matrix_inverse(p, adjoint=adjoint) tf_ans = math_ops.matmul(inv, p, adjoint_b=adjoint) np_ans = np.identity(y.shape[-1]) if x.ndim > 2: tiling = list(y.shape) tiling[-2:] = [1, 1] np_ans = np.tile(np_ans, tiling) out = sess.run(tf_ans, feed_dict={p: y}) self.assertAllClose(np_ans, out, rtol=1e-3, atol=1e-3) self.assertShapeEqual(y, tf_ans)
def Test(self): np.random.seed(1) n = shape_[-1] batch_shape = shape_[:-2] np_dtype = dtype_.as_numpy_dtype def RandomInput(): # Most matrices are diagonalizable a = np.random.uniform(low=-1.0, high=1.0, size=n * n).reshape([n, n]).astype(np_dtype) if dtype_.is_complex: a += 1j * np.random.uniform(low=-1.0, high=1.0, size=n * n).reshape([n, n]).astype(np_dtype) a = np.tile(a, batch_shape + (1, 1)) return a if dtype_ in (dtypes_lib.float32, dtypes_lib.complex64): atol = 1e-4 else: atol = 1e-12 a = RandomInput() np_e, np_v = np.linalg.eig(a) with self.session(): if compute_v_: tf_e, tf_v = linalg_ops.eig(constant_op.constant(a)) # Check that V*diag(E)*V^(-1) is close to A. a_ev = math_ops.matmul( math_ops.matmul(tf_v, array_ops.matrix_diag(tf_e)), linalg_ops.matrix_inverse(tf_v)) self.assertAllClose(self.evaluate(a_ev), a, atol=atol) # Compare to numpy.linalg.eig. CompareEigenDecompositions(self, np_e, np_v, self.evaluate(tf_e), self.evaluate(tf_v), atol) else: tf_e = linalg_ops.eigvals(constant_op.constant(a)) self.assertAllClose(SortEigenValues(np_e), SortEigenValues(self.evaluate(tf_e)), atol=atol)
def _define_distance_to_clusters(self, data): """Defines the Mahalanobis distance to the assigned Gaussian.""" # TODO(xavigonzalvo): reuse (input - mean) * cov^-1 * (input - # mean) from log probability function. self._all_scores = [] for shard in data: all_scores = [] shard = array_ops.expand_dims(shard, 0) for c in xrange(self._num_classes): if self._covariance_type == FULL_COVARIANCE: cov = self._covs[c, :, :] elif self._covariance_type == DIAG_COVARIANCE: cov = array_ops.diag(self._covs[c, :]) inverse = linalg_ops.matrix_inverse(cov + self._min_var) inv_cov = array_ops.tile( array_ops.expand_dims(inverse, 0), array_ops.stack([self._num_examples, 1, 1])) diff = array_ops.transpose(shard - self._means[c, :, :], perm=[1, 0, 2]) m_left = math_ops.matmul(diff, inv_cov) all_scores.append( math_ops.sqrt( math_ops.matmul( m_left, array_ops.transpose(diff, perm=[0, 2, 1])))) self._all_scores.append( array_ops.reshape( array_ops.concat(all_scores, 1), array_ops.stack([self._num_examples, self._num_classes]))) # Distance to the associated class. self._all_scores = array_ops.concat(self._all_scores, 0) assignments = array_ops.concat(self.assignments(), 0) rows = math_ops.to_int64(math_ops.range(0, self._num_examples)) indices = array_ops.concat([ array_ops.expand_dims(rows, 1), array_ops.expand_dims(assignments, 1) ], 1) self._scores = array_ops.gather_nd(self._all_scores, indices)
def _image_projective_transform_grad(op, grad): images = op.inputs[0] transforms = op.inputs[1] image_or_images = ops.convert_to_tensor(images, name="images") transform_or_transforms = ops.convert_to_tensor(transforms, name="transforms", dtype=dtypes.float32) if image_or_images.dtype.base_dtype not in _IMAGE_DTYPES: raise TypeError("Invalid dtype %s." % image_or_images.dtype) if len(image_or_images.get_shape()) == 2: images = image_or_images[None, :, :, None] elif len(image_or_images.get_shape()) == 3: images = image_or_images[None, :, :, :] elif len(image_or_images.get_shape()) == 4: images = image_or_images else: raise TypeError("Images should have rank between 2 and 4") if len(transform_or_transforms.get_shape()) == 1: transforms = transform_or_transforms[None] elif len(transform_or_transforms.get_shape()) == 2: transforms = transform_or_transforms else: raise TypeError("Transforms should have rank 1 or 2.") # Invert transformations transforms = _flat_transforms_to_matrices(transforms=transforms) inverse = linalg_ops.matrix_inverse(transforms) transforms = _transform_matrices_to_flat(inverse) output = gen_image_ops.image_projective_transform(grad, transforms) if len(image_or_images.get_shape()) == 2: return [output[0, :, :, 0], None] elif len(image_or_images.get_shape()) == 3: return [output[0, :, :, :], None] else: return [output, None]
def _define_distance_to_clusters(self, data): """Defines the Mahalanobis distance to the assigned Gaussian.""" # TODO(xavigonzalvo): reuse (input - mean) * cov^-1 * (input - # mean) from log probability function. self._all_scores = [] for shard in data: all_scores = [] shard = array_ops.expand_dims(shard, 0) for c in xrange(self._num_classes): if self._covariance_type == FULL_COVARIANCE: cov = self._covs[c, :, :] elif self._covariance_type == DIAG_COVARIANCE: cov = array_ops.diag(self._covs[c, :]) inverse = linalg_ops.matrix_inverse(cov + self._min_var) inv_cov = array_ops.tile( array_ops.expand_dims(inverse, 0), array_ops.stack([self._num_examples, 1, 1])) diff = array_ops.transpose(shard - self._means[c, :, :], perm=[1, 0, 2]) m_left = math_ops.matmul(diff, inv_cov) all_scores.append( math_ops.sqrt( math_ops.matmul( m_left, array_ops.transpose( diff, perm=[0, 2, 1])))) self._all_scores.append( array_ops.reshape( array_ops.concat(all_scores, 1), array_ops.stack([self._num_examples, self._num_classes]))) # Distance to the associated class. self._all_scores = array_ops.concat(self._all_scores, 0) assignments = array_ops.concat(self.assignments(), 0) rows = math_ops.to_int64(math_ops.range(0, self._num_examples)) indices = array_ops.concat( [array_ops.expand_dims(rows, 1), array_ops.expand_dims(assignments, 1)], 1) self._scores = array_ops.gather_nd(self._all_scores, indices)
def _image_projective_transform_grad(op, grad): images = op.inputs[0] transforms = op.inputs[1] image_or_images = ops.convert_to_tensor(images, name="images") transform_or_transforms = ops.convert_to_tensor( transforms, name="transforms", dtype=dtypes.float32) if image_or_images.dtype.base_dtype not in _IMAGE_DTYPES: raise TypeError("Invalid dtype %s." % image_or_images.dtype) if len(image_or_images.get_shape()) == 2: images = image_or_images[None, :, :, None] elif len(image_or_images.get_shape()) == 3: images = image_or_images[None, :, :, :] elif len(image_or_images.get_shape()) == 4: images = image_or_images else: raise TypeError("Images should have rank between 2 and 4") if len(transform_or_transforms.get_shape()) == 1: transforms = transform_or_transforms[None] elif len(transform_or_transforms.get_shape()) == 2: transforms = transform_or_transforms else: raise TypeError("Transforms should have rank 1 or 2.") # Invert transformations transforms = _flat_transforms_to_matrices(transforms=transforms) inverse = linalg_ops.matrix_inverse(transforms) transforms = _transform_matrices_to_flat(inverse) output = gen_image_ops.image_projective_transform(grad, transforms) if len(image_or_images.get_shape()) == 2: return [output[0, :, :, 0], None] elif len(image_or_images.get_shape()) == 3: return [output[0, :, :, :], None] else: return [output, None]
for size in 2, 5, 10: # We skip the rank 4, size 10 case: it is slow and conceptually covered # by the other cases. for extra in [(), (2, ), (3, )] + [(3, 2)] * (size < 10): shape = extra + (size, size) name = '%s_%s' % (dtype.__name__, '_'.join(map(str, shape))) _AddTest( MatrixUnaryFunctorGradientTest, 'MatrixInverseGradient', name, _GetMatrixUnaryFunctorGradientTest( linalg_ops.matrix_inverse, dtype, shape)) _AddTest( MatrixUnaryFunctorGradientTest, 'MatrixAdjointInverseGradient', name, _GetMatrixUnaryFunctorGradientTest( lambda x: linalg_ops.matrix_inverse(x, adjoint=True), dtype, shape)) if not test_lib.is_built_with_rocm(): # TODO(rocm) : # re-enable this test when upstream issues are resolved # see commit msg for details _AddTest( MatrixUnaryFunctorGradientTest, 'MatrixExponentialGradient', name, _GetMatrixUnaryFunctorGradientTest( linalg_impl.matrix_exponential, dtype, shape)) _AddTest( MatrixUnaryFunctorGradientTest, 'MatrixDeterminantGradient', name, _GetMatrixUnaryFunctorGradientTest(
def MatrixInverseCompositeGrad(l, grad): l_inverse = linalg_ops.matrix_inverse(l) return _GradWithInverseL(l, l_inverse, grad)
def loop_fn(i): return linalg_ops.matrix_inverse(array_ops.gather(x, i), adjoint=adjoint)
def posdef_inv_matrix_inverse(tensor, identity, damping): """Computes inverse(tensor + damping * identity) directly.""" return linalg_ops.matrix_inverse(tensor + damping * identity)
def testNonSquareMatrix(self): # When the inverse of a non-square matrix is attempted we should return # an error with self.assertRaises(ValueError): linalg_ops.matrix_inverse(np.array([[1., 2., 3.], [3., 4., 5.]]))
def _MatrixDeterminantGrad(op, grad): """Gradient for MatrixDeterminant.""" a = op.inputs[0] c = op.outputs[0] a_adj_inv = linalg_ops.matrix_inverse(a, adjoint=True) return grad * c * a_adj_inv
def testWrongDimensions(self): # The input to the inverse should be at least a 2-dimensional tensor. tensor3 = constant_op.constant([1., 2.]) with self.assertRaises(ValueError): linalg_ops.matrix_inverse(tensor3)
def _two_by_two_solve(m, c): # it might be better just to crank out the exact formula for 2x2 inverses return math_ops.matmul(linalg_ops.matrix_inverse(m), c)