Python案例如何实现数据拟合?

wen python案例 1

本文目录导读:

Python案例如何实现数据拟合?

  1. 多项式拟合 (使用numpy)
  2. 非线性拟合 (使用scipy)
  3. 使用机器学习方法 (scikit-learn)
  4. 完整案例:温度数据拟合
  5. 高级:带置信区间的拟合

我来详细介绍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)
  1. 选择合适的方法

    • 线性数据:np.polyfit
    • 多项式数据:scikit-learnPolynomialFeatures
    • 非线性数据:scipy.optimize.curve_fit
  2. 模型评估指标

    • R²(决定系数):越接近1越好
    • RMSE(均方根误差):越小越好
    • 残差分析:检查残差分布是否随机
  3. 注意事项

    • 避免过拟合:不要使用过高阶的多项式
    • 数据预处理:标准化/归一化
    • 参数初始值:为curve_fit提供合理的初始猜测

这些方法可以应对大多数数据拟合需求,根据具体问题选择最合适的方案即可。

抱歉,评论功能暂时关闭!