最小二乘法的直线拟合

由于网上没有找到直接的代码,就来写一下。
原理部分可以回去看高数,核心就是以直线的斜率和截距为变量,让误差最小化。以下是代码部分

import numpy as np
import matplotlib.pyplot as plt

def linear_least_squares(q_list, n_list):
    """
    最小二乘法直线拟合
    
    参数:
    q_list: x坐标数据列表
    n_list: y坐标数据列表
    
    返回:
    slope: 直线斜率
    intercept: 直线截距
    fig: 图像对象
    """
    
    # 将列表转换为numpy数组
    x = np.array(q_list)
    y = np.array(n_list)
    
    # 计算必要的数据和
    n = len(x)
    sum_x = np.sum(x)
    sum_y = np.sum(y)
    sum_xy = np.sum(x * y)
    sum_x2 = np.sum(x ** 2)
    
    # 计算斜率和截距
    slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x ** 2)
    intercept = (sum_y - slope * sum_x) / n
    
    # 计算拟合的y值
    y_fit = slope * x + intercept
    
    # 计算相关系数R²
    y_mean = np.mean(y)
    ss_tot = np.sum((y - y_mean) ** 2)
    ss_res = np.sum((y - y_fit) ** 2)
    r_squared = 1 - (ss_res / ss_tot)
    
    # 创建图像
    fig, ax = plt.subplots(figsize=(10, 6))
    
    # 绘制原始数据点
    ax.scatter(x, y, color='blue', label='original data', s=50, alpha=0.7)
    
    # 绘制拟合直线
    ax.plot(x, y_fit, color='red', linewidth=2, label=f'Fitted Line: y = {slope:.4f}x + {intercept:.4f}')
    
    # 设置图表属性
    ax.set_xlabel('q', fontsize=12)
    ax.set_ylabel('n', fontsize=12)
    ax.set_title('Least Squares Linear Fit', fontsize=14)
    ax.legend(fontsize=10)
    ax.grid(True, alpha=0.3)
    
    # 在图上显示参数
    textstr = f'Slope: {slope:.4f}\nIntercept: {intercept:.4f}\nR²: {r_squared:.4f}'
    ax.text(0.05, 0.95, textstr, transform=ax.transAxes, fontsize=10,
            verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
    
    plt.tight_layout()
    
    return slope, intercept, fig



# 实例 
q_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
n_list = [2.1, 4.2, 5.8, 8.1, 9.9, 12.1, 13.8, 16.2, 17.9, 20.1]

# 调用拟合函数
slope, intercept, fig = linear_least_squares(q_list, n_list)

# 打印结果
print(f"直线方程: y = {slope:.4f}x + {intercept:.4f}")
print(f"斜率: {slope:.4f}")
print(f"截距: {intercept:.4f}")

# 显示图像
plt.show()
    

运行结果:
直线方程: y = 1.9952x + 0.0467
斜率: 1.9952
截距: 0.0467
image

posted @ 2025-10-11 10:46  锦书枫回  阅读(4)  评论(0)    收藏  举报