Regresiones logarítmica, exponencial y potencial a partir de la regresión lineal en Arduino

Lo que vamos a ver en este texto tiene bastante de truco matemático, pero funciona lo suficientemente bien para que merezca la pena hacerlos.

Ya en otro post vimos como implementar la regresión lineal en Arduino, aprovechando ese mismo código se puede calcular la regresión para otras funciones que se pueden adaptar mejor a los datos que la lineal.

Cómo de aquí en adelante nos hará falta vamos a recordar que la fórmula de la regresión lineal es:

y = a + b*x

El algoritmo de la regresión lineal lo que hace es a partir de ejemplos de valores de x e y calcular los valores de a y b

Ahora intentemos explicar el truco que usamos. Primero tomamos la función que queremos ajustar a los datos, por ejemplo:

y = a * e^(b*x)

Buscamos una transformación lineal que deje la fórmula de la misma forma que la de la regresión lineal. En nuestro ejemplo calcular el ln de ambos lados de la igualdad:

ln(y) = ln(a) + b*x

Este truco solo funciona cuando sea posible encontrar una transformación de este tipo, que no siempre se puede.

Realizamos cambios de variables para transformar la formula:

x -> x
y -> ln(y)
a -> ln(a)
b -> b

Ahora podemos usar el mismo algoritmo que en la regresión lineal solo que con un par de cambios de variables:

  • En la fase de aprendizaje, cuando tengamos la pareja de valores (x,y) le pasaremos al algoritmo de regresión lineal (x,ln(y))
  • Una vez calculados los parámetros no tendremos (a, b) si no (ln(a), b) por lo que para obtener a tendremos que elevar e al valor obtenido a = e ^ln(a)
  • Ahora que tenemos los parámetros (a,b) para estimar un valor en lugar de usar la ecuación de la recta (regresión lineal) usaremos y = a * e^(b*x)

Regresión exponencial

La fórmula de esta regresión es:

y = a*e^(b*x)

La transformación lineal que vamos a usar es:

ln(y) = ln(a) + b*x

Como ya hemos visto los cambios de variable son:

x -> x
y -> ln(y)
a -> ln(a)
b -> b

En pseudocódigo:

regExp::learn(x,y){
    regLineal.learn(x,ln(y));
}

regExp::calculate(x){
    a = e ^ regLineal.a;
    b = regLineal.b;
    y = a*e^(b*x);
    return y;
}

Regresión logarítmica

La fórmula de esta regresión es:

y = a*ln(x)+b

La transformación lineal que vamos a usar es:

y = a*ln(x)+b

Efectivamente es la misma puesto que ya tiene la forma deseada.

Los cambios de variable son:

x -> ln(x)
y -> y
a -> a
b -> b

En pseudocódigo:

regLog::learn(x,y){
    regLineal.learn(ln(x),y);
}

regLog::calculate(x){
    a = regLineal.a;
    b = regLineal.b;
    y = a*ln(x)+b;
    return y;
}

Regresión potencial

La fórmula de esta regresión es:

y = b*x^a

La transformación lineal que vamos a usar es:

ln(y) = a*ln(x)+10^b

Los cambios de variable son:

x -> ln(x)
y -> ln(y)
a -> a
b -> 10^b

En pseudocódigo:

regPot::learn(x,y){
    regLineal.learn(ln(x),ln(y));
}

regPot::calculate(x){
    a = regLineal.a;
    b = 10^regLineal.b;
    y = b*x^a
    return y;
}

Ejemplo gráfico

Para ver bien las diferencias entre las cuatro regresiones dejo esta imagen donde se pueden ver todas para los valores a= 1 y b = 3

Comparativa entre las cuatro regresiones con a= 2 y b = 3

La librería

Todo lo aquí explicado se puede encontrar en la librería Regressino que implementa estas cuatro regresiones con ejemplos de como usarlas