Change:
I am having problem in running the backward propagation with svd. In particular, it seems working when the first dimension of the matrix x (below) is greater than the second. But I get the following error if the first is smaller than the second. PyTorch version: 2018.04.20 Is debug build: No CUDA used to build PyTorch: 8.0.61 OS: Ubuntu 16.04.4 LTS GCC version: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 CMake version: Could not collect Python version: 3.5 Is CUDA available: No CUDA runtime version: No CUDA GPU models and configuration: No CUDA Nvidia driver version: No CUDA cuDNN version: No CUDA Versions of relevant libraries: [pip3] numpy (1.13.3) [pip3] torch (2018.4.20) [pip3] torchvision (0.2.0) [conda] pytorch 0.3.1 py35cuda8.0.61cudnn7.0.52 pytorch [conda] pytorch-nightly 2018.04.20 py35cuda8.0.61cudnn7.1.21 pytorch [conda] torchvision 0.2.0 py35heaa392f_1 pytorch
Repro'ed on 0.4 branch. works btw.
What does "Repro'ed" means? Should I install from that branch? I need to compute the kernel of a matrix, therefore I need the last columns of the matrix V (which is why I have to pass ).
It's a shorthand for "reproduced", which means that the bug still hasn't been fixed. Sorry, we'll try to get to it soon.

Discussion:
from copy import deepcopy from collections import OrderedDict from itertools import product <del> from operator import mul </del> <ins> from operator import mul, itemgetter </ins> from functools import reduce, wraps from torch.autograd.gradcheck import gradgradcheck, gradcheck from torch.autograd.function import once_differentiable

#   method name, #   input size/constructing fn, #   args (tuple represents shape of a tensor arg), <del> #   test variant name (will be used at test name suffix),  // optional #   indices for possible dim arg,                          // optional #   output indices that should be gradcheck'ed,            // optional </del> <ins> #   test variant name (will be used at test name suffix),    // optional #   indices for possible dim arg,                            // optional #   fn mapping output to part that should be gradcheck'ed,   // optional </ins> # ) method_tests = [ ('add', (S, S, S), ((S, S, S),)),

'symmetric_pd', NO_ARGS, [skipIfNoLapack]), ('logdet', lambda: make_nonzero_det(random_fullrank_matrix_distinct_singular_value(S), 1, 0), NO_ARGS, 'distinct_singular_values', NO_ARGS, [skipIfNoLapack]), <del> ('slogdet', lambda: make_nonzero_det(torch.randn(1, 1), 1), NO_ARGS, '1x1_pos_det', NO_ARGS, [skipIfNoLapack], [1]), </del> <ins> ('slogdet', lambda: make_nonzero_det(torch.randn(1, 1), 1), NO_ARGS, '1x1_pos_det', NO_ARGS, [skipIfNoLapack], itemgetter(1)), </ins> ('slogdet', lambda: make_nonzero_det(torch.randn(1, 1), -1), NO_ARGS, <del> '1x1_neg_det', NO_ARGS, [skipIfNoLapack], [1]), ('slogdet', lambda: make_nonzero_det(torch.randn(S, S), 1), NO_ARGS, 'pos_det', NO_ARGS, [skipIfNoLapack], [1]), ('slogdet', lambda: make_nonzero_det(torch.randn(S, S), -1), NO_ARGS, 'neg_det', NO_ARGS, [skipIfNoLapack], [1]), </del> <ins> '1x1_neg_det', NO_ARGS, [skipIfNoLapack], itemgetter(1)), ('slogdet', lambda: make_nonzero_det(torch.randn(S, S), 1), NO_ARGS, 'pos_det', NO_ARGS, [skipIfNoLapack], itemgetter(1)), ('slogdet', lambda: make_nonzero_det(torch.randn(S, S), -1), NO_ARGS, 'neg_det', NO_ARGS, [skipIfNoLapack], itemgetter(1)), </ins> ('slogdet', lambda: make_nonzero_det(random_symmetric_matrix(S)), NO_ARGS, <del> 'symmetric', NO_ARGS, [skipIfNoLapack], [1]), ('slogdet', lambda: random_symmetric_pd_matrix(S), NO_ARGS, 'symmetric_pd', NO_ARGS, [skipIfNoLapack], [1]), </del> <ins> 'symmetric', NO_ARGS, [skipIfNoLapack], itemgetter(1)), ('slogdet', lambda: random_symmetric_pd_matrix(S), NO_ARGS, 'symmetric_pd', NO_ARGS, [skipIfNoLapack], itemgetter(1)), </ins> ('slogdet', lambda: random_fullrank_matrix_distinct_singular_value(S), NO_ARGS, <del> 'distinct_singular_values', NO_ARGS, [skipIfNoLapack], [1]), </del> <ins> 'distinct_singular_values', NO_ARGS, [skipIfNoLapack], itemgetter(1)), </ins> ('svd', lambda: random_fullrank_matrix_distinct_singular_value(S), NO_ARGS, '', NO_ARGS, [skipIfNoLapack]), <del> ('svd', lambda: random_fullrank_matrix_distinct_singular_value(M), NO_ARGS, 'large', NO_ARGS, [skipIfNoLapack]), </del> <ins> ('svd', lambda: random_fullrank_matrix_distinct_singular_value(S)[:(S - 2)], NO_ARGS, 'wide', NO_ARGS, [skipIfNoLapack]), ('svd', lambda: random_fullrank_matrix_distinct_singular_value(S)[:, :(S - 2)], NO_ARGS, 'tall', NO_ARGS, [skipIfNoLapack]), ('svd', lambda: random_fullrank_matrix_distinct_singular_value(S)[:(S - 2)], (False,), 'wide_all', NO_ARGS, [skipIfNoLapack], lambda usv: (usv[0], usv[1], usv[2][:, :(S - 2)])), ('svd', lambda: random_fullrank_matrix_distinct_singular_value(S)[:, :(S - 2)], (False,), 'tall_all', NO_ARGS, [skipIfNoLapack], lambda usv: (usv[0][:, :(S - 2)], usv[1], usv[2])), ('svd', lambda: random_fullrank_matrix_distinct_singular_value(M), NO_ARGS, 'large', NO_ARGS, [skipIfNoLapack]), </ins> ('gesv', (S, S), ((S, S),), '', NO_ARGS, [skipIfNoLapack]), ('fill_', (S, S, S), (1,), 'number'), ('fill_', (), (1,), 'number_scalar'),

