From 9f9112f9c331eb049625492c3e44a67fc140855f Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Tue, 25 Jan 2022 15:22:59 +0100 Subject: [PATCH 01/13] add SingularValueThreshold This Method provides 10x faster SVT estimation than the LowRankMatrix Operator. --- modopt/opt/proximity.py | 67 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/modopt/opt/proximity.py b/modopt/opt/proximity.py index e0f28e96..29fde8e3 100644 --- a/modopt/opt/proximity.py +++ b/modopt/opt/proximity.py @@ -14,6 +14,7 @@ import sys import numpy as np +import scipy as sp try: from sklearn.isotonic import isotonic_regression @@ -345,6 +346,72 @@ def _cost_method(self, *args, **kwargs): return cost_val +class SingularValueThreshold(ProximityParent): + r"""Singular Value Threshold operator. + + This is the proximity operator solving: + .. math:: arg min \tau||x||_* + 1/2||x||_F + """ + + def __init__(self, threshold, initial_rank, thresh_type="soft"): + self.threshold = threshold + self.rank = initial_rank + self.threshold_op = SparseThreshold(linear=Identity(), + weights=threshold, + thresh_type=thresh_type) + self._incre = 5 + + def _op_method(self, input_data, extra_factor=1.0): + """Perform singular values thresholding. + + Parameters + ---------- + data: ndarray + + Returns + ------- + data_thresholded: ndarray + The data with thresholded singular values. + """ + OK = False + data = cube2matrix(input_data) + s = self.rank + 1 + while not OK: + U, Sigma, VT = sp.sparse.linalg.svds(data, k=s) + OK = (Sigma[0] <= self.threshold or s == min(data.shape)) + s = min(s + self._incre, *data.shape) + Sigma = self.threshold_op.op(Sigma, extra_factor) + self.rank = np.count_nonzero(Sigma) + return (U[:, -self.rank:] * Sigma[-self.rank:]) @ VT[-self.rank:, :] + + def _cost_method(self, *args, **kwargs): + """Calculate low-rank component of the cost. + + This method returns the nuclear norm error of the deconvolved data in + matrix form. + + Parameters + ---------- + *args : tuple + Positional arguments + **kwargs : dict + Keyword arguments + + Returns + ------- + float + Low-rank cost component + + """ + cost_val = self.thresh * nuclear_norm(cube2matrix(args[0])) + + if 'verbose' in kwargs and kwargs['verbose']: + print(' - NUCLEAR NORM (X):', cost_val) + + return cost_val + + + class LinearCompositionProx(ProximityParent): """Proximity Operator of a Linear Composition. From 7356f600589c85dda6ba13cfe0057addc5e8485b Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Tue, 25 Jan 2022 15:50:18 +0100 Subject: [PATCH 02/13] linting --- modopt/opt/proximity.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/modopt/opt/proximity.py b/modopt/opt/proximity.py index 29fde8e3..af7b6064 100644 --- a/modopt/opt/proximity.py +++ b/modopt/opt/proximity.py @@ -27,6 +27,7 @@ from modopt.base.types import check_callable from modopt.interface.errors import warn from modopt.math.matrix import nuclear_norm +from modopt.opt.linear import Identity from modopt.signal.noise import thresh from modopt.signal.positivity import positive from modopt.signal.svd import svd_thresh, svd_thresh_coef @@ -353,12 +354,14 @@ class SingularValueThreshold(ProximityParent): .. math:: arg min \tau||x||_* + 1/2||x||_F """ - def __init__(self, threshold, initial_rank, thresh_type="soft"): + def __init__(self, threshold, initial_rank, thresh_type='soft'): self.threshold = threshold self.rank = initial_rank - self.threshold_op = SparseThreshold(linear=Identity(), - weights=threshold, - thresh_type=thresh_type) + self.threshold_op = SparseThreshold( + linear=Identity(), + weights=threshold, + thresh_type=thresh_type + ) self._incre = 5 def _op_method(self, input_data, extra_factor=1.0): @@ -366,20 +369,23 @@ def _op_method(self, input_data, extra_factor=1.0): Parameters ---------- - data: ndarray + input_data : numpy.ndarray + Input data array + extra_factor : float + Additional multiplication factor (default is ``1.0``) Returns ------- data_thresholded: ndarray The data with thresholded singular values. """ - OK = False - data = cube2matrix(input_data) + ok = False + matrix_data = cube2matrix(input_data) s = self.rank + 1 - while not OK: - U, Sigma, VT = sp.sparse.linalg.svds(data, k=s) - OK = (Sigma[0] <= self.threshold or s == min(data.shape)) - s = min(s + self._incre, *data.shape) + while not ok: + U, Sigma, VT = sp.sparse.linalg.svds(matrix_data, k=s) + ok = (Sigma[0] <= self.threshold or s == min(matrix_data.shape)) + s = min(s + self._incre, *matrix_data.shape) Sigma = self.threshold_op.op(Sigma, extra_factor) self.rank = np.count_nonzero(Sigma) return (U[:, -self.rank:] * Sigma[-self.rank:]) @ VT[-self.rank:, :] From f41badc544cb274a129b6028dd8cebe89a451f1d Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Tue, 1 Feb 2022 22:31:54 +0100 Subject: [PATCH 03/13] add test for fast computation. --- modopt/opt/proximity.py | 100 +++++++++------------------------------ modopt/signal/svd.py | 51 ++++++++++++++++++++ modopt/tests/test_opt.py | 12 +++++ 3 files changed, 86 insertions(+), 77 deletions(-) diff --git a/modopt/opt/proximity.py b/modopt/opt/proximity.py index af7b6064..efe4cc00 100644 --- a/modopt/opt/proximity.py +++ b/modopt/opt/proximity.py @@ -30,7 +30,7 @@ from modopt.opt.linear import Identity from modopt.signal.noise import thresh from modopt.signal.positivity import positive -from modopt.signal.svd import svd_thresh, svd_thresh_coef +from modopt.signal.svd import svd_thresh, svd_thresh_coef, svd_thresh_coef_fast class ProximityParent(object): @@ -270,6 +270,7 @@ def __init__( threshold, thresh_type='soft', lowr_type='standard', + initial_rank=None, operator=None, ): @@ -279,8 +280,9 @@ def __init__( self.operator = operator self.op = self._op_method self.cost = self._cost_method + self.rank = initial_rank - def _op_method(self, input_data, extra_factor=1.0): + def _op_method(self, input_data, extra_factor=1.0, rank=None): """Operator. This method returns the input data after the singular values have been @@ -292,22 +294,35 @@ def _op_method(self, input_data, extra_factor=1.0): Input data array extra_factor : float Additional multiplication factor (default is ``1.0``) - + rank: int, optional + An estimation of the rank to save computation in standard mode. + Else use an internal estimation. Returns ------- numpy.ndarray SVD thresholded data - + Raises + ------ + ValueError + if lowr_type is not in ``{'standard', 'ngole'} """ # Update threshold with extra factor. threshold = self.thresh * extra_factor - - if self.lowr_type == 'standard': + if self.lowr_type == 'standard' and self.rank is None and rank is None: data_matrix = svd_thresh( cube2matrix(input_data), threshold, thresh_type=self.thresh_type, ) + elif self.lowr_type == 'standard': + data_matrix, update_rank = svd_thresh_coef_fast( + cube2matrix(input_data), + threshold, + n_vals=rank or self.rank, + extra_vals=5, + thresh_type=self.thresh_type, + ) + self.rank = update_rank # save for future use elif self.lowr_type == 'ngole': data_matrix = svd_thresh_coef( @@ -316,6 +331,8 @@ def _op_method(self, input_data, extra_factor=1.0): threshold, thresh_type=self.thresh_type, ) + else: + raise ValueError("lowr_type should be standard, ngole or fast.") # Return updated data. return matrix2cube(data_matrix, input_data.shape[1:]) @@ -347,77 +364,6 @@ def _cost_method(self, *args, **kwargs): return cost_val -class SingularValueThreshold(ProximityParent): - r"""Singular Value Threshold operator. - - This is the proximity operator solving: - .. math:: arg min \tau||x||_* + 1/2||x||_F - """ - - def __init__(self, threshold, initial_rank, thresh_type='soft'): - self.threshold = threshold - self.rank = initial_rank - self.threshold_op = SparseThreshold( - linear=Identity(), - weights=threshold, - thresh_type=thresh_type - ) - self._incre = 5 - - def _op_method(self, input_data, extra_factor=1.0): - """Perform singular values thresholding. - - Parameters - ---------- - input_data : numpy.ndarray - Input data array - extra_factor : float - Additional multiplication factor (default is ``1.0``) - - Returns - ------- - data_thresholded: ndarray - The data with thresholded singular values. - """ - ok = False - matrix_data = cube2matrix(input_data) - s = self.rank + 1 - while not ok: - U, Sigma, VT = sp.sparse.linalg.svds(matrix_data, k=s) - ok = (Sigma[0] <= self.threshold or s == min(matrix_data.shape)) - s = min(s + self._incre, *matrix_data.shape) - Sigma = self.threshold_op.op(Sigma, extra_factor) - self.rank = np.count_nonzero(Sigma) - return (U[:, -self.rank:] * Sigma[-self.rank:]) @ VT[-self.rank:, :] - - def _cost_method(self, *args, **kwargs): - """Calculate low-rank component of the cost. - - This method returns the nuclear norm error of the deconvolved data in - matrix form. - - Parameters - ---------- - *args : tuple - Positional arguments - **kwargs : dict - Keyword arguments - - Returns - ------- - float - Low-rank cost component - - """ - cost_val = self.thresh * nuclear_norm(cube2matrix(args[0])) - - if 'verbose' in kwargs and kwargs['verbose']: - print(' - NUCLEAR NORM (X):', cost_val) - - return cost_val - - - class LinearCompositionProx(ProximityParent): """Proximity Operator of a Linear Composition. diff --git a/modopt/signal/svd.py b/modopt/signal/svd.py index 41241b33..dd09e7cd 100644 --- a/modopt/signal/svd.py +++ b/modopt/signal/svd.py @@ -10,6 +10,7 @@ import numpy as np from scipy.linalg import svd +from scipy.sparse.linalg import svds from modopt.base.transform import matrix2cube from modopt.interface.errors import warn @@ -200,6 +201,56 @@ def svd_thresh(input_data, threshold=None, n_pc=None, thresh_type='hard'): return np.dot(u_vec, np.dot(s_new, v_vec)) +def svd_thresh_coef_fast( + input_data, + threshold, + n_vals=None, + extra_vals=5, + thresh_type='hard'): + """Threshold the singular values coefficients. + + This method threshold the input data by using singular value decomposition, + but only computing the the greastest ``n_vals`` values. + + Parameters + ---------- + input_data : numpy.ndarray + Input data array, 2D matrix + Operator class instance + threshold : float or numpy.ndarray + Threshold value(s) + n_vals: int, default None + Number of singular values to compute. + If None, compute all singular values. + extra_vals: int, optional + If the number of values computed is not enough to perform thresholding, + recompute by using ``n_vals + extra_vals`` (default is ``5``) + thresh_type : {'hard', 'soft'} + Type of noise to be added (default is ``'hard'``) + + Returns + ------- + numpy.ndarray + Thresholded data + int + the estimated rank after thresholding. + """ + n_vals = n_vals or min(input_data.shape) - 1 + ok = False + while not ok: + (u_vec, s_values, v_vec) = svds(input_data, k=n_vals) + ok = (s_values[0] <= threshold or n_vals == min(input_data.shape) - 1) + n_vals = min(n_vals + extra_vals, *input_data.shape) + + s_values = thresh(s_values, + threshold, + threshold_type=thresh_type) + rank = np.count_nonzero(s_values) + return (np.dot(u_vec[:, -rank:] * s_values[-rank:], + v_vec[-rank:, :]), + rank) + + def svd_thresh_coef(input_data, operator, threshold, thresh_type='hard'): """Threshold the singular values coefficients. diff --git a/modopt/tests/test_opt.py b/modopt/tests/test_opt.py index 3c33c948..d5547783 100644 --- a/modopt/tests/test_opt.py +++ b/modopt/tests/test_opt.py @@ -675,6 +675,11 @@ def setUp(self): weights, ) self.lowrank = proximity.LowRankMatrix(10.0, thresh_type='hard') + self.lowrank_rank = proximity.LowRankMatrix( + 10.0, + initial_rank=1, + thresh_type='hard', + ) self.lowrank_ngole = proximity.LowRankMatrix( 10.0, lowr_type='ngole', @@ -763,6 +768,8 @@ def tearDown(self): self.positivity = None self.sparsethresh = None self.lowrank = None + self.lowrank_rank = None + self.lowrank_ngole = None self.combo = None self.data1 = None self.data2 = None @@ -841,6 +848,11 @@ def test_low_rank_matrix(self): err_msg='Incorrect low rank operation: standard', ) + npt.assert_almost_equal( + self.lowrank_rank.op(self.data3), + self.data4, + err_msg='Incorrect low rank operation: standard with rank', + ) npt.assert_almost_equal( self.lowrank_ngole.op(self.data3), self.data5, From 153967ae79f525b52ecb4df75594756999cc8764 Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Tue, 1 Feb 2022 22:50:39 +0100 Subject: [PATCH 04/13] flake8 compliance --- modopt/opt/proximity.py | 8 ++++---- modopt/signal/svd.py | 34 +++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/modopt/opt/proximity.py b/modopt/opt/proximity.py index efe4cc00..d3b79bfb 100644 --- a/modopt/opt/proximity.py +++ b/modopt/opt/proximity.py @@ -14,7 +14,6 @@ import sys import numpy as np -import scipy as sp try: from sklearn.isotonic import isotonic_regression @@ -27,7 +26,6 @@ from modopt.base.types import check_callable from modopt.interface.errors import warn from modopt.math.matrix import nuclear_norm -from modopt.opt.linear import Identity from modopt.signal.noise import thresh from modopt.signal.positivity import positive from modopt.signal.svd import svd_thresh, svd_thresh_coef, svd_thresh_coef_fast @@ -297,14 +295,16 @@ def _op_method(self, input_data, extra_factor=1.0, rank=None): rank: int, optional An estimation of the rank to save computation in standard mode. Else use an internal estimation. + Returns ------- numpy.ndarray SVD thresholded data + Raises ------ ValueError - if lowr_type is not in ``{'standard', 'ngole'} + if lowr_type is not in ``{'standard', 'ngole'}`` """ # Update threshold with extra factor. threshold = self.thresh * extra_factor @@ -332,7 +332,7 @@ def _op_method(self, input_data, extra_factor=1.0, rank=None): thresh_type=self.thresh_type, ) else: - raise ValueError("lowr_type should be standard, ngole or fast.") + raise ValueError('lowr_type should be standard or ngole') # Return updated data. return matrix2cube(data_matrix, input_data.shape[1:]) diff --git a/modopt/signal/svd.py b/modopt/signal/svd.py index dd09e7cd..befa83c5 100644 --- a/modopt/signal/svd.py +++ b/modopt/signal/svd.py @@ -202,11 +202,12 @@ def svd_thresh(input_data, threshold=None, n_pc=None, thresh_type='hard'): def svd_thresh_coef_fast( - input_data, - threshold, - n_vals=None, - extra_vals=5, - thresh_type='hard'): + input_data, + threshold, + n_vals=-1, + extra_vals=5, + thresh_type='hard', +): """Threshold the singular values coefficients. This method threshold the input data by using singular value decomposition, @@ -219,7 +220,7 @@ def svd_thresh_coef_fast( Operator class instance threshold : float or numpy.ndarray Threshold value(s) - n_vals: int, default None + n_vals: int, optional Number of singular values to compute. If None, compute all singular values. extra_vals: int, optional @@ -235,20 +236,27 @@ def svd_thresh_coef_fast( int the estimated rank after thresholding. """ - n_vals = n_vals or min(input_data.shape) - 1 + if n_vals == -1: + n_vals = min(input_data.shape) - 1 ok = False while not ok: (u_vec, s_values, v_vec) = svds(input_data, k=n_vals) ok = (s_values[0] <= threshold or n_vals == min(input_data.shape) - 1) n_vals = min(n_vals + extra_vals, *input_data.shape) - s_values = thresh(s_values, - threshold, - threshold_type=thresh_type) + s_values = thresh( + s_values, + threshold, + threshold_type=thresh_type, + ) rank = np.count_nonzero(s_values) - return (np.dot(u_vec[:, -rank:] * s_values[-rank:], - v_vec[-rank:, :]), - rank) + return ( + np.dot( + u_vec[:, -rank:] * s_values[-rank:], + v_vec[-rank:, :], + ), + rank, + ) def svd_thresh_coef(input_data, operator, threshold, thresh_type='hard'): From d0ff58dcb9e8fdf7c9c284bf44fed31f872d5ced Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Wed, 2 Feb 2022 09:05:19 +0100 Subject: [PATCH 05/13] Ignore DAR000 Error. --- setup.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index eada1b8c..cabd35a0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -58,7 +58,8 @@ per-file-ignores = #Justification: Needed to import matplotlib.pyplot modopt/plot/cost_plot.py: N802,WPS301 #Todo: Investigate possible bug in find_n_pc function - modopt/signal/svd.py: WPS345 + #Todo: Investigate darglint error + modopt/signal/svd.py: WPS345, DAR000 #Todo: Check security of using system executable call modopt/signal/wavelet.py: S404,S603 #Todo: Clean up tests From 853891059d7d71402a38fde707603833b073185b Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Comby <77174042+paquiteau@users.noreply.github.com> Date: Wed, 2 Feb 2022 12:00:38 +0100 Subject: [PATCH 06/13] Update modopt/signal/svd.py tuples in docstring Co-authored-by: Samuel Farrens --- modopt/signal/svd.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modopt/signal/svd.py b/modopt/signal/svd.py index befa83c5..d09b27d3 100644 --- a/modopt/signal/svd.py +++ b/modopt/signal/svd.py @@ -231,10 +231,8 @@ def svd_thresh_coef_fast( Returns ------- - numpy.ndarray - Thresholded data - int - the estimated rank after thresholding. + tuple + The thresholded data (numpy.ndarray) and the estimated rank after thresholding (int) """ if n_vals == -1: n_vals = min(input_data.shape) - 1 From 2b79d46ca01e36dba0ef3f442bc311744f39d387 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Comby <77174042+paquiteau@users.noreply.github.com> Date: Wed, 2 Feb 2022 12:00:53 +0100 Subject: [PATCH 07/13] Update modopt/signal/svd.py typo Co-authored-by: Samuel Farrens --- modopt/signal/svd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modopt/signal/svd.py b/modopt/signal/svd.py index d09b27d3..1c883a9d 100644 --- a/modopt/signal/svd.py +++ b/modopt/signal/svd.py @@ -210,7 +210,7 @@ def svd_thresh_coef_fast( ): """Threshold the singular values coefficients. - This method threshold the input data by using singular value decomposition, + This method thresholds the input data by using singular value decomposition, but only computing the the greastest ``n_vals`` values. Parameters From 6f8f0b0d317db77fec0e48e40395e2e96630988a Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Comby <77174042+paquiteau@users.noreply.github.com> Date: Wed, 2 Feb 2022 12:01:10 +0100 Subject: [PATCH 08/13] Update modopt/opt/proximity.py typo Co-authored-by: Samuel Farrens --- modopt/opt/proximity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modopt/opt/proximity.py b/modopt/opt/proximity.py index d3b79bfb..981bef0a 100644 --- a/modopt/opt/proximity.py +++ b/modopt/opt/proximity.py @@ -294,7 +294,7 @@ def _op_method(self, input_data, extra_factor=1.0, rank=None): Additional multiplication factor (default is ``1.0``) rank: int, optional An estimation of the rank to save computation in standard mode. - Else use an internal estimation. + An estimation of the rank to save computation time in standard mode, if not set an internal estimation is used. Returns ------- From 09c4f89a1ec2cfb7e8448df760a03d96c72c2d44 Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Wed, 2 Feb 2022 12:06:09 +0100 Subject: [PATCH 09/13] update docstring --- modopt/opt/proximity.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modopt/opt/proximity.py b/modopt/opt/proximity.py index 981bef0a..f8f368ef 100644 --- a/modopt/opt/proximity.py +++ b/modopt/opt/proximity.py @@ -237,6 +237,9 @@ class LowRankMatrix(ProximityParent): lowr_type : {'standard', 'ngole'} Low-rank implementation (options are 'standard' or 'ngole', default is 'standard') + initial_rank: int, optional + Initial guess of the rank of future input_data. + If provided this will save computation time. operator : class Operator class ('ngole' only) @@ -293,8 +296,8 @@ def _op_method(self, input_data, extra_factor=1.0, rank=None): extra_factor : float Additional multiplication factor (default is ``1.0``) rank: int, optional - An estimation of the rank to save computation in standard mode. - An estimation of the rank to save computation time in standard mode, if not set an internal estimation is used. + Estimation of the rank to save computation time in standard mode, + if not set an internal estimation is used. Returns ------- From 7ad88456c5f22f767a2297ce6aaed83261a2ef40 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Comby <77174042+paquiteau@users.noreply.github.com> Date: Thu, 3 Feb 2022 09:15:54 +0100 Subject: [PATCH 10/13] fix isort --- modopt/signal/svd.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modopt/signal/svd.py b/modopt/signal/svd.py index 1c883a9d..970add8d 100644 --- a/modopt/signal/svd.py +++ b/modopt/signal/svd.py @@ -9,14 +9,12 @@ """ import numpy as np -from scipy.linalg import svd -from scipy.sparse.linalg import svds - from modopt.base.transform import matrix2cube from modopt.interface.errors import warn from modopt.math.convolve import convolve from modopt.signal.noise import thresh - +from scipy.linalg import svd +from scipy.sparse.linalg import svds def find_n_pc(u_vec, factor=0.5): """Find number of principal components. From ef62aa03c07c1e8481e363a0239c7ab29582896e Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Comby <77174042+paquiteau@users.noreply.github.com> Date: Thu, 3 Feb 2022 09:59:42 +0100 Subject: [PATCH 11/13] Update modopt/signal/svd.py Co-authored-by: Samuel Farrens --- modopt/signal/svd.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modopt/signal/svd.py b/modopt/signal/svd.py index 970add8d..6ea2a893 100644 --- a/modopt/signal/svd.py +++ b/modopt/signal/svd.py @@ -208,8 +208,9 @@ def svd_thresh_coef_fast( ): """Threshold the singular values coefficients. - This method thresholds the input data by using singular value decomposition, - but only computing the the greastest ``n_vals`` values. + This method thresholds the input data by using singular value + decomposition, but only computing the the greastest ``n_vals`` + values. Parameters ---------- From 791583bf3ae41907516c1c9412997542164635e4 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Comby <77174042+paquiteau@users.noreply.github.com> Date: Thu, 3 Feb 2022 09:59:59 +0100 Subject: [PATCH 12/13] Update modopt/signal/svd.py Co-authored-by: Samuel Farrens --- modopt/signal/svd.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modopt/signal/svd.py b/modopt/signal/svd.py index 6ea2a893..4f30ada9 100644 --- a/modopt/signal/svd.py +++ b/modopt/signal/svd.py @@ -231,7 +231,8 @@ def svd_thresh_coef_fast( Returns ------- tuple - The thresholded data (numpy.ndarray) and the estimated rank after thresholding (int) + The thresholded data (numpy.ndarray) and the estimated rank after + thresholding (int) """ if n_vals == -1: n_vals = min(input_data.shape) - 1 From ca5524af51608ba4eb79dda8dd7114e8877a2c1f Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Mon, 7 Feb 2022 08:49:48 +0100 Subject: [PATCH 13/13] run isort --- modopt/signal/svd.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modopt/signal/svd.py b/modopt/signal/svd.py index 4f30ada9..6dcb9eda 100644 --- a/modopt/signal/svd.py +++ b/modopt/signal/svd.py @@ -9,12 +9,14 @@ """ import numpy as np +from scipy.linalg import svd +from scipy.sparse.linalg import svds + from modopt.base.transform import matrix2cube from modopt.interface.errors import warn from modopt.math.convolve import convolve from modopt.signal.noise import thresh -from scipy.linalg import svd -from scipy.sparse.linalg import svds + def find_n_pc(u_vec, factor=0.5): """Find number of principal components. @@ -209,7 +211,7 @@ def svd_thresh_coef_fast( """Threshold the singular values coefficients. This method thresholds the input data by using singular value - decomposition, but only computing the the greastest ``n_vals`` + decomposition, but only computing the the greastest ``n_vals`` values. Parameters @@ -231,7 +233,7 @@ def svd_thresh_coef_fast( Returns ------- tuple - The thresholded data (numpy.ndarray) and the estimated rank after + The thresholded data (numpy.ndarray) and the estimated rank after thresholding (int) """ if n_vals == -1: