scipy.optimize.curve_fit, TypeError: tipo de operando no compatible

He hecho una búsqueda y el problema parece similar a Python scipy: tipo (s) de operando no compatibles para ** o pow (): ‘lista’ y ‘lista’ sin embargo, la solución publicada allí no funcionó y creo que en realidad sé diferente.

Estoy tratando de ajustar una curva a los datos usando scipy.curve_fit, cuando dejo los 3 parámetros libres, todo funciona correctamente y obtengo el resultado esperado.

def func(x,a,b,c): return a*np.exp(b*(x**c)) popt, pcov = curve_fit(func,x,y) 

Sin embargo, cuando bash corregir uno de los valores (c = 2) como se muestra a continuación,

 def func2(x,a,b): return a*np.exp(b*(x**2)) popt, pcov = curve_fit(func2,x,y) 

Obtengo TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'list' usando numpy.power(x,2) como se sugiere en la pregunta vinculada permite que el código se ejecute pero produce un resultado incorrecto . ¿Alguien ve lo que estoy haciendo mal?

Editado para agregar: aún menos confuso, que hasta ahora sé que usa curve_fit, con la segunda fórmula que funciona.

Edición 2: A los que se mencionan los problemas de lista, X e Y ahora son matrices y el código se ejecuta sin errores. Sin embargo, func2 sigue produciendo drásticamente el resultado equivocado. (Publicaré la gráfica aquí, pero aparentemente necesito más representantes).

Func 1 curvefit da [a,b,c] = [ 1.71890826, -0.0239123, 3.17039851] sin embargo, para func2 todo sale mal [a,b] = [ -2.88694423e-15, 9.99999998e-01] . No entiendo cómo un cambio tan pequeño puede estar causando un problema tan drástico, lesssq pudo ajustar estos datos con c = 2.

El TypeError produce porque la x se pasa a func2 es una lista.

Aquí hay un ejemplo:

 import numpy as np import scipy.optimize as optimize def func2(x,a,b): return a*np.exp(b*(x**2)) x = np.linspace(0,1,6).reshape(2,-1) y = func2(x,1,1) x = x.tolist() y = y.tolist() print(x) # [[0.0, 0.2, 0.4], [0.6000000000000001, 0.8, 1.0]] print(y) # [[1.0, 1.0408107741923882, 1.1735108709918103], [1.4333294145603404, 1.8964808793049517, 2.718281828459045]] popt, pcov = optimize.curve_fit(func2, x, y) # TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int' 

En este caso, func2 mapea una matriz x de forma (2,3) a una matriz y de forma (2,3). La función func2 espera que el valor de retorno de func2 sea ​​una secuencia de números, no una matriz.

Afortunadamente para nosotros, en este caso, func2 funciona de manera elemental en cada componente de x ; no hay interacción entre los elementos de x . Entonces realmente no hay diferencia si pasamos una matriz x de forma (2,3) o una matriz 1D de forma (6,).

Si pasamos una matriz de forma (6,), func2 devolverá una matriz de forma (6,). Perfecto. Eso va a hacer muy bien:

 x = np.asarray(x).ravel() y = np.asarray(y).ravel() popt, pcov = optimize.curve_fit(func2, x, y) print(popt) # [ 1. 1.] 

¿Qué valores de x usaste? El siguiente ejemplo funciona para mí.

 from scipy.optimize import curve_fit import numpy as np def func2(x,a,b): return a*np.exp(b*(x**2)) x = np.linspace(0,4,50) y = func2(x, 2.5, 2.3) yn = y + 6.*np.random.normal(size=len(x)) popt, pcov = curve_fit(func2,x,yn) print popt, pcov 

Da el resultado dependiendo de la función random :

 [ 1.64182333 2.00134505] [[ 1.77331612e+11 -6.77171181e+09] [ -6.77171181e+09 2.58627411e+08]] 

¿Son sus valores x e yn de tipo lista? El siguiente ejemplo da su mensaje de error:

 print range(10)**2 TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'