Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
401 views
in Technique[技术] by (71.8m points)

python - scipy curve_fit doesn't like math module

While trying to create an example with scipy.optimize curve_fit I found that scipy seems to be incompatible with Python's math module. While function f1 works fine, f2 throws an error message.

from scipy.optimize import curve_fit
from math import sin, pi, log, exp, floor, fabs, pow

x_axis = np.asarray([pi * i / 6 for i in range(-6, 7)])  
y_axis = np.asarray([sin(i) for i in x_axis])

def f1(x, m, n):
    return m * x + n

coeff1, mat = curve_fit(f1, x_axis, y_axis)    
print(coeff1)

def f2(x, m, n):
    return m * sin(x) + n 

coeff2, mat = curve_fit(f2, x_axis, y_axis)  
print(coeff2)

The full traceback is

Traceback (most recent call last):
  File "/Documents/Programming/Eclipse/PythonDevFiles/so_test.py", line 49, in <module>
    coeff2, mat = curve_fit(f2, x_axis, y_axis)
  File "/usr/local/lib/python3.5/dist-packages/scipy/optimize/minpack.py", line 742, in curve_fit
    res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/scipy/optimize/minpack.py", line 377, in leastsq
    shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
  File "/usr/local/lib/python3.5/dist-packages/scipy/optimize/minpack.py", line 26, in _check_func
    res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
  File "/usr/local/lib/python3.5/dist-packages/scipy/optimize/minpack.py", line 454, in func_wrapped
    return func(xdata, *params) - ydata
  File "/Documents/Programming/Eclipse/PythonDevFiles/so_test.py", line 47, in f2
    return m * sin(x) + n 
TypeError: only length-1 arrays can be converted to Python scalars

The error message appears with lists and numpy arrays as input alike. It affects all math functions, I tested (see functions in import) and must have something to do with, how the math module manipulates input data. This is most obvious with pow() function - if I don't import this function from math, curve_fit works properly with pow().

The obvious question - why does this happen and how can math functions be used with curve_fit?

P.S.: Please don't discuss, that one shouldn't fit the sample data with a linear fit. This was just chosen to illustrate the problem.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Be careful with numpy-arrays, operations working on arrays and operations working on scalars!

Scipy optimize assumes the input (initial-point) to be a 1d-array and often things go wrong in other cases (a list for example becomes an array and if you assumed to work on lists, things go havoc; those kind of problems are common here on StackOverflow and debugging is not that easy to do by the eye; code-interaction helps!).

import numpy as np
import math

x = np.ones(1)

np.sin(x)
> array([0.84147098])

math.sin(x)
> 0.8414709848078965                     # this only works as numpy has dedicated support
                                         # as indicated by the error-msg below!
x = np.ones(2)

np.sin(x)
> array([0.84147098, 0.84147098])

math.sin(x)
> TypeError: only size-1 arrays can be converted to Python scalars

To be honest: this is part of a very basic understanding of numpy and should be understood when using scipy's somewhat sensitive functions.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...