You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用最小二乘法拟合线段?LsqFit.jl使用问题咨询

问题与解决

问题背景

我尝试用最小二乘法拟合一条线段(样式如下):
线段样式

现有代码存在数据提取错误、模型选错、初始参数不合理等问题,导致拟合失败或不符合需求:

using LsqFit
img=load("img_file.jpg")
nodes=findall(img.>0)
xdata=map(p->p[2], nodes)
ydata=map(p->p[2], nodes) # 错误:y坐标应该取p[1]
p=[0.5,0.5]#nodes[1]
m(t, p) = p[1] * exp.(p[2] * t) # 错误:用了指数模型,实际要拟合直线
fit = curve_fit(model, xdata, ydata, p)

## 初始参数改为node[1]时出现Inf报错
fit = curve_fit(m, xdata, ydata, [8.0,273.0])

需求是为nodes中的笛卡尔索引拟合多项式直线,但不清楚如何正确传递curve_fit参数;替换初始参数后出现Inf值报错,也不知道如何分析拟合结果、获取直线的笛卡尔索引。相关图示:
拟合目标
Inf报错


分步解决

1. 修正坐标提取

笛卡尔索引中,p[1]对应行号(y轴),p[2]对应列号(x轴),修正数据提取代码:

xdata = map(p -> p[2], nodes)  # 列号作为x坐标
ydata = map(p -> p[1], nodes)  # 行号作为y坐标

2. 定义直线拟合模型

直线的数学形式为y = 截距 + 斜率*x,替换原指数模型:

# 直线模型:p[1]是截距,p[2]是斜率
linear_model(t, p) = p[1] .+ p[2] .* t

3. 设置合理初始参数

初始参数要贴合直线的实际范围,避免过大值导致溢出(比如原指数模型用273作为参数会直接生成Inf):

# 示例初始参数:截距0,斜率1,可根据数据调整
initial_p = [0.0, 1.0]
# 执行拟合
fit_result = curve_fit(linear_model, xdata, ydata, initial_p)

4. 提取拟合结果与生成笛卡尔索引

  • 获取拟合参数:fit_result.param返回截距和斜率
  • 生成拟合直线的笛卡尔索引:
# 提取拟合得到的截距a和斜率b
a, b = fit_result.param

# 生成覆盖原数据x范围的拟合点
x_range = minimum(xdata):maximum(xdata)
y_fit = @. a + b * x_range

# 转换为笛卡尔索引(行号取整为整数)
fit_nodes = [CartesianIndex(round(Int, y), x) for (x, y) in zip(x_range, y_fit)]

5. Inf报错原因说明

原代码用指数模型p[1]*exp(p[2]*t),当p[2]取273这类大值时,exp(273*t)会因数值溢出直接变成Inf,导致拟合失败。换成直线模型后,不存在指数溢出问题,同时初始参数控制在合理范围即可避免报错。


内容的提问来源于stack exchange,提问作者F612

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 22:25:25