wiki:Piecewise
close Warning: Can't synchronize with repository "(default)" (/var/svn/mms does not appear to be a Subversion repository.). Look in the Trac log for more information.

Función definida a trozos (piecewise-defined function)

Una función definida a trozos es aquella cuya expresión varía en determinados tramos de su variable independiente.

Un ejemplo muy conocido es la función valor absoluto, que puede describirse como la función identidad para los valores positivos o cero y como la función opuesto para los valores negativos:

          | x ,, x>=0
abs(x) = <|
          | -x ,, x<0

Regresión con funciones a trozos

En una regresión describimos una variable Y (el output) como combinación lineal de otras variables X_i (los inputs):

Y = Sum_i(beta_i * X_i) + N

más una parte no explicada N que es el ruido o residuo de la regresión.

De este modo, la relación entre el output y cada input es lineal. Sin embargo, no siempre esta relación se ajusta a la relación existente entre dichas variables y es necesario proponer algún tipo de relación no lineal.

En ocasiones, la función que caracteriza la relación no lineal es conocida y basta sustituir el input original X_i, por el input transformado convenientemente F(X_i) y realizar la regresión lineal correspondiente.

En otras ocasiones, esta forma funcional es conocida, pero depende de algún parámetro no lineal que puede ser estimado por los algoritmos correspondientes.

En el caso que nos ocupa, se propone describir dicha forma no-lineal como una función lineal a trozos, de modo que un término E(X) = beta * X se pueda reescribir como:

E(X) = alpha_k + beta_k * X ,,  X <: [X_k, X_{k+1}]

cumpliendo dos condiciones:

  • continuidad: alpha_k + beta_k * X_{k+1} == alpha_{k+1} + beta_{k+1} * X_{k+1}
  • efecto nulo para input nulo: E(0) == 0

Particionamiento del input

Para incorporar dicha función a trozos a la regresión, utilizaremos un particionamiento del input P_k(X) de modo que la función a trozos se pueda escribir como combinación lineal de dicho particionamiento:

E(X) = Sum_k(beta_k * P_k(X))

El particionamiento del input viene dado por:

          |          / x_k - x_{k+1}   ,,  x<x_k
          | k<q  -> |  x - x_{k+1}     ,,  x<:[x_k, x_{k+1}]
          |          \ 0               ,,  x>x_{k+1}
          |          / x_k             ,,  x<x_k
P_k(x) = <| k==q -> |  x               ,,  x<:[x_k, x_{k+1}]
          |          \ x_{k+1}         ,,  x>x_{k+1}
          |          / 0               ,,  x<x_k
          | k>q  -> |  x - x_k         ,,  x<:[x_k, x_{k+1}]
          |          \ x_{k+1} - x_k   ,,  x>x_{k+1}

siendo: 0 <: [x_q, x_{q+1}]

Nótese que:

Sum_k(P_k(x)) == x

y de ahí el término particionamiento para referirse a este conjunto de transformaciones del input.


[Cálculos]

Transformaciones-piecewise del input

Se admite que las marcas utilizadas para la partición del input recorren todo el dominio del input. Ya que, de lo contrario, el input tendría que truncarse al intervalo definido por las marcas usadas.

Sean n+1 marcas: x_k con k<:[1,n+1] y un input x que será modelado con diferentes parámetros según sus valores estén en un intervalo [x_k, x_{k+1}] u otro:

        |  a_1 + b_1 * x  ,,  x<:[x_1, x_2]
        |  ...
E(x) = <|  a_m + b_m * x  ,,  x<:[x_m, x_{m+1}]
        |  ...
        |  a_n + b_n * x  ,,  x<:[x_n, x_{n+1}]

Se busca que el efecto (E) sea continuo de modo que el valor para una marca: x_k sea el mismo por la izquierda o por la derecha:

a_{k-1} + b_{k-1} * x_k = a_k + b_k * x_k

y se quiere que la el efecto sea nulo para el input nulo (esté libre de constante u ordenada en el origen):

E(x=0) = 0

Si reescribimos la expresión anterior teniendo en cuenta cual es el intervalo que contiene al 0: 0<:[x_q, x_{q+1}]

        |  ... (+)
        |  ...
E(x) = <|  b_q * x                        ,,  x<:[x_q, x_(q+1)]
        |  b_{q+1}*(x-x_{q+1})
        |    + b_q*x_{q+1}                ,,  x<:[x_{q+1}, x_{q+2}]
        |  b_{q+2}*(x-x_{q+2}) 
        |    + b_{q+1}*(x_{q+2}-x_{q+1}) 
        |    + b_q*x_{q+1}                ,,  x<:[x_{q+2}, x_{q+3}]
        |  ...
        |  b_n*(x-x_n) 
        |    + b_{n-1}*(x_n-x_{n-1}) 
        |    + ... + b_q*x_{q+1}          ,,  x<:[x_n, x_{n+1}]

