def from_data_mapper_and_regularization( cls, visibilities: vis.Visibilities, noise_map: vis.VisibilitiesNoiseMap, transformer: trans.TransformerNUFFT, mapper: typing.Union[mappers.MapperRectangular, mappers.MapperVoronoi], regularization: reg.Regularization, settings=SettingsInversion(), ): regularization_matrix = regularization.regularization_matrix_from_mapper( mapper=mapper ) Aop = pylops.MatrixMult(sparse.bsr_matrix(mapper.mapping_matrix)) Fop = transformer Op = Fop * Aop curvature_matrix_approx = np.multiply( np.sum(noise_map.weight_list_ordered_1d), mapper.mapping_matrix.T @ mapper.mapping_matrix, ) preconditioner_matrix = np.add(curvature_matrix_approx, regularization_matrix) preconditioner_inverse_matrix = np.linalg.inv(preconditioner_matrix) MOp = pylops.MatrixMult(sparse.bsr_matrix(preconditioner_inverse_matrix)) log_det_curvature_reg_matrix_term = 2.0 * np.sum( np.log(np.diag(np.linalg.cholesky(preconditioner_matrix))) ) reconstruction = pylops.NormalEquationsInversion( Op=Op, Regs=None, epsNRs=[1.0], data=visibilities.ordered_1d, Weight=pylops.Diagonal(diag=noise_map.weight_list_ordered_1d), NRegs=[pylops.MatrixMult(sparse.bsr_matrix(regularization_matrix))], M=MOp, tol=settings.tolerance, atol=settings.tolerance, **dict(maxiter=settings.maxiter), ) return InversionInterferometerLinearOperator( visibilities=visibilities, noise_map=noise_map, transformer=transformer, mapper=mapper, regularization=regularization, regularization_matrix=regularization_matrix, reconstruction=np.real(reconstruction), settings=settings, log_det_curvature_reg_matrix_term=log_det_curvature_reg_matrix_term, )
def inpainting_ista_once(Y, D, maskvec, n_nonzero_coefs, sigma=0.001, rc_min=0.01): coef = np.zeros((D.shape[1], Y.shape[1])) for k in tqdm(range(Y.shape[1])): nonzero_pos = np.nonzero(maskvec[:, k])[0] D_sub = D[nonzero_pos, :] Y_sub = Y[:, k:k + 1][nonzero_pos] # ISTA coef[:, k] = ISTA_Inpainting2(D_sub, Y_sub, n_nonzero_coefs, max_iter=1000)[:, 0] coef[:, k] = pylops.optimization.sparsity.ISTA(pylops.MatrixMult(D_sub), Y_sub[:, 0], 5000, eps=1e-2, tol=1e-3, returninfo=True)[0] return coef
def decode_lasso(self, results): #lasso = LassoLars(alpha=self.l) #lasso = Lasso(alpha=self.l, max_iter=1000) #lasso = LassoCV(n_alphas=100) #lasso.fit(self.M.T, results) temp_mat = (self.M.T).astype(float) #temp_mat=np.matrix(temp_mat) #print(np.shape(temp_mat)) #print('best lambda = ', lasso.alpha_) #answer = lasso.coef_ #Using ISTA #temp_mat=pylops.MatrixMult(temp_mat) #answer = pylops.optimization.sparsity.ISTA(temp_mat, results, 10000, eps=self.l, tol=0, returninfo=True)[0] #Using OMP #print(type(temp_mat)) temp_mat = pylops.MatrixMult(temp_mat) #print(temp_mat) answer = pylops.optimization.sparsity.OMP(temp_mat, results, 10000, sigma=0.4)[0] #Using spgl1 lasso #[answer,r,g,info] = spg.spg_lasso(temp_mat,results,1e-4); #Using ISTA function #answer = fista(temp_mat, results, self.l, 10000)[0] #print(answer) score = math.sqrt(np.linalg.norm(answer - self.conc) / self.d) infected = (answer != 0.).astype(np.int32) # Compute stats tpos = (infected * self.arr) fneg = (1 - infected) * self.arr fpos = infected * (1 - self.arr) tp = sum(tpos) fp = sum(fpos) fn = sum(fneg) return score, tp, fp, fn
plt.close('all') np.random.seed(0) ############################################################################### # Let's start with a simple example, where we create a dense mixing matrix # and a sparse signal and we use OMP and ISTA to recover such a signal. # Note that the mixing matrix leads to an underdetermined system of equations # (:math:`N < M`) so being able to add some extra prior information regarding # the sparsity of our desired model is essential to be able to invert # such a system. N, M = 15, 20 A = np.random.randn(N, M) A = A / np.linalg.norm(A, axis=0) Aop = pylops.MatrixMult(A) x = np.random.rand(M) x[x < 0.9] = 0 y = Aop * x # MP/OMP eps = 1e-2 maxit = 500 x_mp = pylops.optimization.sparsity.OMP(Aop, y, maxit, niter_inner=0, sigma=1e-4)[0] x_omp = pylops.optimization.sparsity.OMP(Aop, y, maxit, sigma=1e-4)[0]
epsI = np.sqrt(1e-4) xne = \ pylops.optimization.leastsquares.NormalEquationsInversion(Rop, [D2op], y, epsI=epsI, epsRs=[epsR], returninfo=False, **dict(maxiter=50)) ############################################################################### # Note that in case we have access to a fast implementation for the chain of # forward and adjoint for the regularization operator # (i.e., :math:`\nabla^T\nabla`), we can modify our call to # :py:func:`pylops.optimization.leastsquares.NormalEquationsInversion` as # follows: ND2op = pylops.MatrixMult((D2op.H * D2op).tosparse()) # mimic fast D^T D xne1 = \ pylops.optimization.leastsquares.NormalEquationsInversion(Rop, [], y, NRegs=[ND2op], epsI=epsI, epsNRs=[epsR], returninfo=False, **dict(maxiter=50)) ############################################################################### # We can do the same while using # :py:func:`pylops.optimization.leastsquares.RegularizedInversion` # which solves the following augmented problem # # .. math::
In this example we will consider the BlockDiagonal operator which contains :class:`pylops.basicoperators.MatrixMult` operators along its main diagonal. """ import numpy as np import matplotlib.pyplot as plt import pylops plt.close('all') ############################################################################### # Let's start by creating N MatrixMult operators and the BlockDiag operator N = 100 Nops = 32 Ops = [ pylops.MatrixMult(np.random.normal(0., 1., (N, N))) for _ in range(Nops) ] Op = pylops.BlockDiag(Ops, nproc=1) ############################################################################### # We can now perform a scalability test on the forward operation workers = [2, 3, 4] compute_times, speedup = \ pylops.utils.multiproc.scalability_test(Op, np.ones(Op.shape[1]), workers=workers, forward=True) plt.figure(figsize=(12, 3)) plt.plot(workers, speedup, 'ko-') plt.xlabel('# Workers') plt.ylabel('Speed Up') plt.title('Forward scalability test')
import numpy as np import matplotlib.pyplot as plt import pylops plt.close('all') warnings.filterwarnings('ignore') ############################################################################### # Let's define a matrix :math:`\mathbf{A}` or size (``N`` and ``M``) and # fill the matrix with random numbers N, M = 20, 10 A = np.random.normal(0, 1, (N, M)) Aop = pylops.MatrixMult(A, dtype='float64') x = np.ones(M) ############################################################################### # We can now use the cgls solver to invert this matrix y = Aop * x xest, istop, nit, r1norm, r2norm, cost_cgls = \ pylops.optimization.solver.cgls(Aop, y, x0=np.zeros_like(x), niter=10, tol=1e-10, show=True) print('x= %s' % x) print('cgls solution xest= %s' % xest) ###############################################################################
import matplotlib.pyplot as plt import matplotlib.gridspec as pltgs import pylops from pylops.utils import dottest plt.close('all') ############################################################################### # Let's start with something very simple. We will make a :py:class:`pylops.MatrixMult` # operator and verify that its implementation passes the dot-test. # For this time, we will do this step-by-step, replicating what happens in the # :py:func:`pylops.utils.dottest` routine. N, M = 5, 3 Mat = np.arange(N * M).reshape(N, M) Op = pylops.MatrixMult(Mat) v = np.random.randn(N) u = np.random.randn(M) # Op * u y = Op.matvec(u) # Op'* v x = Op.rmatvec(v) yy = np.dot(y, v) # (Op * u)' * v xx = np.dot(u, x) # u' * (Op' * v) print('Dot-test %e' % np.abs((yy - xx) / ((yy + xx + 1e-15) / 2))) ###############################################################################
from scipy.sparse import rand from scipy.sparse.linalg import lsqr import pylops plt.close("all") warnings.filterwarnings("ignore") # sphinx_gallery_thumbnail_number = 2 ############################################################################### # Let's define the sizes of the matrix :math:`\mathbf{A}` (``N`` and ``M``) and # fill the matrix with random numbers N, M = 20, 20 A = np.random.normal(0, 1, (N, M)) Aop = pylops.MatrixMult(A, dtype="float64") x = np.ones(M) ############################################################################### # We can now apply the forward operator to create the data vector :math:`\mathbf{y}` # and use ``/`` to solve the system by means of an explicit solver. y = Aop * x xest = Aop / y ############################################################################### # Let's visually plot the system of equations we just solved. gs = pltgs.GridSpec(1, 6) fig = plt.figure(figsize=(7, 3)) ax = plt.subplot(gs[0, 0])
import matplotlib.pyplot as plt import numpy as np import pylops plt.close("all") warnings.filterwarnings("ignore") ############################################################################### # Let's define a matrix :math:`\mathbf{A}` or size (``N`` and ``M``) and # fill the matrix with random numbers N, M = 20, 10 A = np.random.normal(0, 1, (N, M)) Aop = pylops.MatrixMult(A, dtype="float64") x = np.ones(M) ############################################################################### # We can now use the cgls solver to invert this matrix y = Aop * x xest, istop, nit, r1norm, r2norm, cost_cgls = pylops.optimization.solver.cgls( Aop, y, x0=np.zeros_like(x), niter=10, tol=1e-10, show=True ) print("x= %s" % x) print("cgls solution xest= %s" % xest) ###############################################################################
def decode_lasso(self, results, algo='lasso', prefer_recall=False, compute_stats=True): determined = 0 overdetermined = 0 # Add check if system is determined or overdetermined if self.t == self.n: determined = 1 elif self.t > self.n: overdetermined = 1 prob1 = None prob0 = None answer_high_precision = np.zeros(self.n) if algo == 'lasso': #lasso = LassoLars(alpha=self.l) lasso = Lasso(alpha=self.l, max_iter=10000) #lasso = LassoCV(n_alphas=100) lasso.fit(self.M.T, results) #print('best lambda = ', lasso.alpha_) answer = lasso.coef_ elif algo == 'OMP': temp_mat = (self.M.T).astype(float) temp_mat = pylops.MatrixMult(temp_mat) answer = pylops.optimization.sparsity.OMP(temp_mat, results, 10000, sigma=0.001)[0] elif algo == 'NNOMP': # Max d that can be detected by NNOMP is equal to number of rows answer = nnompcv.nnomp(self.M.T.astype('float'), 0, results, 0, self.t, cv=False) elif algo == 'NNOMPCV': temp_mat = (self.M.T).astype(float) mr = math.ceil(0.9 * temp_mat.shape[1]) m = temp_mat.shape[1] Ar = temp_mat[0:mr, :] Acv = temp_mat[mr + 1:m, :] yr = results[0:mr] ycv = results[mr + 1:m] #print('yo') # Max d that can be detected by NNOMP is equal to number of rows answer = nnompcv.nnomp(Ar, Acv, yr, ycv, self.t, cv=True) elif algo == 'NNOMP_loo_cv': answer, prob1, prob0 = self.decode_nnomp_multi_split_cv( results, 'loo_splits') elif algo == 'NNOMP_random_cv': # Skip cross-validation for really small cases if np.sum(results) == 0: answer = np.zeros(self.n) elif self.t < 4: # Max d that can be detected by NNOMP is equal to number of rows answer = nnompcv.nnomp(self.M.T.astype('float'), 0, results, 0, self.t, cv=False) else: answer, prob1, prob0 = self.decode_nnomp_multi_split_cv( results, 'random_splits') elif algo.startswith('combined_COMP_'): #print('Doing ', algo) l = len('combined_COMP_') secondary_algo = algo[l:] answer, infected, prob1, prob0, determined, overdetermined =\ self.decode_comp_combined(results, secondary_algo, compute_stats=compute_stats) elif algo.startswith('precise_SBL_'): # e.g. combined_SBL_clustered_combined_COMP_SBL # e.g. combined_SBL_clustered_COMP l = len('precise_SBL_') primary_algo = 'combined_COMP_SBL_clustered' secondary_algo = algo[l:] assert secondary_algo not in [ 'SBL_clustered', 'combined_COMP_SBL_clustered' ] y = results # First run SBL_clustered to get precise results # Then run secondary algorithm to get high recall results # "answer" is those from high recall ones. # we'll create "answer_precise_SBL" and "infected_precise_SBL". # infected_dd will become union of infected_dd and infected_precise_SBL # Hence surep will contain results from SBL_clustered as well. answer_high_precision = self.get_high_precision_algo_answer( primary_algo, y) answer = self.get_high_recall_algo_answer(secondary_algo, y) elif algo == 'SBL': A = self.M.T y = results answer = sbl.sbl(A, y) elif algo == 'l1ls': A = self.M.T y = results if np.all(y == 0): answer = np.zeros(self.n) else: answer = l1ls.l1ls(A, y, self.l, self.tau) elif algo == 'l1ls_cv': A = self.M.T y = results sigval = 0.01 * np.mean(y) if np.all(y == 0): answer = np.zeros(self.n) else: answer = l1ls.l1ls_cv(A, y, sigval, self.tau) elif algo in algos.algo_dict: params = {'A': self.M.T, 'y': results} res = algos.algo_dict[algo](params) answer = res["x_est"] else: raise ValueError('No such algorithm %s' % algo) score = np.linalg.norm(answer - self.conc) / math.sqrt(self.t) infected = (answer != 0.).astype(np.int32) if prob1 is None: assert prob0 is None prob1 = np.array(infected) prob0 = np.array(1 - infected) num_unconfident_negatives = 0 if prefer_recall: # Report the unconfident -ves as +ve negatives = (infected == 0).astype(np.int32) unconfident_negatives = negatives * (prob0 < 0.6).astype(np.int32) num_unconfident_negatives = np.sum(unconfident_negatives) infected = infected + unconfident_negatives # Get definite defects y = results bool_y = (y > 0).astype(np.int32) _infected_comp, infected_dd, _score, _tp, _fp, _fn, surep, _unsurep, _ =\ self.decode_comp_new(bool_y, compute_stats=compute_stats) #print(infected.shape) #print(infected_dd.shape) # Compare definite defects with ours to detect if our algorithm doesn't # detect something that should definitely have been detected wrongly_undetected = np.sum(infected_dd - infected_dd * infected) # Add infections from high precision algo infected_high_precision = (answer_high_precision > 0).astype(np.int32) # For ease of implementation we add above to infected_dd. This will become # sure_list later infected_dd = (infected_dd + infected_high_precision > 0).astype( np.int32) infected = (infected + infected_dd > 0).astype(np.int32) if compute_stats: # re-compute surep from above infected_dd surep = np.sum(infected_dd) # Compute stats tpos = (infected * self.arr) fneg = (1 - infected) * self.arr fpos = infected * (1 - self.arr) tp = sum(tpos) fp = sum(fpos) fn = sum(fneg) # The following assertion is no longer valid due to infected_high_precision # being added to infected_dd, for precise_SBL_FOO algorithms. We'll ignore # the assertion for now. try: assert surep <= tp except: if not algo.startswith('precise_SBL_'): raise # Following stat is not valid in some cases when using precise_SBL_ unsurep = tp + fp - surep else: tp = 0 fp = 0 fn = 0 surep = 0 unsurep = 0 num_infected_in_test = np.zeros(self.t, dtype=np.int32) for test in range(self.t): for person in range(self.n): if infected[person] > 0 and self.M[person, test] == 1: num_infected_in_test[test] += 1 return answer, infected, infected_dd, prob1, prob0, score, tp, fp, fn,\ num_unconfident_negatives, determined, overdetermined, surep,\ unsurep, wrongly_undetected, num_infected_in_test
import pylops plt.close('all') np.random.seed(0) ############################################################################### # Let's start with a simple example, where we create a dense mixing matrix # and a sparse signal and we use OMP and ISTA to recover such a signal. # Note that the mixing matrix leads to an underdetermined system of equations # (:math:`N < M`) so being able to add some extra prior information regarding # the sparsity of our desired model is essential to be able to invert # such a system. N, M = 15, 20 Aop = pylops.MatrixMult(np.random.randn(N, M)) x = np.random.rand(M) x[x < 0.9] = 0 y = Aop * x # ISTA eps = 0.5 maxit = 1000 x_omp = pylops.optimization.sparsity.OMP(Aop, y, maxit, sigma=1e-4)[0] x_ista = pylops.optimization.sparsity.ISTA(Aop, y, maxit, eps=eps, tol=0, returninfo=True)[0]
import matplotlib.pyplot as plt import matplotlib.gridspec as pltgs import pylops plt.close('all') # sphinx_gallery_thumbnail_number = 2 ############################################################################### # Let's define the sizes of the matrix :math:`\mathbf{A}` (``N`` and ``M``) and # fill the matrix with random numbers N, M = 20, 20 A = np.random.normal(0, 1, (N, M)) Aop = pylops.MatrixMult(A, dtype='float64') x = np.ones(M) ############################################################################### # We can now apply the forward operator to create the data vector :math:`\mathbf{y}` # and use ``/`` to solve the system by means of an explicit solver. y = Aop * x xest = Aop / y ############################################################################### # Let's visually plot the system of equations we just solved. gs = pltgs.GridSpec(1, 6) fig = plt.figure(figsize=(7, 3)) ax = plt.subplot(gs[0, 0])
plt.plot(x, x, 'k', lw=2, label='x') plt.plot(x, xp, 'r', lw=2, label='prox(x)') plt.plot(x, xdp, 'b', lw=2, label='dualprox(x)') plt.xlabel('x') plt.title(r'$||x-b||_2^2$') plt.legend() plt.tight_layout() ############################################################################### # Finally we can also multiply x by a matrix A x = np.arange(-1, 1, 0.1) nx = len(x) ny = nx * 2 A = np.random.normal(0, 1, (ny, nx)) l2 = pyproximal.L2(sigma=2., b=np.ones(ny), Op=pylops.MatrixMult(A)) print('||Ax-b||_2^2: ', l2(x)) tau = 2 xp = l2.prox(x, tau) xdp = l2.proxdual(x, tau) plt.figure(figsize=(7, 2)) plt.plot(x, x, 'k', lw=2, label='x') plt.plot(x, xp, 'r', lw=2, label='prox(x)') plt.plot(x, xdp, 'b', lw=2, label='dualprox(x)') plt.xlabel('x') plt.title(r'$||Ax-b||_2^2$') plt.legend() plt.tight_layout()
m1, m2 = np.meshgrid(m1, m2, indexing='ij') mgrid = np.vstack((m1.ravel(), m2.ravel())) J = 0.5 * np.sum(mgrid * np.dot(G, mgrid), axis=0) - np.dot(d, mgrid) J = J.reshape(nm1, nm2) ############################################################################### # We can now define the upper and lower bounds of the box and again we create # a grid to display alongside the solution lower = 1.5 upper = 3 indic = (mgrid > lower) & (mgrid < upper) indic = indic[0].reshape(nm1, nm2) & indic[1].reshape(nm1, nm2) ############################################################################### # We can now define both the quadratic functional and the box l2 = pyproximal.L2(Op=pylops.MatrixMult(G), b=d, niter=2) ind = pyproximal.Box(lower, upper) ############################################################################### # We are now ready to solve our problem. All we need to do is to choose an # initial guess for the proximal gradient algorithm def callback(x): mhist.append(x) m0 = np.array([4, 3]) mhist = [ m0, ]
color='black') ax7.errorbar(np.sqrt(u_points**2 + v_points**2), phase[ind], yerr=phase_err[ind], fmt='o', color='black') values = range(len(lambd_values3)) jet = plt.get_cmap('jet') cNorm = colors.Normalize(vmin=0, vmax=values[-1]) scalarMap = cm.ScalarMappable(norm=cNorm, cmap=jet) ii = 0 for m in lambd_values3: colorVal = scalarMap.to_rgba(values[ii]) sigma = m Aop = pylops.MatrixMult(dict_0) X_mp = sparsity.OMP(Aop, Y, niter_outer=1000, niter_inner=1000, sigma=sigma) rec = np.dot(dict_0, X_mp[0]) u_points = u[ind] / waves v_points = v[ind] / waves ax6.plot(np.sqrt(u_points**2 + v_points**2), rec[0:len(ind)], 'o', label=str(np.round(alpha, 3)), zorder=500, alpha=0.5, color=colorVal)
import pylops plt.close('all') np.random.seed(0) ############################################################################### # To start we create the forward problem n = 5 x = np.arange(n) + 1. # make A Ar = np.random.normal(0, 1, (n, n)) Ai = np.random.normal(0, 1, (n, n)) A = Ar + 1j * Ai Aop = pylops.MatrixMult(A, dtype=np.complex) y = Aop @ x ############################################################################### # Let's check we can solve this problem using the first formulation A1op = Aop.toreal(forw=False, adj=True) xinv = A1op.div(y) print('xinv=%s\n' % xinv) ############################################################################### # Let's now see how we formulate the second problem Amop = pylops.MemoizeOperator(Aop, max_neval=10) Arop = Amop.toreal() Aiop = Amop.toimag()
import pylops import pyproximal plt.close('all') ############################################################################### # To start with cosider the most complete case when both :math:`\mathbf{Op}` and # :math:`\mathbf{Op}` are non-null. x = np.arange(-5, 5, 0.1) nx = len(x) A = np.random.normal(0, 1, (nx, nx)) A = A.T @ A c = 2. quad = pyproximal.Quadratic(Op=pylops.MatrixMult(A), b=np.ones_like(x), c=c, niter=500) print('1/2 x^T Op x + b^T x + c: ', quad(x)) tau = 4 xp = quad.prox(x, tau) xdp = quad.proxdual(x, tau) plt.figure(figsize=(7, 2)) plt.plot(x, x, 'k', lw=2, label='x') plt.plot(x, xp, 'r', lw=2, label='prox(x)') plt.plot(x, xdp, 'b', lw=2, label='dualprox(x)') plt.xlabel('x') plt.title(r'$\frac{1}{2} \mathbf{x}^T \mathbf{Op} \mathbf{x} + ' r'\mathbf{b}^T \mathbf{x} + c$') plt.legend()