卡方检验转多项式拟合:基于Welch法的5阶多项式拟合技术问询
卡方检验融入多项式拟合的技术指导
结合你已经完成的Welch功率谱估计和5阶多项式拟合工作,我来一步步帮你把卡方检验的逻辑转化为拟合评估与优化的流程:
核心思路
卡方检验在这里的作用是量化你的多项式拟合模型与实际功率谱数据的匹配程度——通过计算残差的卡方统计量,判断拟合结果是否能合理解释观测数据,甚至帮你选择最优的多项式阶数。
具体步骤与代码整合
1. 先完成拟合值的完整计算
你已经通过curve_fit得到了5阶多项式的参数popt,先把拟合后的功率谱值完整计算出来(注意你是在log10域做的拟合,要还原回原始尺度):
# 计算log10(psd)的拟合值 log_psd_fit = line(freqs, *popt) # 还原为原始尺度的psd拟合值 psd_fit = 10 ** log_psd_fit
2. 计算卡方统计量
卡方统计量的核心公式是:$\chi^2 = \sum \frac{(Y_{观测} - Y_{拟合})^2}{Y_{拟合}}$,这里的$Y$就是你的功率谱数据。为了避免除以0的错误,先过滤掉拟合值过小的点:
# 过滤掉拟合值接近0的点,避免计算错误 mask = psd_fit > 1e-10 # 阈值可以根据你的数据动态调整 # 计算卡方统计量 chi_squared = np.sum((psd[mask] - psd_fit[mask]) ** 2 / psd_fit[mask])
3. 计算自由度与p值
自由度 = 有效数据点数量 - 拟合参数数量。你的5阶多项式有6个参数(a到f),所以:
from scipy import stats df = len(freqs[mask]) - 6 # 计算p值——p值越大,拟合与数据的一致性越好 p_value = 1 - stats.chi2.cdf(chi_squared, df)
通常来说,当p值>0.05时,我们认为拟合模型可以合理解释观测数据。
4. 用卡方检验优化拟合模型
- 如果p值过小:说明5阶多项式的拟合能力不足,或者你选择的log域拟合假设不够合理。可以尝试更高阶的多项式(比如6阶、7阶),或者尝试直接在原始psd尺度做非线性拟合(不过原始尺度动态范围大,需要更合理的初始参数估计)。
- 比较不同阶数的模型:分别拟合4阶、5阶、6阶多项式,计算各自的卡方统计量和p值,选择p值最大且阶数最精简的模型(避免过拟合)。
5. 整合后的完整代码示例
把以上步骤嵌入到你现有的代码中:
import numpy as np import matplotlib.pyplot as plt from scipy import signal, stats from scipy.optimize import curve_fit # 假设Bxfft是你的输入数据集 fig3 = plt.figure(3) for dataset in [Bxfft]: dataset = np.asarray(dataset) # Welch法计算功率谱 freqs, psd = signal.welch(dataset, fs=266336/300, window='hamming', nperseg=8192) plt.semilogy(freqs, psd/dataset.size**0, color='r', label='Original PSD') # 定义5阶多项式(用于拟合log10(psd)) def line(freqs, a, b, c, d, e, f): return a*freqs**5 + b*freqs**4 + c*freqs**3 + d*freqs**2 + e*freqs + f # 执行拟合 popt, pcov = curve_fit(line, freqs, np.log10(psd)) # 计算拟合值并绘制 log_psd_fit = line(freqs, *popt) psd_fit = 10 ** log_psd_fit plt.semilogy(freqs, psd_fit/dataset.size**0, color='b', label='5th-order Fit') # 卡方检验流程 mask = psd_fit > 1e-10 chi_squared = np.sum((psd[mask] - psd_fit[mask]) ** 2 / psd_fit[mask]) df = len(freqs[mask]) - 6 p_value = 1 - stats.chi2.cdf(chi_squared, df) # 输出检验结果 print(f"拟合结果卡方统计量: {chi_squared:.2f}") print(f"自由度: {df}") print(f"p值: {p_value:.4f}") plt.legend() plt.xlabel('Frequency (Hz)') plt.ylabel('Power Spectral Density') plt.show()
额外注意事项
- 加权卡方的优化:Welch法得到的每个psd点本身有统计自由度(由分段数和重叠率决定),更准确的卡方检验应该用每个psd点的方差来加权,方差可以近似为
psd * 2 / dof(dof为Welch法的自由度),此时卡方统计量为sum( (psd - psd_fit)^2 / var_psd ),结果会更贴合统计假设。 - log域拟合的偏差:因为你是在log10域做线性拟合,原始域的残差分布可能和卡方检验假设的正态分布有偏差。如果对统计严谨性要求高,可以尝试直接拟合原始psd尺度的非线性模型(即
psd = 10^(a*freqs^5 + ... + f)),不过这需要更合理的初始参数估计。
内容的提问来源于stack exchange,提问作者MolyPoly
相关产品推荐
相关产品推荐

