|
| 1 | +import numpy as np |
| 2 | + |
| 3 | +from pyproximal.ProxOperator import _check_tau |
| 4 | +from pyproximal import ProxOperator |
| 5 | + |
| 6 | + |
| 7 | +class QuadraticEnvelopeCard(ProxOperator): |
| 8 | + r"""Quadratic envelope of the :math:`\ell_0`-penalty. |
| 9 | +
|
| 10 | + The :math:`\ell_0`-penalty is also known as the *cardinality function*, and the |
| 11 | + quadratic envelope :math:`\mathcal{Q}(\mu\|\cdot\|_0)` of it is defined as |
| 12 | +
|
| 13 | + .. math:: |
| 14 | +
|
| 15 | + \mathcal{Q}(\mu\|\cdot\|_0)(x) = \sum_i \left(\mu - \frac{1}{2}\max(0, \sqrt{2\mu} - |x_i|)^2\right) |
| 16 | +
|
| 17 | + where :math:`\mu \geq 0`. |
| 18 | +
|
| 19 | + Parameters |
| 20 | + ---------- |
| 21 | + mu : :obj:`float` |
| 22 | + Threshold parameter. |
| 23 | +
|
| 24 | + Notes |
| 25 | + ----- |
| 26 | + The terminology *quadratic envelope* was coined in [1]_, however, the rationale has |
| 27 | + been used earlier, e.g. in [2]_. In a general setting, the quadratic envelope |
| 28 | + :math:`\mathcal{Q}(f)(x)` is defined such that |
| 29 | +
|
| 30 | + .. math:: |
| 31 | +
|
| 32 | + \left(f(x) + \frac{1}{2}\|x-y\|_2^2\right)^{**} = \mathcal{Q}(f)(x) + \frac{1}{2}\|x-y\|_2^2 |
| 33 | +
|
| 34 | + where :math:`g^{**}` denotes the bi-conjugate of :math:`g`, which is the l.s.c. |
| 35 | + convex envelope of :math:`g`. |
| 36 | +
|
| 37 | + There is no closed-form expression for :math:`\mathcal{Q}(f)(x)` given an arbitrary |
| 38 | + function :math:`f`. However, for certain special cases, such as in the case of the |
| 39 | + cardinality function, such expressions do exist. |
| 40 | +
|
| 41 | + The proximal operator is given by |
| 42 | +
|
| 43 | + .. math:: |
| 44 | +
|
| 45 | + \prox_{\tau\mathcal{Q}(\mu\|\cdot\|_0)}(x) = |
| 46 | + \begin{cases} |
| 47 | + x_i, & |x_i| \geq \sqrt{2 \mu} \\ |
| 48 | + \frac{x_i-\tau\sqrt{2\mu}\sgn(x_i)}{1-\tau}, & \tau\sqrt{2\mu} < |x_i| < \sqrt{2 \mu} \\ |
| 49 | + 0, & |x_i| \leq \tau\sqrt{2 \mu} |
| 50 | + \end{cases} |
| 51 | +
|
| 52 | + By inspecting the structure of the proximal operator it is clear that large values |
| 53 | + are unaffected, whereas smaller ones are penalized partially or completely. Such |
| 54 | + properties are desirable to counter the effect of *shrinking bias* observed with |
| 55 | + e.g. the :math:`\ell_1`-penalty. Note that in the limit :math:`\tau=1` this becomes |
| 56 | + the hard thresholding with threshold :math:`\sqrt{2\mu}`. It should also be noted |
| 57 | + that this proximal operator is identical to the Minimax Concave Penalty (MCP) |
| 58 | + proposed in [3]_. |
| 59 | +
|
| 60 | + .. [1] Carlsson, M. "On Convex Envelopes and Regularization of Non-convex |
| 61 | + Functionals Without Moving Global Minima", In Journal of Optimization Theory |
| 62 | + and Applications, 183:66–84, 2019. |
| 63 | + .. [2] Larsson, V. and Olsson, C. "Convex Low Rank Approximation", In International |
| 64 | + Journal of Computer Vision (IJCV), 120:194–214, 2016. |
| 65 | + .. [3] Zhang et al. "Nearly unbiased variable selection under minimax concave |
| 66 | + penalty", In the Annals of Statistics, 38(2):894–942, 2010. |
| 67 | +
|
| 68 | + """ |
| 69 | + |
| 70 | + def __init__(self, mu): |
| 71 | + super().__init__(None, False) |
| 72 | + self.mu = mu |
| 73 | + |
| 74 | + def __call__(self, x): |
| 75 | + return np.sum(self.elementwise(x)) |
| 76 | + |
| 77 | + def elementwise(self, x): |
| 78 | + return self.mu - 0.5 * np.maximum(0, np.sqrt(2 * self.mu) - np.abs(x)) ** 2 |
| 79 | + |
| 80 | + @_check_tau |
| 81 | + def prox(self, x, tau): |
| 82 | + r = np.abs(x) |
| 83 | + idx = r < np.sqrt(2 * self.mu) |
| 84 | + if tau >= 1: |
| 85 | + r[idx] = 0 |
| 86 | + else: |
| 87 | + r[idx] = np.maximum(0, (r[idx] - tau * np.sqrt(2 * self.mu)) / (1 - tau)) |
| 88 | + return r * np.sign(x) |
0 commit comments