skipTestIf = test[5] if len(test) >= 6 else [] <del> test_output_indices = test[6] if len(test) >= 7 else None </del> <ins> output_process_fn = test[6] if len(test) >= 7 else lambda x: x </ins> for dim_perm in product([-1, 1], repeat=len(dim_args_idx)): test_name = basic_test_name

# for-loop bodies don't define scopes, so we have to save the variables # we want to close over in some way def do_test(self, name=name, self_size=self_size, args=new_args, test_name=test_name, <del> test_output_indices=test_output_indices): </del> <ins> output_process_fn=output_process_fn): </ins> def check(name): is_magic_method = name[:2] == '__' and name[-2:] == '__' is_inplace = name[-1] == "_" and not is_magic_method

def fn(*inputs): output = getattr(inputs[0], name)(*inputs[1:]) <del> if test_output_indices is None: return output else: return tuple(output[i] for i in test_output_indices) </del> <ins> return output_process_fn(output) </ins> if not is_inplace and name not in EXCLUDE_GRADCHECK: run_grad_and_gradgrad_checks(self, name, test_name, fn,

if hasattr(torch, name) and name not in EXCLUDE_FUNCTIONAL: def fn(*inputs): output = getattr(torch, name)(*inputs) <del> if test_output_indices is None: return output else: return tuple(output[i] for i in test_output_indices) </del> <ins> return output_process_fn(output) </ins> f_args_variable = (self_variable,) + args_variable f_args_tensor = (self_tensor,) + args_tensor

auto m = self.size(0); auto n = self.size(1); auto k = sigma.size(0); <ins> auto gsigma = grads[1]; auto u = raw_u; auto v = raw_v; auto gu = grads[0]; auto gv = grads[2]; </ins> <del> Tensor u, v; </del> if (!some) { <del> // ignore the free subspace </del> <ins> // We ignore the free subspace here because possible base vectors cancel // each other, e.g., both -v and +v are valid base for a dimension. // Don't assume behavior of any particular implementation of svd. </ins> u = raw_u.narrow(1, 0, k); v = raw_v.narrow(1, 0, k); <del> } else { u = raw_u; v = raw_v; </del> <ins> if (gu.defined()) { gu = gu.narrow(1, 0, k); } if (gv.defined()) { gv = gv.narrow(1, 0, k); } </ins> } <del> auto gu = grads[0]; auto gsigma = grads[1]; auto gv = grads[2]; </del> auto vt = v.t(); Tensor sigma_term;