35 votos

Buscando una función que aproxime una parábola

Tengo una forma que está definida por una parábola en un cierto rango, y una línea horizontal fuera de ese rango (ver en rojo en la figura).

Estoy buscando una función única, diferenciable, sin valores absolutos, no por partes y continua que pueda aproximarse a esa forma. Intenté con una función tipo Gaussiana (azul), que funciona bien alrededor del máximo, pero es demasiado grande en los bordes. ¿Hay alguna forma de hacer que la función azul se parezca más a la función roja? O, ¿hay otra función que pueda hacer esto?

introducir descripción de la imagen aquí

81voto

leftaroundabout Puntos 1343

Sugeriría simplemente aproximando la función $\max(0,\cdot)$, y luego usar eso para implementar $\max(0,1-x^2)$. Este es un problema muy estudiado, ya que $\max(0,\cdot)$ es la función relu que actualmente es ubicua en aplicaciones de aprendizaje automático. Una posibilidad es $$ \max(0,y) \approx \mu(w)(y) = \frac{y}2 + \sqrt{\frac{y^2}4 + w} $$ soft clip

Una forma de derivar esta fórmula: es la inversa del rango positivo de $x\mapsto x-\tfrac{w}x$.

Luego, compuesto con el cuadrático, esto se ve así:

softclipped parabola

Nota cómo, a diferencia de las sugerencias de Calvin Khor, esto evita llegar a ser negativo y es más fácil de adoptar para otras parábolas.


Nathaniel señala que este enfoque no conserva la altura del pico. No sé si eso importa en absoluto, pero si lo hace, la solución más simple es simplemente reescalar la función con un factor constante. Sin embargo, eso requiere conocer el máximo real de la propia parábola (en mi caso, 1).

Reescalado para preservar la altura del pico

