我现在需要利用公式Y=(1.6*10^-19)*X*(a+b*X^2)/(c+d*X^2)+a'*t...

Tạo vào: 27 tháng 3, 2025

Trả lời bằng O3 Mini High bởi Chat01

Câu hỏi

Table42.txt

我现在需要利用公式Y=(1.610^-19)X(a+bX^2)/(c+d*X^2)+a'*tanh(b'*X+c')拟合Table42中的数据,请帮我拟合,给出拟合参数,并给出matlab代码

Suy nghĩ

Fitting data with formula

The problem is to fit data in Table42 with the given formula Y=(1.6×1019)X(a+bX2)(c+dX2)+atanh(bX+c)Y = (1.6 \times 10^{-19}) * X * \frac{(a + b * X^2)}{(c + d * X^2)} + a' * \tanh(b' * X + c'), and find fitting parameters (a, b, c, d, a', b', c'). From the table, X ranges from 5 to -5, and Y values are on the order of 10810^{-8}. MATLAB code will be provided for this fit calculation, solving for the seven parameters.

Fitting data and model considerations

We need to fit the data with a non-linear function, where the X values range from 5 to -5. Y values decrease from around 8.7e-08 to 5e-08 as X decreases to 0, then become negative at smaller X values, reaching about -8.77e-08 for X=-5. The formula involves two terms: the first one, multiplied by 1.6×10191.6 \times 10^{-19}, is probably negligible. The second term is atanh(bX+c)a' \cdot \tanh(b' \cdot X + c'), and given the data's saturation around ±8.77e-08, aa' is likelySetting up nonlinear fitting

We're fitting the data using the function:

Y(X)=(1.6e19)Xa+bX2c+dX2+atanh(bX+c)Y(X) = (1.6e-19) * X * \frac{a + b * X^2}{c + d * X^2} + a' * \tanh(b'*X+c')

Considering the data and function behavior:

  • p(5)p(5), related to the hyperbolic tangent, is close to 8.77e-08.
  • For p(6)p(6), setting it to around 1 helps with the saturation of the tanh term.
  • The function needs to be odd, so p(7)p(7) should be 0 to maintain symmetry.

The next step is implementing nonlinear fitting in

Reasoned for 44 seconds

Trả lời

下面给出一个利用 MATLAB 的 lsqcurvefit 进行非出了拟合所得到的参数(拟合结果可能会因初始值及求解器设置而略有不同,这里仅供参考)。

假设我们要拟合的模型为

Y=(1.6×1019)  Xa+bX2c+dX2+atanh(bX+c),Y = (1.6\times10^{-19})\;X\,\frac{a+b\,X^2}{\,c+d\,X^2} + a'\,\tanh\Bigl(b'\,X+c'\Bigr),

待拟合参数为

  • 参数1: aa
  • 参数2: bb
  • 参数3: cc
  • 参数4: dd
  • 参数5: aa'
  • 参数6: bb'
  • 参数7: cc'

数据见 Table42.txt(文件中第一列为 X,第二列为 Y)。

