曲线拟合函数类型:y = 10^((a-x)/10*b)

3
以下是基于传感器值(列 x)计算的距离(列 y)。

test.txt - 内容

x   y   
----------


-51.61  ,1.5
-51.61  ,1.5
-51.7   ,1.53
-51.91  ,1.55
-52.28  ,1.62
-52.35  ,1.63
-52.49  ,1.66
-52.78  ,1.71
-52.84  ,1.73
-52.90  ,1.74
-53.21  ,1.8
-53.43  ,1.85
-53.55  ,1.87
-53.71  ,1.91
-53.99  ,1.97
-54.13  ,2
-54.26  ,2.03
-54.37  ,2.06
-54.46  ,2.08
-54.59  ,2.11
-54.89  ,2.19
-54.94  ,2.2
-55.05  ,2.23
-55.11  ,2.24
-55.17  ,2.26

我希望进行曲线拟合找到test.txt中数据的常数ab,该函数如下:

Function y = 10^((a-x)/10*b) 

我使用以下代码:
import math

from numpy import genfromtxt  
from scipy.optimize import curve_fit 

inData = genfromtxt('test.txt',delimiter=',')

rssi_data = inData[:,0]
dist_data= inData[:,1]

print rssi_data
print dist_data

def func(x, a,b):
    exp_val = (x-a)/(10.0*b) 
    return math.pow(10,exp_val)

coeffs, matcov = curve_fit(func,rssi_data,dist_data)

print(coeffs)
print(matcov)

这段代码无法成功执行。而且我不确定是否向curve_fit()传递了正确的参数。


1
你有什么问题? - eyllanesc
2
math.pow(10, exp_val) 更改为 10**exp_val - Alicia Garcia-Raboso
以上更改似乎有效,请您详细说明原因吗? - user1474918
1
scipy.optimize.curve_fit 期望一个函数作为其第一个参数,该函数可以接受 numpy 数组作为输入,但是你的 func 函数不行,因为 math.pow 不支持。 - Alicia Garcia-Raboso
1
为什么不在两边取log10并拟合一条直线呢?:o - Alex
2个回答

5
该函数需要处理numpy数组,但目前无法处理,因为math.pow期望一个标量值。如果我执行您的代码,将会得到以下异常信息:

TypeError: only length-1 arrays can be converted to Python scalars

如果您将函数改为:
def func(x, a, b):
    return 10 ** ((a - x) / (10 * b))  # ** is the power operator

它应该能够正常运行,没有任何异常:

>>> print(coeffs)
[-48.07485338   2.00667587]
>>> print(matcov)
[[  3.59154631e-04   1.21357926e-04]
 [  1.21357926e-04   4.25732516e-05]]

这里是完整的代码:

def func(x, a, b):
    return 10 ** ((a - x) / (10 * b))

coeffs, matcov = curve_fit(func, rssi_data, dist_data)

# And some plotting for visualization

import matplotlib.pyplot as plt
%matplotlib notebook  # only works in IPython notebooks

plt.figure()
plt.scatter(rssi_data, dist_data, label='measured')
x = np.linspace(rssi_data.min(), rssi_data.max(), 1000)
plt.plot(x, func(x, coeffs[0], coeffs[1]), label='fitted')
plt.legend()

enter image description here


1
我赞同之前的答案,因为它是编程问题的正确答案。但仔细观察后,你不需要进行幂律拟合:
y = 10^((a-x)/10*b) <=> log10(y) = log10(10^((a-x)/10*b)) 
<=> log10(y) = (a-x)/10*b

使用新变量:

z = log10(y), c = a/10*b and d = -1/10*b 

你现在必须适应以下内容:
z = dx + c

这是一条直线。你只需要将上述变换应用于表格中的2个点(x,y) => (x,log10(y)),并拟合一条直线以获得c、d和因此a、b。

我写这篇文章是因为你可能需要多次执行此操作,而这比拟合幂函数要简单得多(也更精确)。当你计划实验时,这也有影响。如果你知道这是正确的拟合函数,你只需要2个点就可以获得一般行为。

希望对你有所帮助。干杯!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接