如何逼近几何增长序列的函数?

发布于 2025-01-11 22:15:54 字数 1061 浏览 0 评论 0原文

我有创建 x0 的函数:

x0 = []
    for i in range(0,N):
        if i == 0:
            a =  0.4
        else:
            a = round(0.4 + 0.3*2**(i-1), 1)
        print(i, a)
        x0.append(a)

它为我提供了增长序列的数据:[0.4, 0.7, 1.0, 1.6, 2.8, 5.2, 10.0, 19.6, 38.8, 77.2, ... ] 我想找到一个适合这些点的函数。我不想使用多项式,因为 N 可以不同,但​​需要找到单参数函数。投影需要非常笼统。

我的方法是使用代码:

def fun(x, a, b):    
    return np.cos(x**(2/3) * a + b) 
    
# Make fit #
y0 = [0]*len(x0)
p, c = curve_fit(f=fun, xdata=np.array(x0), ydata=y0)
  
x = np.linspace(0, max(x0), 10000)    
plt.plot(x, fun(x, *p))    
plt.scatter(x0, y0)

该函数的进度对于起点来说似乎太宽,并且非常适合最后的进度。我还尝试通过将此函数乘以 x 来降低初始振荡,但开始时周期仍然太宽。是否有可能找到良好的振荡函数来通过(几乎)所有这些点?我不知道如何在 x**(...) 下设置参数,因为在那里放置一个变量会导致拟合估计它接近 1,这不是我需要的。我可以这样设置 sin(x**b) 的幂吗?如果不是,我应该尝试什么功能家庭?

下面是函数乘以 b*x 的图。第一点的振荡应该更加密集。 输入图片此处描述

I have the function to create x0:

x0 = []
    for i in range(0,N):
        if i == 0:
            a =  0.4
        else:
            a = round(0.4 + 0.3*2**(i-1), 1)
        print(i, a)
        x0.append(a)

which gives me data of growing sequence: [0.4, 0.7, 1.0, 1.6, 2.8, 5.2, 10.0, 19.6, 38.8, 77.2, ...] which I want to find a function to fit to these points. I don't want to use polynomials because the N can be different but need to find single parameter function. The projection needs to be very general.

My approach is using the code:

def fun(x, a, b):    
    return np.cos(x**(2/3) * a + b) 
    
# Make fit #
y0 = [0]*len(x0)
p, c = curve_fit(f=fun, xdata=np.array(x0), ydata=y0)
  
x = np.linspace(0, max(x0), 10000)    
plt.plot(x, fun(x, *p))    
plt.scatter(x0, y0)

That function's progress seem to be too wide for starting points and quite fit the last ones. I also tried to lower the initial oscillations by multiplying this function by x, but the period still is too wide at the beginning. Is it possible to find good oscillation function to go thru (almost) all those points? I don't know how to set parameter under the x**(...) because placing there a variable cause the fit to estimate it as close to 1, which is not what I need. Can I set the power for sin(x**b) that way? If not what functions family should I try?

Below the plot for function multiplied by b*x. The oscillations at first points should be much denser.
enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

·深蓝 2025-01-18 22:15:54

感谢建议,我找到了最合适的,而且我认为它再好不过了。

解决方案是:

 def fun(x, a, b, c):
        return np.cos(np.pi*(np.log2((x-a)/b) + c))

并且拟合方法看起来像

p, c = curve_fit(f=fun, xdata=np.array(x0), ydata=y0, bounds=([0, -np.inf, -np.inf], [x0[0], np.inf, np.inf]))

a设置初始边界很重要,以避免收敛失败或“残差在初始点不是有限的”问题。最后,尽管域中接近 0 的疯狂行为,每个点都有自己的交叉点。参数非常接近 0 或 1 - 不趋于无穷大。

Thanks to suggestions I've found the best fit and I think it can't be better.

The solution is:

 def fun(x, a, b, c):
        return np.cos(np.pi*(np.log2((x-a)/b) + c))

and the fit method looks like

p, c = curve_fit(f=fun, xdata=np.array(x0), ydata=y0, bounds=([0, -np.inf, -np.inf], [x0[0], np.inf, np.inf]))

It's important to set initial bounds for a to avoid convergention failure or "Residuals are not finite in the initial point" issues. At last each point has its own crossing despite mad behavior of the close to 0 at the domain. Parameters are pretty close to 0 or 1 - not tending to infinity.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文