[英]why is my optimize.leastsq not working?
I am trying to fit function to my data. 我正在尝试使功能适合我的数据。 I have two different axis, x-axis: height, y-axis: weight. 我有两个不同的轴,x轴:高度,y轴:重量。 By visual inspection, I can see, that it gives more or less the shape of square root function saturating around weight = 10. Here is what I am doing: 通过视觉检查,我可以看到,它或多或少地给出了在重量= 10周围饱和的平方根函数的形状。这就是我正在做的事情:
from scipy import optimize
fitfunc = lambda p, x: np.sqrt(p[0]* x + p[1]) +p[2] # Target function
errfunc = lambda p, x, y: fitfunc(p, x) - y
sort_idx = np.argsort(height)
height = height[sort_idx]
weight = weight[sort_idx]
p0 = [0.1, 0.2, 0.3] # initial values
p1, success = optimize.leastsq(errfunc, p0, args=(height, weight), maxfev=10000)
No matter what values I set as p0, the output is always p1 = p0 无论我设置为p0的值,输出始终为p1 = p0
What am I doing wrong? 我究竟做错了什么?
Do you think it would be better to use different function if it is saturating? 您认为饱和时使用其他功能会更好吗?
Thanks in advance! 提前致谢!
You may have weight and height reversed, if they are the weight and height of a human population. 如果它们是人口的体重和身高,您的体重和身高可能会发生逆转。 Other than that your code runs beautifully well: 除此之外,您的代码可以很好地运行:
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
fitfunc = lambda p, x: np.sqrt(p[0]* x + p[1]) +p[2] # Target function
errfunc = lambda p, x, y: fitfunc(p, x) - y
height = np.random.normal(loc=1.70, scale=.15, size=(100))
bmi = np.random.normal(loc=20, scale=2, size=(100))
weight = bmi * height**2
sort_idx = np.argsort(weight)
height = height[sort_idx]
weight = weight[sort_idx]
p0 = [0.1, 0.2, 0.3] # initial values
p1, success = optimize.leastsq(errfunc, p0, args=(weight, height), maxfev=10000)
plt.plot(weight, height, 'o')
plt.plot(weight, fitfunc(p1, weight), '-')
plt.xlabel('weight')
plt.ylabel('height')
plt.show()
>>> p1
array([ 0.01625167, -0.32844465, 0.9256349 ])
The code does sometime give warnings like: 该代码有时会发出如下警告:
RuntimeWarning: invalid value encountered in sqrt
fitfunc = lambda p, x: np.sqrt(p[0]* x + p[1]) +p[2] # Target function
You may want to redefine your fitfunc
and errfunc
as 您可能希望将fitfunc
和errfunc
重新定义为
fitfunc2 = lambda p, y: ((y - p[2])**2 - p[1]) / p[0] # Target function
errfunc2 = lambda p, x, y: fitfunc2(p, y) - x
and then do : 然后做:
p2, success2 = optimize.leastsq(errfunc2, p0, args=(weight, height), maxfev=10000)
Plotting this and the previous gives slightly different but comparable results: 绘制这个和前一个给出了略有不同但可比较的结果:
Not directly an answer to your problem, but with your data given, I have no problem fitting this: 不是直接回答你的问题,但是根据你提供的数据,我没有问题:
import sys
from scipy import optimize
import numpy as np
from matplotlib import pyplot as plt
height=np.array([34.75625407,126.90646855,369.02594015,321.33822843,100.89398254,119.73654933,421.4400502,98.09051003,72.61433571,626.54970675,45.97802204,741.65476066,39.13568217,67.21666378,58.44445182,31.9950751,32.74788721,168.3256637,149.57003524,1058.41323859])
weight=np.array([4.375,3.95833333,9.16666667,8.125,3.75,8.4375,7.91666667,7.5,5.,10.,6.25,7.625,5.,6.25,10.,3.75,4.375,6.66666667,6.25,8.28125])
fitfunc = lambda p, x: np.sqrt(p[0]* x + p[1]) +p[2] # Target function
errfunc = lambda p, x, y: fitfunc(p, x) - y
pp = [0.2, 0.3, 0.4]
sort_idx = np.argsort(height)
height = height[sort_idx]
weight = weight[sort_idx]
p0 = [0.2, 0.2, 0.3] # initial values
result = optimize.leastsq(errfunc, p0, args=(height, weight), maxfev=10000, full_output=1)
p1 = result[0]
print result[3]
plt.plot(height, weight, 'o')
plt.plot(height, fitfunc(p1, height), '-')
plt.show()
One thing you could do, as I've done in my code above, is set full_output=1
and print the message you get. 正如我在上面的代码中所做的那样,您可以做的一件事是将full_output=1
设置并打印得到的消息。 Note that my success
value is actually 2, not 4. So there is some odd difference. 请注意,我的success
值实际上是2,而不是4.所以有一些奇怪的区别。 Since we should be using the same data, something in your scipy setup may be incorrect. 由于我们应该使用相同的数据,因此scipy设置中的某些内容可能不正确。 That, or you're not showing the whole problem and something's up elsewhere. 那,或者您没有显示整个问题,而其他地方有问题。
Looking at the figure, I do see that the values are scattered pretty much around anywhere, so it'll be hard to fit anyway (in fact, I wouldn't!). 查看该图,我确实看到这些值几乎分散在任何地方,因此无论如何都很难拟合(实际上,我不会!)。
Thanks for your help. 谢谢你的帮助。 I think I know what was the problem. 我想我知道问题是什么。 Somehow the sqrt was becoming negative, and was giving the errors. 不知何故,sqrt变得负面,并且正在给出错误。 When I took out the variables so that it cannot be negative it started to work, ie: 当我拿出变量以使其不能为负数时,它开始起作用,即:
p[0]* np.sqrt(x + np.abs(p[1]))
It's not exactly the same, but it works for me. 它不完全一样,但对我有用。 I should have thought about that before. 我之前应该考虑过这个问题。 Thanks again 再次感谢
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.