Huber.prox uses the wrong branch threshold (|x| > alpha instead of |x| > alpha + tau)
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 42/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Estancado
- Stack tecnológico
- numpy, python
- Área
- machine-learning
Línea de trabajo
Read pyproximal/proximal/Huber.py at the Huber.prox implementation and inspect the existing tests for that operator. Reproduce the reported values, especially where alpha < |x| <= alpha + tau, then check the prox against the stated formula or a numerical minimizer. Done means the prox is monotone and matches the minimizer across those inputs; issue #276 already has an open pull request.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
pyproximal.Huber.prox decides which branch to apply from |x| > alpha, but for the proximal operator the switch happens at |x| = alpha + tau. Inputs with alpha < |x| <= alpha + tau are soft-thresholded when they should be scaled. The result is not the minimizer, and the prox becomes discontinuous and non-monotone in x. This is in pyproximal/proximal/Huber.py (line 63 on main, also in 0.12.0). Related: #189, which split Huber and HuberCircular but left this threshold as it was.
Reproducer
import numpy as np
import pyproximal
alpha, tau = 1.0, 1.0
h = pyproximal.Huber(alpha=alpha)
x = np.array([-2.5, -1.5, -0.5, 0.5, 1.0, 1.2, 1.5, 1.9, 2.0, 2.5, 4.0])
# brute-force argmin_y H(y) + (y - x)^2 / (2 tau)
ys = np.linspace(-5, 5, 1000001)
H = lambda t: np.where(np.abs(t) <= alpha, t**2 / (2 * alpha), np.abs(t) - alpha / 2)
brute = np.array([ys[np.argmin(H(ys) + (ys - xi) ** 2 / (2 * tau))] for xi in x])
print(np.round(h.prox(x, tau), 4)) # [-1.5 -0.5 -0.25 0.25 0.5 0.2 0.5 0.9 1. 1.5 3.]
print(np.round(brute, 4)) # [-1.5 -0.75 -0.25 0.25 0.5 0.6 0.75 0.95 1. 1.5 3.]
For example, x = 1.2 returns 0.2, which is smaller than the 0.5 returned for x = 1.0.
Fix
The prox of tau * H_alpha is
prox(x) = x * alpha / (alpha + tau) if |x| <= alpha + tau
x - tau * sign(x) otherwise
which can also be written in closed form as (1 - tau / max(|x|, alpha + tau)) * x. That is the alternative already in the commented-out code; the comment says it "does not provide the same result", and that is because the current code is the one that is wrong. A minimal change to prox:
mask = xabs > self.alpha + tau
Equivalently, replace the body with y = (1.0 - tau / np.maximum(np.abs(x), tau + self.alpha)) * x. With either change the output matches the brute-force minimizer at all the points above. A test against a brute-force or scipy.optimize minimizer on a grid of x values that includes alpha < |x| < alpha + tau would catch a regression.
Related suggestion: HuberCircular applies the Huber function to the norm of the whole vector. For isotropic Huber-TV you need it per group, the way L21 works, e.g. a HuberL21(ndim, sigma, alpha) whose prox is v_i * (1 - tau*sigma / max(||v_i||, tau*sigma + alpha)) for each pixel.
- Lenguaje dominante
- Python
- Estrellas
- 85
- Forks
- 22
- Merge medio
- 2 h 11 min
- PR fusionados (30 d)
- 7
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de PyLops/pyproximal
-
documentation
Dificultad 1/5 Menos de una hora Aptitud para principiantes 62/100
PyLops/pyproximal#280 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 35/100
PyLops/pyproximal#198 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
Stopping criteria for solversAbiertoenhancement good first issue help wanted
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
PyLops/pyproximal#177 ·
Los mantenedores suelen responder en 1 día
-
enhancement help wanted
Dificultad 5/5 Más de una semana Aptitud para principiantes 28/100
PyLops/pyproximal#152 ·
Los mantenedores suelen responder en 1 día
-
Faster TVAbiertoquestion
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
PyLops/pyproximal#118 · 4 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de PyLops/pyproximal
Issues similares
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
yt-project/yt#5624 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
NousResearch/hermes-agent#148376 ·
Los mantenedores suelen responder en 1 día
-
Analysis
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
SACGF/variantgrid#2615 ·
Los mantenedores suelen responder en 1 día