def _prox(self, x, T): # Gamma is T in the matlab UNLocBox implementation. gamma = self.lambda_ * T if self.tight: # Nati: I've checked this code the use of 'y' seems correct sol = self.A(x) - self.y() sol[:] = functions._soft_threshold(sol, gamma * self.nu * self.w) - sol sol[:] = x + self.At(sol) / self.nu sol[sol < 0] = 0 else: raise NotImplementedError('Not implemented for non-tight frame.') return sol
def test_soft_thresholding(self): """ Test the soft thresholding helper function. """ x = np.arange(-4, 5, 1) # Test integer division for complex method. Ts = [2] y_gold = [[-2, -1, 0, 0, 0, 0, 0, 1, 2]] # Test division by 0 for complex method. Ts.append([.4, .3, .2, .1, 0, .1, .2, .3, .4]) y_gold.append([-3.6, -2.7, -1.8, -.9, 0, .9, 1.8, 2.7, 3.6]) for k, T in enumerate(Ts): for cmplx in [False, True]: y_test = functions._soft_threshold(x, T, cmplx) nptest.assert_array_equal(y_test, y_gold[k])
def graph_pnorm_interpolation(self, gradient, P, w, labels_bin, x0=None, p=1., **kwargs): r""" Solve an interpolation problem via gradient p-norm minimization. A signal :math:`x` is estimated from its measurements :math:`y = A(x)` by solving :math:`\text{arg}\underset{z \in \mathbb{R}^n}{\min} \| \nabla_G z \|_p^p \text{ subject to } Az = y` via a primal-dual, forward-backward-forward algorithm. Parameters ---------- gradient : array_like A matrix representing the graph gradient operator P : callable Orthogonal projection operator mapping points in :math:`z \in \mathbb{R}^n` onto the set satisfying :math:`A P(z) = A z`. x0 : array_like, optional Initial point of the iteration. Must be of dimension n. (Default is `numpy.random.randn(n)`) p : {1., 2.} labels_bin : array_like A vector that holds the binary labels. kwargs : Additional solver parameters, such as maximum number of iterations (maxit), relative tolerance on the objective (rtol), and verbosity level (verbosity). See :func:`pyunlocbox.solvers.solve` for the full list of options. Returns ------- x : array_like The solution to the optimization problem. """ grad = lambda z: gradient.dot(z) div = lambda z: gradient.transpose().dot(z) # Indicator function of the set satisfying :math:`y = A(z)` f = functions.func() f._eval = lambda z: 0 f._prox = lambda z, gamma: P(z, w, labels_bin) # :math:`\ell_1` norm of the dual variable :math:`d = \nabla_G z` g = functions.func() g._eval = lambda z: np.sum(np.abs(grad(z))) g._prox = lambda d, gamma: functions._soft_threshold(d, gamma) # :math:`\ell_2` norm of the gradient (for the smooth case) h = functions.norm_l2(A=grad, At=div) stepsize = (0.9 / (1. + scipy.sparse.linalg.norm(gradient, ord='fro'))) ** p solver = solvers.mlfbf(L=grad, Lt=div, step=stepsize) if p == 1.: problem = solvers.solve([f, g, functions.dummy()], x0=x0, solver=solver, **kwargs) return problem['sol'] if p == 2.: problem = solvers.solve([f, functions.dummy(), h], x0=x0, solver=solver, **kwargs) return problem['sol'] else: return x0