r"""Projection of :math:`\mathbf{V}` onto the simplex, scaled by `z` .. math:: P\left(\mathbf{V}, z\right) = \mathop{\arg \min}_{\substack{\mathbf{y} >= 0 \\ \sum_i \mathbf{y}_i = z}} \quad \|\mathbf{y} - \mathbf{V}\|^2 Parameters ---------- V: ndarray, rank 2 z: float
(V, z=1, axis=None)
| 63 | |
| 64 | |
| 65 | def projection_simplex(V, z=1, axis=None): |
| 66 | r"""Projection of :math:`\mathbf{V}` onto the simplex, scaled by `z` |
| 67 | |
| 68 | .. math:: |
| 69 | P\left(\mathbf{V}, z\right) = \mathop{\arg \min}_{\substack{\mathbf{y} >= 0 \\ \sum_i \mathbf{y}_i = z}} \quad \|\mathbf{y} - \mathbf{V}\|^2 |
| 70 | |
| 71 | Parameters |
| 72 | ---------- |
| 73 | V: ndarray, rank 2 |
| 74 | z: float or array |
| 75 | If array, len(z) must be compatible with :math:`\mathbf{V}` |
| 76 | axis: None or int |
| 77 | - axis=None: project :math:`\mathbf{V}` by :math:`P(\mathbf{V}.\mathrm{ravel}(), z)` |
| 78 | - axis=1: project each :math:`\mathbf{V}_i` by :math:`P(\mathbf{V}_i, z_i)` |
| 79 | - axis=0: project each :math:`\mathbf{V}_{:, j}` by :math:`P(\mathbf{V}_{:, j}, z_j)` |
| 80 | |
| 81 | Returns |
| 82 | ------- |
| 83 | projection: ndarray, shape :math:`\mathbf{V}`.shape |
| 84 | """ |
| 85 | if axis == 1: |
| 86 | n_features = V.shape[1] |
| 87 | U = np.sort(V, axis=1)[:, ::-1] |
| 88 | z = np.ones(len(V)) * z |
| 89 | cssv = np.cumsum(U, axis=1) - z[:, np.newaxis] |
| 90 | ind = np.arange(n_features) + 1 |
| 91 | cond = U - cssv / ind > 0 |
| 92 | rho = np.count_nonzero(cond, axis=1) |
| 93 | theta = cssv[np.arange(len(V)), rho - 1] / rho |
| 94 | return np.maximum(V - theta[:, np.newaxis], 0) |
| 95 | |
| 96 | elif axis == 0: |
| 97 | return projection_simplex(V.T, z, axis=1).T |
| 98 | |
| 99 | else: |
| 100 | V = V.ravel().reshape(1, -1) |
| 101 | return projection_simplex(V, z, axis=1).ravel() |
| 102 | |
| 103 | |
| 104 | class Regularization(object): |