Y para los valores negativos de x hacemos lo mismo pero usando el extremo superior del intervalo: (+)

        |  b_{q-1}*(x-x_q)
        |    + b_q*x_q                    ,,  x<:[x_{q-1}, x_q]
        |  b_{q-2}*(x-x_{q-1}) 
        |    + b_{q-1}*(x_{q-1}-x_q) 
        |    + b_q*x_q                    ,,  x<:[x_{q-2}, x_{q-1}]
        |  ...
        |  b_1*(x-x_2) 
        |    + b_2*(x_2-x_3) 
        |    + ... + b_q*x_q              ,,  x<:[x_1, x_2]

Podemos reagrupar los términos en función de los parámetros b_k del siguiente modo:

        |         / x_k - x_{k+1}   ,,  x<x_k
        |  b_k * |  x - x_{k+1}     ,,  x<:[x_k, x_{k+1}]  ,,  k<q
        |         \ 0               ,,  x>x_{k+1}
        |         / x_k             ,,  x<x_k
E(x) = <|  b_k * |  x               ,,  x<:[x_k, x_{k+1}]  ,, k==q
        |         \ x_{k+1}         ,,  x>x_{k+1}
        |         / 0               ,,  x<x_k
        |  b_k * |  x - x_k         ,,  x<:[x_k, x_{k+1}]  ,,  k>q
        |         \ x_{k+1} - x_k   ,,  x>x_{k+1}

Estos nuevos inputs los podemos denominar transformaciones-piecewise del input o inputs-piecewise.

Suma de las transformaciones-piecewise del input

Podemos observar que el particionamiento del input, puede escribirse en los tres diferentes casos siguientes como:

si x <: [x_a, x_{a+1}]   ,,  a>q  ,,  0 <: [x_q, x_{q+1}]

         | 0             ,, k < q
P_k(x) = | x_{k+1}       ,, k == q
         | x_{k+1} - x_k ,, q < k < a
         | x - x_k       ,, k == a
         | 0             ,, k > a
si x <: [x_a, x_{a+1}]   ,,  a==q  ,,  0 <: [x_q, x_{q+1}]

         | 0             ,, k < q
P_k(x) = | x_{k+1}       ,, k == q
         | x_{k+1} - x_k ,, q < k < a
         | x - x_k       ,, k == a
         | 0             ,, k > a
si x <: [x_a, x_{a+1}]   ,,  a>q  ,,  0 <: [x_q, x_{q+1}]

         | 0           ,, k < q
P_k(x) = | x           ,, k == q
         | 0           ,, k > q

y comprobar que: Sum_k(P_k(x)) == x.


[Implementación]

Se propone una implementación del particionamiento P_k(x) a partir de los valores: (x, xI:=x_k, xS:=x_{k+1})

TOL

//////////////////////////////////////////////////////////////////////////////
Real Piecewise(Real x, Real xI, Real xS)
//////////////////////////////////////////////////////////////////////////////
{
  Case(xI<0 & xS<0, Case(x<xI, xI-xS, x<xS, x-xS, True, 0),
    xI<=0 & xS>=0, Case(x<xI, xI, x>xS, xS, True, x), 
    xI>0 & xS>0, Case(x<xI, 0, x<xS, x-xI, True, xS-xI))
};

Véase trunk/ExtLib/fun_piecewise.tol.

SQL

CREATE FUNCTION piecewise(x NUMERIC, xI NUMERIC, xS NUMERIC) RETURNS NUMERIC
  AS $$ SELECT CASE 
  WHEN $1 IS NULL THEN NULL
  WHEN $2 IS NULL AND $3 IS NULL THEN $1                                                 -- (-inf, inf)
  WHEN $2 IS NULL AND $3<0 THEN (CASE WHEN $1<$3 THEN $1-$3 ELSE 0 END)                  -- (-inf, neg)
  WHEN $2 IS NULL AND $3>=0 THEN (CASE WHEN $1>$3 THEN $3 ELSE $1 END)                   -- (-inf, pos|0)
  WHEN $2<=0 AND $3 IS NULL THEN (CASE WHEN $1<$2 THEN $2 ELSE $1 END)                   -- (neg|0, inf)
  WHEN $2>0 AND $3 IS NULL THEN (CASE WHEN $1<$2 THEN 0 ELSE $1-$2 END)                  -- (pos, inf)
  WHEN $2<0 AND $3<0 THEN (CASE WHEN $1<$2 THEN $2-$3 WHEN $1<$3 THEN $1-$3 ELSE 0 END)  -- (neg, neg)
  WHEN $2<=0 AND $3>=0 THEN (CASE WHEN $1<$2 THEN $2 WHEN $1>$3 THEN $3 ELSE $1 END)     -- (neg|0, pos|0)
  WHEN $2>0 AND $3>0 THEN (CASE WHEN $1<$2 THEN 0 WHEN $1<$3 THEN $1-$2 ELSE $3-$2 END)  -- (pos, pos)
  END $$
  LANGUAGE SQL;
Last modified 11 years ago Last modified on Jun 13, 2014, 2:42:01 PM