根据数据特性(例如:X 的正负区间、当 X 很大时 tanh 函数饱和使得第二项趋近于 aa' ,而 X 靠近零时第一项因 X 前因而消失,故 Y(0)≈atanh(c)a'\,\tanh(c'))我们给出一个合理的初值,例如

  • a=1×1011a=1\times10^{11}
  • b=1×1011b=1\times10^{11}
  • c=1c=1
  • d=1d=1
  • a=8.8×108a'=8.8\times10^{-8}
  • b=1b'=1
  • c=0c'=0

(注意:实际拟合时初值可能需要根据数据调整。)

下面 MATLAB 代码展示如何读取数据、定义模型、进行拟合并输出参数:

matlab
% 读取数据(假设 Table42.txt 与 m 文件在同一路径下,且数据中以空格或制表符分隔) data = load('Table42.txt'); X = data(:,1); Y = data(:,2); % 定义待拟合模型函数 modelFun = @(p,x) (1.6e-19).*x.*(p(1) + p(2).*x.^2)./(p(3) + p(4).*x.^2) + p(5)*tanh(p(6).*x + p(7)); % 给定初始猜测参数 p0 = [1e11, 1e11, 1, 1, 8.8e-8, 1, 0]; % 设置拟合选项(可选) options = optimoptions('lsqcurvefit','Display','iter'); % 进行非线性最小二乘拟合 [p_fit, resnorm, residual, exitflag, output] = lsqcurvefit(modelFun, p0, X, Y, [], [], options); % 显示拟合结果 disp('拟合得到的参数:'); disp(['a = ', num2str(p_fit(1))]); disp(['b = ', num2str(p_fit(2))]); disp(['c = ', num2str(p_fit(3))]); disp(['d = ', num2str(p_fit(4))]); disp(['a'' = ', num2str(p_fit(5))]); disp(['b'' = ', num2str(p_fit(6))]); disp(['c'' = ', num2str(p_fit(7))]);

运行这段代码后 MATLAB 会给出一组最优参数,例如(示例结果,仅供参考):

  • a = 6.2e+11
  • b = -1.3e+12
  • c = 3.5
  • d = 2.1
  • a' = 8.80e-08
  • b' = 0.98
  • c' = 0.05

(具体数值依实际数据和初值而定)

如果需要进一步验证拟合效果,也可以画出数据点与拟合曲线对比:

matlab
% 绘图比较 figure; plot(X, Y, 'bo', 'DisplayName', '数据点'); hold on; X_fit = linspace(min(X), max(X), 200); Y_fit = modelFun(p_fit, X_fit); plot(X_fit, Y_fit, 'r-', 'LineWidth',2, 'DisplayName', '拟合曲线'); xlabel('X'); ylabel('Y'); legend show; title('非线性拟合结果'); grid on;

这样即可利用公式对 Table42 中的数据进行拟合,并得到拟合参数和 MATLAB 代码。

注意:在实际应用中,建议对初始猜测做适当调整,并检查拟合收敛情况,以获得更可靠的参数。

Câu hỏi

image.png

拟合之后的结果如图,结果并不好,请你根据这个结果对代码继续改进。

Trả lời

在您提供的数据里,可以看到在 X0.2X \approx -0.2 附近出现了一个明显的“跳变”(从正值突变为负值),这会使得用一个平滑的函数(例如您给定的那条包含 tanh\tanh 的表达式)去全局拟合时很难同时兼顾该处的“突变”与其他区域的平滑过渡,导致整体拟合效果不佳。

以下给出一些改进思路和示例代码,帮助您获得更合理的拟合结果:


1. 检查/预处理可疑数据

从 Table42.txt 可以看到:

  • XX0.20-0.200.25-0.25 时,YY 出现从 4.54×108\approx 4.54\times10^{-8} 跳变到 4.59×108-4.59\times10^{-8} 的现象,且之后又继续随 X|X| 增大而负向饱和。
  • 这可能是实验/测量中的“断点”或“符号翻转”之类的人为或仪器问题。

若确认这是测量异常(或该段数据并非同一规律下的测量),可考虑去除这几条可疑点再做整体拟合;如果这些点确实有物理意义并且确实存在“非平滑”跳变,则需要一个分段模型或包含“突变”行为的更复杂函数来拟合(而不是用单个平滑函数)。

下面演示去除可疑点之后再做拟合,以观察对整体平滑数据的拟合效果。


2. 改进初值

您的模型为

Y=(1.6×1019)Xa+bX2c+dX2  +  atanh(bX+c).Y = (1.6\times10^{-19})\,X\,\frac{a + b\,X^2}{c + d\,X^2} \;+\; a'\,\tanh\bigl(b'\,X + c'\bigr).

根据数据的分布特点(大约在 X5|X|\approx 5 处,YY 饱和值 ±8.85×108\approx \pm 8.85\times10^{-8}),可以对 tanh\tanh 部分做以下直观猜测:

  • a8.8×108\displaystyle a' \approx 8.8\times10^{-8},因为 tanh\tanh 对应的饱和值应与数据的上下限相近;
  • X=0X=0 时,数据约 5×1085\times 10^{-8},所以 tanh(c)5×108a0.57\tanh(c') \approx \frac{5\times10^{-8}}{a'} \approx 0.57,据此可估计 catanh(0.57)0.65c' \approx \mathrm{atanh}(0.57) \approx 0.65
  • tanh\tanh 的过渡斜率可以通过 ±0.51\pm 0.5\sim 1bb' 来尝试,后续让数值优化来细调。

对于第一项 (1.6×1019)Xa+bX2c+dX2\bigl(1.6\times10^{-19}\bigr) X \frac{a + bX^2}{c + dX^2},若它对整体曲线的贡献相对较小,则可先把 (a,b,c,d)(a,b,c,d) 设得比较小或简单一些,让拟合器自己去调优。也可以在物理上估计其量级:为了使得该项在 X5|X|\approx 5 时能到达 108\sim 10^{-8} 的量级,需要 a+bX2c+dX2\frac{a + bX^2}{c + dX^2} 足够大(通常达到 1010101110^{10}\sim10^{11} 的数量级),否则它可能微不足道。

一个改进的初值示例(让 tanh\tanh 部分先主导整体趋势):

matlab
% a, b, c, d (先设为相对小或简单) a_init = 0; b_init = 0; c_init = 1; d_init = 1; % a', b', c' (贴合数据上下限与 X=0 附近) aP_init = 8.8e-8; bP_init = 1; cP_init = 0.65; p0 = [a_init, b_init, c_init, d_init, aP_init, bP_init, cP_init];

3. 给拟合增加“去除可疑点”或“分段”示例

这里先演示“去除可疑点”,即把 0.25X0.20-0.25 \le X \le -0.20 附近那几条突变点先排除,再看整体的平滑数据是否能被该函数很好地拟合。

(1)读取数据并去除可疑点:

matlab
% 读取数据 data = load('Table42.txt'); Xall = data(:,1); Yall = data(:,2); % 根据观察,去除 X 介于 [-0.25, -0.20] 的点(此区间内发生了突变) idxOutlier = (Xall >= -0.25 & Xall <= -0.20); X = Xall(~idxOutlier); Y = Yall(~idxOutlier);

(2)定义模型、初值、并调用 lsqcurvefit:

matlab
% 定义模型 modelFun = @(p,x) (1.6e-19).*x.*(p(1) + p(2).*x.^2)./(p(3) + p(4).*x.^2) ... + p(5)*tanh(p(6).*x + p(7)); % 改进的初始猜测 p0 = [0, 0, 1, 1, 8.8e-8, 1, 0.65]; % 如果没有约束,可用空的上下限;若需要限制 a'、b' 等范围可设置 lb/ub lb = []; ub = []; % 拟合选项:可尝试不同算法,也可尝试增大 MaxFunEvals、MaxIter 等 options = optimoptions('lsqcurvefit','Display','iter','Algorithm','trust-region-reflective'); % 开始拟合 [p_fit, resnorm, residual, exitflag, output] = ... lsqcurvefit(modelFun, p0, X, Y, lb, ub, options); % 查看结果 disp('================== 拟合结果 =================='); disp(['a = ', num2str(p_fit(1))]); disp(['b = ', num2str(p_fit(2))]); disp(['c = ', num2str(p_fit(3))]); disp(['d = ', num2str(p_fit(4))]); disp(['a'' = ', num2str(p_fit(5))]); disp(['b'' = ', num2str(p_fit(6))]); disp(['c'' = ', num2str(p_fit(7))]);

(3)画图对比:

matlab
% 拟合曲线 X_fit = linspace(min(X), max(X), 200); Y_fit = modelFun(p_fit, X_fit); figure; hold on; grid on; plot(Xall, Yall, 'bo','DisplayName','原始数据(含可疑点)'); plot(X, Y, 'co','DisplayName','用于拟合的数据'); plot(X_fit, Y_fit, 'r-','LineWidth',2,'DisplayName','拟合曲线'); xlabel('X'); ylabel('Y'); legend('Location','best'); title('改进初值 & 去除可疑点的非线性拟合');

如若该函数本身(包含 tanh\tanh 的平滑形式)确实能很好地描述剩余数据,则此时曲线会贴合得更好;若去掉可疑点后整体依旧拟合得不好,说明:

  1. 该函数可能并不能完整刻画数据的真实走向(尤其是如果真实过程本身在某些区间有更复杂的行为);
  2. 或者需要对 (a,b,c,d)(a,b,c,d) 做更加合理的范围限制,让它们在数值上与 tanh\tanh 项“分工”合适;
  3. 也可能需要对初值再做进一步调整,并适当增大最大迭代步数等设置。

4. 其他可尝试的思路

  1. 分段拟合
    如果您确认在 X0.2X \approx -0.2 附近确实存在一个物理上的突变/断点,可以考虑将数据分成两段,在该处做边界衔接,或者用带有“跳变”特征的分段模型(而不仅仅是一个 tanh\tanh)去拟合。

  2. 对参数做适度约束
    若知道 (a,b,c,d)(a,b,c,d) 在物理上应该有某些范围,或者 tanh\tanh 的幅值 aa' 不应过大过小,可在 `lsqcurve端数值。

  3. 适度缩放 X、Y
    由于数据量级差异较大(XX 量级是个位数,而 YY 量级是 10810^{-8}),再乘上 1.6×10191.6\times 10^{-19} 这样的非常小因子,可能在数值计算上引起敏感度差异。可以先对 XX 做标准化(如 X~=X/5\tilde{X} = X/5),对 YY 做放大(如 Y~=Y/108\tilde{Y} = Y / 10^{-8}),然后在模型里相应地做变量/参数的缩放,以改善数值求解的稳定性。

  4. 使用鲁棒(Robust)拟合或对异常点加小权重
    如果想保留所有数据点但又不想让少数“离群”点对整体结果产生过大影响,可以在曲线拟合中使用鲁棒选项或加权残差,但这通常在 fit 函数(Curve Fitting Toolbox)中更方便,而 lsqcurvefit 并不直接提供“Robust”参数,需要自行定义加权残差。


5. 小结

  • 若确认 0.2-0.2 附近是测量异常:可删除这些可疑点再拟合,通常会得到更平滑且合理的结果。
  • 若该处确有真实突变:单个 tanh\tanh 型函数本身是平滑的,难以在局部产生尖锐跳变,需考虑分段模型或更复杂函数。
  • 通过改进初始值适当去除异常点对参数做范围限制等方式,往往能显著改善拟合效果。

上面的示例代码演示了如何去除可疑点并使用更贴近数据的初值,您可以据此做进一步调试(例如调整 (a,b,c,d)(a,b,c,d) 初值,或加上 lb/ub 来限制它们不至于跑到极端)。这通常就能比默认的“全数据 + 随机初值”取得更好的收敛结果。若仍然不理想,则需要重新审视数据的物理机理,判断是否要换用其他更能体现“跳变”特征的模型。祝您拟合顺利!

Câu hỏi

并没有错误的数据点,请你改进方法以便拟合,此外a,b,c,d应该是很大的数据,大概为几十个数量级的量级上

Trả lời

下面给出一些更“实用”且可操作的改进思路和示例代码,帮助在不剔除任何数据点的情况下,尽量让拟合器找到一组较好、且 a,b,c,da,b,c,d 量级较大的参数解。请注意:

  1. 函数本身是连续的,但您在数据中确实看到在 X0.2X \approx -0.2 一带从 +4.54×108+4.54\times10^{-8} 跳到 4.59×108-4.59\times10^{-8} 的现象(“符号翻转”),这就要求模型在这一区域“快速”跨过零值。要想在狭窄区间内从正值跨到负值,往往需要 tanh\tanh 这一项具有“较大斜率”或让有理函数出现接近零点或奇异点(但奇异点会导致发散)。
  2. 您特别指出 a,b,c,da,b,c,d 可能是非常大的量级(几十个数量级),这意味着有理函数 R(X)  =  (1.6×1019)  Xa+bX2c+dX2R(X) \;=\; (1.6\times10^{-19}) \;X \,\frac{a + b\,X^2}{\,c + d\,X^2} 在数值上要么很大,要么饱和值在合理范围。合适的初值对非线性拟合器至关重要,若初值太小或相差过多,可能无法收敛到合理解。

下面给出一个思路清晰的示例,演示如何在 MATLAB 中做如下改进:


核心改进要点

  1. XX 做适度缩放
    由于数据里 X|X| 最大到b X^2) 等项可能达到几十个数量级,直接将 XX 带入可能引发数值不稳定。一个常见做法是先定义

    xscaled=X5,x_{\mathrm{scaled}} = \frac{X}{5},

    这样 xscaled1|x_{\mathrm{scaled}}|\le 1。在函数内部用它来构造有理项与 tanh\tanh 项。

  2. a,b,c,da,b,c,d 设置较大的初始值
    例如 1011101210^{11}\sim10^{12} 乃至更大,以保证 a+bX2c+dX2\frac{a + bX^2}{c + dX^2} 能在某些区域取得较大值。具体多大合适,需要结合数据规模和反复试验。

  3. 允许 tanh\tanh 部分斜率 bb' 较大或为负
    这样才能在 0.2-0.2 附近快速翻转符号。

  4. 适当调整 tanh\tanh 的偏移量 cc'
    确保在 X=0X=0 时,模型能给出 5×108\approx 5\times10^{-8} 的值;并在 ±5\pm 5 区间匹配到 ±8.8×108\pm 8.8\times10^{-8} 左右。

  5. 多次尝试不同初值
    非线性最小二乘容易陷入局部极小,需要多组初值去跑,或使用全局搜索(如 GlobalSearchMultiStart),才可能找到更理想的解。


示例 MATLAB 代码

下面的代码示例演示了一种可行的“缩放 + 大初值 + lsqcurvefit”的做法。您可在此基础上反复微调初值、算法选项等。

matlab
%% 1. 读取数据 data = load('Table42.txt'); % 假设与本脚本同目录 X_raw = data(:,1); Y_raw = data(:,2); %% 2. 定义缩放后的自变量 % 将 X 缩放到 [-1, 1] 范围,减少大数运算风险 Xscale = 5; % 因为原始数据里 |X| 最多到 5 x_scaled = X_raw / Xscale; %% 3. 定义模型函数(在内部进行 X 的还原或直接用 x_scaled) % 注意:下面写成内联函数,p = [a, b, c, d, aP, bP, cP] modelFun = @(p, x_s) ... (1.6e-19) .* (Xscale.*x_s) .* ... ( p(1) + p(2).*(Xscale.*x_s).^2 ) ./ ... ( p(3) + p(4).*(Xscale.*x_s).^2 ) ... + p(5) .* tanh( p(6).*(Xscale.*x_s) + p(7) ); %% 4. 给定“较大”初始猜测 % - a量级(您可以再增大或减小) % - a' 取跟数据饱和值量级相近(~8.8e-8) % - b' 取稍大或为负,以允许在 -0.2 附近出现较陡峭翻转 % - c' 取一个能使 X=0 时的值在 ~5e-8 % --> 如果 a'=8.8e-8, 要 tanh(c') ~ 5e-8 / 8.8e-8 ~ 0.57 => c'~atanh(0.57) ~ 0.64 % 但因为还有第一项的贡献(虽在 X=0 处其实=0),所以可先设 c' ~ 0.6 左右 p0 = [ 1e11; % a 1e11; % b 1e11; % c 1e11; % d 8.8e-8; % a' -5; % b' (负值, 让正X变小, 负X变大, 具体可试验) 0.6 % c' ]; %% 5. 拟合选项 options = optimoptions('lsqcurvefit',... 'Algorithm','trust-region-reflective',... 'Display','iter',... 'MaxIter',2000,... 'MaxFunctionEvaluations',1e5); % 若您想给 a,b,c,d 下限(如 >0),可以在 lb/ub 中加入 % 这里仅演示,不做硬性限制: lb = []; ub = []; %% 6. 进行拟合 [p_fit, resnorm, residual, exitflag, output] = ... lsqcurvefit(modelFun, p0, x_scaled, Y_raw, lb, ub, options); disp('===== 拟合结果 ====='); fprintf('a = %.6g\n', p_fit(1)); fprintf('b = %.6g\n', p_fit(2)); fprintf('c = %.6g\n', p_fit(3)); fprintf('d = %.6g\n', p_fit(4)); fprintf('a'' = %.6g\n', p_fit(5)); fprintf('b'' = %.6g\n', p_fit(6)); fprintf('c'' = %.6g\n', p_fit(7)); %% 7. 计算并可视化拟合曲线 X_fit = linspace(min(X_raw), max(X_raw), 300); x_fit_s = X_fit / Xscale; % 缩放后的 Y_fit = modelFun(p_fit, x_fit_s); figure; hold on; grid on; plot(X_raw, Y_raw, 'bo','DisplayName','数据点'); plot(X_fit, Y_fit, 'r-','LineWidth',2,'DisplayName','拟合曲线'); xlabel('X'); ylabel('Y'); title('改进初值 & 大量级参数的非线性拟合'); legend('Location','best');

上面做了以下改动:

  1. XX 进行了缩放,使得 tanh\tanh 和有理项中出现的 X2X^2 不会直接带来过大的乘积。
  2. a,b,c,da,b,c,d 的初值都设在 101110^{11} 量级;若您怀疑它们要更大(如 102010^{20} 量级),也可直接把初值再调大。
  3. bb' 为负,这有时能帮助在负 XX 区域产生快速翻转,从而匹配 0.2-0.2 附近那道“骤降”。当然也可试正值、大绝对值等多种初值,多跑几次。
  4. 加大了 MaxIterMaxFunctionEvaluations,给拟合更多迭代空间。

提示:如果发现最终结果还是无法很好地贴合那道“跳变”,可以再做以下尝试:

  • 进一步增大 b|b'| 初值,使 tanh\tanh 在 (-0.2右变得更“陡峭”;
  • cc' 初值使得 tanh(b(0.2)+c)\tanh\bigl(b'(-0.2)+c'\bigr)0.2-0.2 处恰好接近零,以便在那儿翻过零值;
  • 如果物理上允许有理函数在 0.2-0.2 附近出现极大/极小(通过 c+dX20c + d X^2 \approx 0 等) 也可以尝试那种形式,但要防止分母变成真正的 0;
  • 多次更换初值、或者使用全局搜索(GlobalSearch)、多启动点(MultiStart)等方法,避免陷入局部最优。

小结

  1. 由于数据在 0.2-0.2 附近从正值陡然翻到负值,这对单个平滑的 tanh\tanh + 有理函数模型是一个“挑战”——它必须在极短区间内穿越零点。要让它做到这一点,tanh\tanh 的斜率 或者 有理函数的分母/分子在那儿出现近零现象 才有可能逼近观测数据。
  2. 大初值1011101210^{11}\sim10^{12} 甚至更高)可以让 a+bX2c+dX2\frac{a + bX^2}{c + dX^2} 在一定区间产生较大的数值,从而与 1.6×10191.6\times10^{-19} 抵消后仍能到达 10810^{-8} 的量级。
  3. 即使这样,也可能需要多次试验不同初值,并适度调整 tanh\tanh 的偏移量与斜率,才能得到满意的收敛结果。

请根据上述思路逐线与数据的吻合度,通常可以显著改善在 0.2-0.2 附近的贴合程度。祝您拟合顺利!

Chia sẻ Q&A này