Para obtener una mejor coincidencia con el pico original, puedes definir una versión de $\mu$ cuyos dos primeros coeficientes de Taylor alrededor de 1 sean ambos 1 (es decir, como la identidad), reescalando tanto el resultado como la entrada (esto explota la regla de la cadena): $$\begin{align} \mu_{1(1)}(w,y) :=& \frac{\mu(w,y)}{\mu(1)} \\ \mu_{2(1)}(w,y) :=& \mu_{1(1)}\left(w, 1 + \frac{y - 1}{\mu'_{1(1)}(w,1)}\right) \end{align}$$

La aproximación relu corregida por Taylor

Y con eso, este es tu resultado:

Aproximación de parábola corregida por Taylor relu

Lo bueno de esto es que la expansión de Taylor alrededor de 0 te devolverá la parábola original (sin restricciones) exacta.


Código fuente (Haskell con dynamic-plot):

import Graphics.Dynamic.Plot.R2
import Text.Printf

μ₁₁, μ₁₁', μ₂₁ :: Double -> Double -> Double
μ₁₁ w y = (y + sqrt (y^2 + 4*w))
             / (1 + sqrt(1 + 4*w))
μ₁₁' w y = (1 + y / sqrt (y^2 + 4*w))
             / (1 + sqrt(1 + 4*w))
μ₂₁ w y = μ₁₁ w $ 1 + (y-1) / μ₁₁' w 1

q :: Double -> Double
q x = 1 - x^2

main :: IO ()
main = do
 plotWindow
  [ plotLatest [ plot [ legendName (printf "μ₂₍₁₎(w,q(x))")
                         . continFnPlot $ μ₂₁ w . q
                      , legendName (printf "w = %.2g" w) mempty
                      ]
               | w <- (^1500).recip<$>[1,1+3e-5..]]
  , legendName "max(0,q x)" . continFnPlot
       $ max 0 . q, xAxisLabel "x"
  , yInterval (0,1.5)
  , xInterval (-1.3,1.3) ]
 return ()

36voto

Pierre Lebeaupin Puntos 729

Aquí hay una familia de funciones analíticas reales que hace el trabajo; hacer que el parámetro $N=1,2,3,4,\dots$ sea más grande mejora la aproximación. Digamos simplemente que el cuadrático es $q(x) = 1-x^2$, por lo que la función es $f(x)=\max(0,q(x)). Es fácil hacer un caso más general. Luego establece $$f_N(x) = \frac1{1+x^{2N}}q(x). Esto funciona porque para $N$ muy grande, cuando $|x|<1$, $x^{2N}\approx 0$, por lo que $\frac1{1+x^{2N}}\approx 1$. Pero en el momento en que $|x|>1$, $x^{2N}$ se vuelve enorme, así que entonces $\frac1{1+x^{2N}} \approx 0$. No es exactamente 0 fuera de $|x|<1$, sino que decae como $O(|x|^{-2N+2})$ (de nuevo, aumenta $N$ para obtener una mejor aproximación)

Así es como se ve para $N=10$: enter image description here

El caso general: el cuadrático con altura $h$ sobre $y=c$, base $d$ centrado alrededor de $x_0$ es $$ q_{h,c,d,x_0}(x)=h q\left(\frac{x-x_0}{d/2}\right)+c. El cuadrático truncado en $y=c$ es entonces $$ f_{h,c,d,x_0}(x) = h f\left(\frac{x-x_0}{d/2}\right)+c, y la aproximación correspondiente que estoy proponiendo es $$ f_{N,h,c,d,x_0}(x) = h f_N\left(\frac{x-x_0}{d/2}\right)+c.

Puedes ajustar estos parámetros en este gráfico interactivo de Desmos.

Una variación adicional es usar $1/(1-x^{2N})$ en lugar de definir $f_N$; esto hace que $f_N$ sea siempre positivo (porque cambia de signo exactamente donde lo hace $q$, y $f_N$ es diferenciable en los puntos de truncamiento por l'Hôpital), lo cual podría ser útil. Pero la aproximación es peor cerca del límite.

Aquí tienes un gráfico de esta última variante - enter image description here

La primera variante es exactamente 1 en $x=0$, y exactamente 0 en $x=\pm 1$. Tiene el mismo signo que el polinomio original $1-x^2$ en todas partes.

La segunda es exacta solo en $x=0$, (pero incluso si $N$ es pequeño), y es siempre positiva. (En particular, es una ligera tergiversación decir que "a diferencia de las sugerencias de Calvin Khor, esto evita volver negativo en cualquier momento" :) ¡pero no incluí un gráfico de esta variante antes, y su solución también es genial!)

8voto

Acccumulation Puntos 13

No existe tal cosa como una "función a trozos". En la frase "función definida a trozos", la palabra "a trozos" modifica la palabra "definida", no "función". El término "a trozos" se refiere a cómo se define la función, no a la función en sí.

$$ t(x) = \begin{cases} -x & x < 0 \\ x& x \geq 0 \end{cases} $$

y

$t(x)=|x|$

son la misma función. En el primer caso, la definición se da a trozos, y en el segundo, no lo es. Puedes hacer cualquier definición a trozos no a trozos con suficientes valores absolutos. Por ejemplo, lo siguiente da un gráfico similar al tuyo:

$f(x) = \frac 12(200-||x-50|-|x-150||)(100-|x-50|)$

7voto

Scott McClung Puntos 171

Como una expansión de la respuesta de Calvin Khor, necesitas generar una aproximación adecuada a la función de pulso cuadrado, lo cual se puede hacer de diferentes maneras.

Ten en cuenta que la función de error va de -1 a 1, con una transición relativamente rápida de un lado al otro. Usando esta función, podemos escribir $$ f_a(x)=\frac{\text{erf}(ax)+1}2-\frac{\text{erf}(a(x-1))+1}2=\frac{\text{erf}(ax)-\text{erf}(a(x-1))}2 $$ Aquí está cómo se ve esa función para $a=5$ (rojo), $a=50$ (azul), y $a=500$ (verde):

Aproximación de la función de pulso cuadrado

Podemos trasladar esto según sea necesario, luego multiplicar por nuestro polinomio requerido, para obtener nuestro ajuste. Ajustando $(1-x^2)$ nos lleva a $$ f(x)\approx (1-x^2)f_a(2x+1) $$ lo cual, para los mismos valores de $a$, da

Aproximando nuestra función

Cualquier secuencia que converge hacia el pulso cuadrado funcionará. En lugar de $\text{erf}$, podrías usar $\tan^{-1}$ (con el reescalado apropiado), por ejemplo, o $\tanh$.

4voto

pjz Puntos 139

Una "meta-respuesta", si se me permite.

Entonces, tienes una restricción de suavidad. Pero - no la lleves más lejos de lo necesario. Es decir, hay una tendencia natural a asumir que si se te pide una aproximación suave debe ser infinitamente diferenciable. Así que, optaste por una Gaussiana. No estoy diciendo que sea una mala elección, pero - definitivamente deberías considerar una solución que "solo" cumpla con la restricción y no mucho más allá.

Lo que inmediatamente me viene a la mente es "casi-hacer trampa": tomar la función por partes que rompe la restricción (digamos que sus partes son $p_1$ y $p_2$) y suavizar sus partes, así: $$ f(x) = (1-t(x)) \cdot p_1(x) + t(x) \cdot p_2(x) $$ con alguna función $t : \mathbb{R} \to [0,1]$. es decir, $p_1$ transicionará gradualmente en $p_2$ en lugar de simplemente cambiar a ella.

En tu caso, un $t(x)$ súper simple sería el siguiente asunto lineal por partes: $$ t(x) = \begin{cases} 0 & x < -100 \\ \frac{x+100}{100} &- 100 \leq x < 0 \\ \frac{100-x}{100} &0 \leq x < 100 \\ 0 & x \geq 100 \end{cases} $$ (viendo cómo tu segmento de parábola cruza en -50 y 50.)

Por supuesto, esta no es la mejor elección de $t$. Puedes estrechar los segmentos lineales que van de 0 a 1 y de regreso; o podrías agregar más piezas; o podrías hacerlo un spline de mayor grado. Estrechar el segmento de transición está bien - ya que la función suavizada seguirá cumpliendo con tus restricciones (no estabas limitado en el valor absoluto de la derivada). Luego tendrás un quinto, central segmento lineal con valor 1.

Si quisieras ser más amable, podrías aumentar el grado de las funciones lineales por partes, para obtener un spline de mayor grado. Cuando pienses en esa dirección, podrás notar que lo que ya tienes es un polinomio de Bernstein de grado 1 Bernstein polynomial - una base para el espacio de polinomios de [0,1] a $\mathbb{R}$. Entonces, si no me equivoco, tus coeficientes de suavizado generalizarán para hacer Bezier splines de tu grado elegido de suavidad.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X