No soy matemático, pero creo que lo que busco se llama "regresión lineal múltiple"; Por favor, corríjame si estoy equivocado.

Utilizo numpy.polyfit y numpy.poly1d en una serie de valores de ángulo / ancho de pulso de un servomotor, para obtener una función, angles_to_pulsewidths.

angles_to_pulsewidths es una función polinomial que modela el servo y representa una línea de buen ajuste para la serie. Dado un valor de angle, devuelve un pulse_width correspondiente.

Ahora estoy tratando de hacer algo similar, pero en lugar de un solo valor angle en mi serie, tengo un par de coordenadas x / y para cada pulse_width. Quiero obtener una función que, dado un par x / y, devuelva un pulse_width correspondiente.

Este es mi código para crear mi función angles_to_pulsewidths:

import numpy

angles_and_pulsewidths = [
    [-162, 2490],
    [-144, 2270],
    [-126, 2070],
    [-108, 1880]
]

angles_values_array =      numpy.array(angles_and_pulsewidths)[:, 0]
pulsewidths_values_array = numpy.array(angles_and_pulsewidths)[:, 1]

coefficients = numpy.polyfit(
        angles_values_array,
        pulsewidths_values_array,
        3
    )

angles_to_pulsewidths = numpy.poly1d(coefficients)

He estado tratando de modificar esto para que, en lugar de proporcionar una matriz unidimensional de ángulos, proporcione una matriz bidimensional de valores x / y:

xy_values = [[1, 2], [3, 4], [5, 6], [6, 7]]
pulse_widths = [2490, 2270, 2070, 1880]

Sin embargo, en este caso, no puedo usar polyfit, porque que solo toma una matriz unidimensional para su parámetro x.

Puedo usar numpy.linalg .lstsq en su lugar, pero no puedo averiguar qué hacer con los resultados que me da.

Tampoco estoy seguro de si estoy en el camino correcto; soy yo He leído numerosas preguntas relacionadas aquí y he encontrado numerosas pistas, pero no las suficientes para llevarme al siguiente paso.

1
Daniele Procida 21 oct. 2019 a las 01:53

1 respuesta

La mejor respuesta

Es posible utilizar scipy curve_fit < / a> para esto.

Si conoce el formato general de la función, tal vez crea que será algo de la forma:

a x ^ 2 + b x y + c y ^ 2 + d x + e y +f

Entonces puedes usar el curve_fit de scipy para estimar a qué me referiré como "parámetros": a, b, c, d, e, f.

Primero necesitamos definir la forma general de nuestra función:

def func(variables, a, b, c, d, e, f):
    x, y = variables
    return a * x ** 2 + b * x * y + c * y ** 2 + d * x + e * y + f

Tenga en cuenta que nuestra función tiene 6 parámetros, para poder demostrar cómo funciona, necesitamos más datos que parámetros, así que voy a extender su conjunto de datos de ejemplo para tener 7 pares de valores xy y 7 anchos de pulso:

xy_values = [[1, 2], [3, 4], [5, 6], [6, 7], [8, 9], [10, 11], [12, 13]]
pulse_widths = [2490, 2270, 2070, 1880, 2000, 500, 600]

(Si no tiene más datos que parámetros, probablemente pueda elegir una forma general de su función para tener menos parámetros).

Necesitamos remodelar nuestro xy_values para que no sean pares de valores sino un solo par de dos conjuntos de valores (las xs y las ys). Para hacer esto, elijo crear una matriz numpy y "transponerla":

xy_values = np.array(xy_values).T

Ahora podemos llamar a nuestro func en nuestra matriz:

func(variables=xy_values, a=0, b=0, c=0, d=0, e=0, f=4)

Lo que da:

array([4, 4, 4, 4, 4, 4, 4])

Ahora podemos usar nuestros datos y curve_fit para estimar los mejores parámetros:

from scipy.optimize import curve_fit
popt, pcov = curve_fit(f=func, xdata=xy_values, ydata=pulse_widths)

pcov contiene información sobre qué tan bueno es el ajuste y popt son los valores reales de los parámetros que podemos ver y usar directamente:

popt

Da:

array([ -25.61043682, -106.84636863,  119.10145249, -374.6200899 ,
        230.65326227, 2141.55126789])

Y podemos llamar a la función con él en algún nuevo valor de xey:

func([0, 5], *popt)

Que da:

6272.353891536915

La elección de la forma general correcta de la función que desea ajustar depende del caso. Si hay algún conocimiento del problema en cuestión (tal vez espere que haya alguna relación trigonométrica), entonces puede usarlo, de lo contrario, es un caso de prueba y error y obtener una relación que sea "lo suficientemente buena" para su caso de uso.

EDITAR: Su sugerencia original de la necesidad de usar regresión lineal múltiple (MLR) no es completamente incorrecta. El enfoque de solución que he descrito le permite realizar MLR, pero solo asume un tipo específico de func: uno en el que todos los términos son lineales.

2
Daniele Procida 24 oct. 2019 a las 21:10