本文目录导读:

我来详细介绍Python中实现数据拟合的几种常用方法。
多项式拟合 (使用numpy)
import numpy as np
import matplotlib.pyplot as plt
# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 20)
y = 2 * x + 3 + np.random.randn(20) * 0.5 # 线性关系加噪声
# 一次多项式拟合(线性拟合)
coeffs = np.polyfit(x, y, 1)
p = np.poly1d(coeffs)
# 预测值
y_fit = p(x)
# 可视化
plt.figure(figsize=(10, 6))
plt.scatter(x, y, label='原始数据', alpha=0.7)
plt.plot(x, y_fit, 'r-', label=f'拟合直线: y = {coeffs[0]:.2f}x + {coeffs[1]:.2f}')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid(True, alpha=0.3)'线性拟合示例')
plt.show()
print(f"斜率: {coeffs[0]:.4f}")
print(f"截距: {coeffs[1]:.4f}")
非线性拟合 (使用scipy)
from scipy.optimize import curve_fit
import numpy as np
import matplotlib.pyplot as plt
# 定义目标函数(指数函数)
def func(x, a, b, c):
return a * np.exp(-b * x) + c
# 生成示例数据
x_data = np.linspace(0, 4, 50)
y_data = func(x_data, 2.5, 1.3, 0.5) + 0.2 * np.random.randn(50)
# 进行拟合
popt, pcov = curve_fit(func, x_data, y_data, p0=(1, 1, 1))
# 获取拟合参数
a_fit, b_fit, c_fit = popt
y_fit = func(x_data, a_fit, b_fit, c_fit)
# 计算拟合优度
residuals = y_data - y_fit
ss_res = np.sum(residuals**2)
ss_tot = np.sum((y_data - np.mean(y_data))**2)
r_squared = 1 - (ss_res / ss_tot)
# 可视化
plt.figure(figsize=(10, 6))
plt.scatter(x_data, y_data, label='原始数据', alpha=0.7)
plt.plot(x_data, y_fit, 'r-', label=f'拟合曲线: y = {a_fit:.2f} * exp(-{b_fit:.2f}x) + {c_fit:.2f}')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid(True, alpha=0.3)f'非线性拟合示例 (R² = {r_squared:.4f})')
plt.show()
print(f"拟合参数: a={a_fit:.4f}, b={b_fit:.4f}, c={c_fit:.4f}")
print(f"R² = {r_squared:.4f}")
使用机器学习方法 (scikit-learn)
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
from sklearn.metrics import r2_score
import numpy as np
import matplotlib.pyplot as plt
# 生成示例数据
np.random.seed(42)
x = np.linspace(-3, 3, 100)
y = 0.5 * x**3 - 2 * x**2 + x + 1 + np.random.randn(100) * 2
# 准备数据
X = x.reshape(-1, 1)
# 尝试不同阶数的多项式
degrees = [1, 2, 3, 5]
plt.figure(figsize=(12, 10))
for i, degree in enumerate(degrees, 1):
# 创建多项式回归模型
model = make_pipeline(PolynomialFeatures(degree), LinearRegression())
model.fit(X, y)
# 预测
y_pred = model.predict(X)
r2 = r2_score(y, y_pred)
# 可视化
plt.subplot(2, 2, i)
plt.scatter(x, y, alpha=0.5, label='原始数据')
plt.plot(x, y_pred, 'r-', label=f'阶数={degree}, R²={r2:.3f}', linewidth=2)
plt.xlabel('x')
plt.ylabel('y')
plt.title(f'多项式拟合 (阶数={degree})')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
完整案例:温度数据拟合
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from sklearn.metrics import r2_score, mean_squared_error
# 模拟温度数据(小时 vs 温度)
hours = np.array([0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24])
temperature = np.array([15, 14, 13, 14, 17, 21, 25, 28, 29, 27, 23, 19, 16])
# 正弦函数拟合(考虑昼夜温度变化)
def temp_model(h, a, b, c, d):
return a * np.sin(b * (h - c)) + d
# 拟合
popt, pcov = curve_fit(temp_model, hours, temperature,
p0=[7, 0.3, 6, 20])
# 生成连续预测
hours_smooth = np.linspace(0, 24, 200)
temp_pred = temp_model(hours_smooth, *popt)
# 评估模型
temp_fitted = temp_model(hours, *popt)
r2 = r2_score(temperature, temp_fitted)
rmse = np.sqrt(mean_squared_error(temperature, temp_fitted))
# 可视化
plt.figure(figsize=(12, 6))
plt.scatter(hours, temperature, color='blue', s=100, zorder=5,
label='实际观测数据')
plt.plot(hours_smooth, temp_pred, 'r-', linewidth=2,
label=f'拟合曲线 (R²={r2:.3f}, RMSE={rmse:.2f}°C)')
plt.xlabel('时间 (小时)', fontsize=12)
plt.ylabel('温度 (°C)', fontsize=12)'24小时温度变化拟合', fontsize=14)
plt.grid(True, alpha=0.3)
plt.legend(fontsize=11)
plt.xticks(np.arange(0, 25, 2))
plt.xlim(0, 24)
plt.tight_layout()
plt.show()
print(f"拟合参数:")
print(f"振幅: {popt[0]:.2f}°C")
print(f"频率: {popt[1]:.4f}")
print(f"相位偏移: {popt[2]:.2f}小时")
print(f"基线温度: {popt[3]:.2f}°C")
print(f"\n模型评估:")
print(f"R² 分数: {r2:.4f}")
print(f"均方根误差: {rmse:.2f}°C")
高级:带置信区间的拟合
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy import stats
def plot_fit_with_confidence(x, y, func, popt, pcov, alpha=0.05):
"""
绘制拟合曲线和置信区间
"""
# 生成平滑的x值
x_smooth = np.linspace(x.min(), x.max(), 300)
y_smooth = func(x_smooth, *popt)
# 计算置信区间
residuals = y - func(x, *popt)
n = len(y)
p = len(popt)
dof = n - p # 自由度
t_value = stats.t.ppf(1 - alpha/2, dof)
# 计算标准误差
sse = np.sum(residuals**2)
mse = sse / dof
# 计算置信区间(简化的方法)
std_error = np.sqrt(mse) * np.sqrt(1/n + (x_smooth - x.mean())**2 /
np.sum((x - x.mean())**2))
# 绘图
plt.figure(figsize=(10, 6))
plt.scatter(x, y, alpha=0.7, label='数据点')
plt.plot(x_smooth, y_smooth, 'r-', label='拟合曲线', linewidth=2)
# 置信区间
ci = t_value * std_error
plt.fill_between(x_smooth, y_smooth - ci, y_smooth + ci,
alpha=0.2, color='red', label=f'{1-alpha:.0%} 置信区间')
plt.xlabel('x')
plt.ylabel('y')
plt.title('带置信区间的拟合')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 示例:线性回归带置信区间
np.random.seed(42)
x = np.linspace(0, 10, 20)
y = 2 * x + 3 + np.random.randn(20) * 2
plot_fit_with_confidence(x, y, lambda x, a, b: a*x + b, [2, 3], None)
-
选择合适的方法:
- 线性数据:
np.polyfit - 多项式数据:
scikit-learn的PolynomialFeatures - 非线性数据:
scipy.optimize.curve_fit
- 线性数据:
-
模型评估指标:
- R²(决定系数):越接近1越好
- RMSE(均方根误差):越小越好
- 残差分析:检查残差分布是否随机
-
注意事项:
- 避免过拟合:不要使用过高阶的多项式
- 数据预处理:标准化/归一化
- 参数初始值:为
curve_fit提供合理的初始猜测
这些方法可以应对大多数数据拟合需求,根据具体问题选择最合适的方案即可。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播