MATLAB中含x^d项的自定义拟合函数报错及结果不佳问题求助
MATLAB自定义广义伽马分布拟合问题解决建议
问题背景
尝试用带$x^d$项的广义伽马分布(形式为 $a \cdot x^d \cdot \exp\left(-\left(\frac{x-b}{c}\right)^2\right)$)拟合一组数据,高斯拟合正常,但自定义函数拟合遇报错,添加约束和初始值后参数无更新。
已做尝试
1. 高斯拟合成功
使用gauss1模型拟合以下数据:
- data_x:
0 0.0500000000000000 0.100000000000000 0.150000000000000 0.200000000000000 0.250000000000000 0.300000000000000 0.350000000000000 0.400000000000000 0.450000000000000 0.500000000000000 0.550000000000000 0.600000000000000 0.650000000000000 0.700000000000000 0.750000000000000 0.800000000000000 0.850000000000000 0.900000000000000 0.950000000000000 1 1.05000000000000 1.10000000000000 1.15000000000000 1.20000000000000 1.25000000000000 1.30000000000000 1.35000000000000 1.40000000000000 1.45000000000000
- data_y:
4.82569292042591 6.15748191498009 4.31807282776559 2.46795497033244 1.17871657319353 0.518857189303422 0.242237665610014 0.121149313175648 0.0619970738844184 0.0346663415427132 0.0237950093473137 0.0164594001463058 0.00944891489880517 0.00268227261643502 0.00288547508737706 0.00247907014549297 0.00195074372104365 0.00213362594489149 0.00174754125010160 0.00168658050881899 0.00140209704950012 0.00138177680240592 0.00146305779078274 0.00125985531984069 0.00111761359018126 0.00123953507274648 4.06404941884093e-05 0 0 0
代码:
fit_result = fit(data_x, data_y, 'gauss1');
得到系数:a1=5.79, b1=0.04453, c1=0.1165。
2. 自定义函数拟合报错
使用自定义广义伽马分布函数:
gamma_distribution = @(a, d, b, c, x) a * x.^d .* exp(-((x-b)/c).^2); fit_result = fit(data_x, data_y, gamma_distribution);
报错:
Error using fit>iFit (line 340)
Inf computed by model function, fitting cannot continue.
Try using or tightening upper and lower bounds on coefficients.
3. 添加参数约束仍报错
添加上下限后代码:
gamma_distribution = @(a, d, b, c, x) a * x.^d .* exp(-((x-b)/c).^2); fit_result = fit(data_x, data_y, gamma_distribution, 'Lower', [-10, -10, -10, -10], 'Upper', [10, 10, 10, 10]);
报错问题未解决。
4. 添加初始值后参数无更新
用高斯拟合结果作为初始值(d设为0):
gamma_distribution = @(a, d, b, c, x) a * x.^d .* exp(-((x-b)/c).^2); fit_result = fit(data_x, data_y, gamma_distribution, 'Start', [5.79, 0, 0.04453, 0.1165], 'Lower', [-10, -10, -10, -10], 'Upper', [10, 10, 10, 10]);
运行成功但参数与初始值完全一致,d始终为0,拟合无改进。
解决建议
1. 修复函数的x=0处数值问题
当d<0时,x=0会导致0^d变成Inf,这是报错的核心原因。修改函数,对x=0做特殊处理:
gamma_distribution = @(a, d, b, c, x) a .* (x + eps).^d .* exp(-((x-b)/c).^2);
添加eps(MATLAB的极小值)避免x=0时出现Inf。
2. 优化参数约束范围
根据数据特征和物理意义缩小约束,避免参数进入无意义区间:
a:数据峰值在6左右,设Lower=0,Upper=10(y值均为正,a无需负数)d:先尝试[-2,2]的合理范围,避免极端值b:峰值在x=0.05附近,约束在[0, 0.5]c:控制分布宽度,设[0.05, 0.5](必须为正,避免分母为0)
修改后的代码:
gamma_distribution = @(a, d, b, c, x) a .* (x + eps).^d .* exp(-((x-b)/c).^2); fit_result = fit(data_x, data_y, gamma_distribution, ... 'Start', [5.79, 0.5, 0.04453, 0.1165], ... % 给d一个非0初始值,打破局部最优 'Lower', [0, -2, 0, 0.05], ... 'Upper', [10, 2, 0.5, 0.5]);
3. 更换拟合算法
默认拟合算法可能陷入局部最优,尝试用lsqcurvefit手动控制优化过程:
% 定义拟合函数 gamma_fun = @(params, x) params(1) .* (x + eps).^params(2) .* exp(-((x-params(3))/params(4)).^2); % 初始参数 start_params = [5.79, 0.5, 0.04453, 0.1165]; % 参数约束 lb = [0, -2, 0, 0.05]; ub = [10, 2, 0.5, 0.5]; % 执行拟合 params_fit = lsqcurvefit(gamma_fun, start_params, data_x, data_y, lb, ub); % 可视化拟合结果 y_fit = gamma_fun(params_fit, data_x); plot(data_x, data_y, 'o', data_x, y_fit, '-'); legend('原始数据', '拟合曲线');
4. 数据预处理
x≥1.35后y值为0,这些无效点会干扰拟合,可只保留x∈[0,1.3]的数据进行拟合:
valid_idx = data_x <= 1.3; data_x_valid = data_x(valid_idx); data_y_valid = data_y(valid_idx);
内容的提问来源于stack exchange,提问作者yang lee
相关产品推荐
相关产品推荐

