diff options
author | Eric Wieser <wieser.eric@gmail.com> | 2019-10-16 12:47:40 +0100 |
---|---|---|
committer | Eric Wieser <wieser.eric@gmail.com> | 2019-10-16 13:07:00 +0100 |
commit | 418a85eb738c76109779d1a70ba7da6c3a3f1603 (patch) | |
tree | 3a8d63cfea36efb17fe464d50c903b67bbf4598f | |
parent | 033907bae4ee39eeb27234eda1c80e60009dd5ed (diff) | |
download | numpy-418a85eb738c76109779d1a70ba7da6c3a3f1603.tar.gz |
Back out use_factor changes, to be restored in a separate PR
-rw-r--r-- | doc/release/upcoming_changes/14197.improvement.rst | 16 | ||||
-rw-r--r-- | numpy/random/generator.pyx | 37 | ||||
-rw-r--r-- | numpy/random/tests/test_generator_mt19937.py | 40 |
3 files changed, 11 insertions, 82 deletions
diff --git a/doc/release/upcoming_changes/14197.improvement.rst b/doc/release/upcoming_changes/14197.improvement.rst index d460fdab5..c0c52580a 100644 --- a/doc/release/upcoming_changes/14197.improvement.rst +++ b/doc/release/upcoming_changes/14197.improvement.rst @@ -1,9 +1,7 @@ -``method`` and ``use_factor`` options for `np.random.multivariate_normal` ----------------------------------------------------- -A ``method`` option is now available for `np.random.multivariate_normal` with -possible values {'svd', 'eigh', 'cholesky'}. To use it, write -``np.random.multivariate_normal(..., method=<method>)``. Another option -``use_factor`` is now available which allows the user to pass a precomputed -factor of a covariance matrix in order to speed up computation. To use it, -write ``np.random.multivariate_normal(..., use_factor=True)``. The ``method`` -option is ignored when ``use_factor=True`` +``method`` keyword argument for `np.random.multivariate_normal` +--------------------------------------------------------------- +A ``method`` keyword argument is now available for +`np.random.multivariate_normal` with possible values +``{'svd', 'eigh', 'cholesky'}``. To use it, write +``np.random.multivariate_normal(..., method=<method>)``. + diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 13099c524..9d0d1e267 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -3331,7 +3331,7 @@ cdef class Generator: # Multivariate distributions: def multivariate_normal(self, mean, cov, size=None, check_valid='warn', - tol=1e-8, *, method='svd', use_factor=False): + tol=1e-8, *, method='svd'): """ multivariate_normal(mean, cov, size=None, check_valid='warn', tol=1e-8) @@ -3371,14 +3371,6 @@ cdef class Generator: .. versionadded:: 1.18.0 - use_factor : bool, optional - If set to True then cov argument is treated as a precomputed factor - matrix A such that `A @ A.T = cov`` holds true. This provides - significant speedups because the factorization of cov is avoided. - Note that when this argument is set to True, ``method`` is ignored. - - .. versionadded:: 1.18.0 - Returns ------- out : ndarray @@ -3425,11 +3417,7 @@ cdef class Generator: Note that the covariance matrix must be positive semidefinite (a.k.a. nonnegative-definite). Otherwise, the behavior of this method is - undefined and backwards compatibility is not guaranteed. When supplying - a factor `F` in place of the full covariance matrix the user is expected - to ensure that ``F @ F.T`` recovers the covariance matrix. This - also implies that a factor input computed using the Cholesky method - must be a lower-triangular matrix. + undefined and backwards compatibility is not guaranteed. References ---------- @@ -3452,15 +3440,6 @@ cdef class Generator: >>> y.shape (3, 3, 2) - We can also use a precomputed factor matrix of cov to speed up the - computation. This is very useful when one needs to generate random - values using the sample covariance matrix but different means. - >>> s, u = np.linalg.eigh(cov) - >>> A = u * np.sqrt(s) # factor matrix of cov using Eigendecomposition. - >>> z = rng.multivariate_normal(mean, A, (3, 3), use_factor=True) - >>> z.shape - (3, 3, 2) - The following is probably true, given that 0.6 is roughly twice the standard deviation: @@ -3484,13 +3463,10 @@ cdef class Generator: if len(mean.shape) != 1: raise ValueError("mean must be 1 dimensional") - matrix_type = "factor" if use_factor else "cov" if (len(cov.shape) != 2) or (cov.shape[0] != cov.shape[1]): - raise ValueError("{} must be 2 dimensional and square" - .format(matrix_type)) + raise ValueError("cov must be 2 dimensional and square") if mean.shape[0] != cov.shape[0]: - raise ValueError("mean and {} must have same length" - .format(matrix_type)) + raise ValueError("mean and cov must have same length") # Compute shape of output and create a matrix of independent # standard normally distributed random numbers. The matrix has rows @@ -3500,11 +3476,6 @@ cdef class Generator: final_shape.append(mean.shape[0]) x = self.standard_normal(final_shape).reshape(-1, mean.shape[0]) - if use_factor: - x = mean + np.dot(x, cov) - x.shape = tuple(final_shape) - return x - # Transform matrix of standard normals into matrix where each row # contains multivariate normals with the desired covariance. # Compute A such that dot(transpose(A),A) == cov. diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index 3b92f17f0..70c8851fc 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -992,10 +992,6 @@ class TestRandomDist(object): random = Generator(MT19937(self.seed)) actual_chol = random.multivariate_normal(mean, cov, size, method='cholesky') - # the factor matrix is the same for all methods - random = Generator(MT19937(self.seed)) - actual_factor = random.multivariate_normal(mean, cov, size, - use_factor=True) desired = np.array([[[-1.747478062846581, 11.25613495182354 ], [-0.9967333370066214, 10.342002097029821 ]], [[ 0.7850019631242964, 11.181113712443013 ], @@ -1006,7 +1002,6 @@ class TestRandomDist(object): assert_array_almost_equal(actual_svd, desired, decimal=15) assert_array_almost_equal(actual_eigh, desired, decimal=15) assert_array_almost_equal(actual_chol, desired, decimal=15) - assert_array_almost_equal(actual_factor, desired, decimal=15) # Check for default size, was raising deprecation warning random = Generator(MT19937(self.seed)) @@ -1017,18 +1012,10 @@ class TestRandomDist(object): actual_chol = random.multivariate_normal(mean, cov, method='cholesky') # the factor matrix is the same for all methods random = Generator(MT19937(self.seed)) - actual_factor = random.multivariate_normal(mean, cov, use_factor=True) desired = np.array([-1.747478062846581, 11.25613495182354]) assert_array_almost_equal(actual_svd, desired, decimal=15) assert_array_almost_equal(actual_eigh, desired, decimal=15) assert_array_almost_equal(actual_chol, desired, decimal=15) - assert_array_almost_equal(actual_factor, desired, decimal=15) - - # test if raises ValueError when non-square factor is used - non_square_factor = [[1, 0], [0, 1], [1, 0]] - assert_raises(ValueError, random.multivariate_normal, mean, - non_square_factor, use_factor=True) - # Check that non symmetric covariance input raises exception when # check_valid='raises' if using default svd method. mean = [0, 0] @@ -1036,33 +1023,6 @@ class TestRandomDist(object): assert_raises(ValueError, random.multivariate_normal, mean, cov, check_valid='raise') - # Check if each method used with use_factor=False returns the same - # output when used with use_factor=True - cov = [[2, 1], [1, 2]] - random = Generator(MT19937(self.seed)) - desired_svd = random.multivariate_normal(mean, cov) - u, s, vh = svd(cov) - svd_factor = np.sqrt(s)[:, None] * vh - random = Generator(MT19937(self.seed)) - actual_svd = random.multivariate_normal(mean, svd_factor.T, - use_factor=True) - random = Generator(MT19937(self.seed)) - desired_eigh = random.multivariate_normal(mean, cov, method='eigh') - s, u = eigh(cov) - eigh_factor = u * np.sqrt(s) - random = Generator(MT19937(self.seed)) - actual_eigh = random.multivariate_normal(mean, eigh_factor, - use_factor=True) - random = Generator(MT19937(self.seed)) - desired_chol = random.multivariate_normal(mean, cov, method='cholesky') - chol_factor = cholesky(cov) - random = Generator(MT19937(self.seed)) - actual_chol = random.multivariate_normal(mean, chol_factor, - use_factor=True) - assert_array_almost_equal(actual_svd, desired_svd, decimal=15) - assert_array_almost_equal(actual_eigh, desired_eigh, decimal=15) - assert_array_almost_equal(actual_chol, desired_chol, decimal=15) - # Check that non positive-semidefinite covariance warns with # RuntimeWarning cov = [[1, 2], [2, 1]] |