Python多项式拟合详解与实践

文章目录

  • Python 多项式拟合
  • 一、Numpy 实现
  • 二、Torch 实现
  • 三、拟合程度
  • 3.1 展示
  • 3.2 过拟合
  • 3.3 欠拟合
  • Python 多项式拟合

    一、Numpy 实现

    多项式拟合原理:Python最小二乘法

    这里使用第三方库来实现多项式拟合,而不是使用原始的方法:

    numpy 库实现:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 生成原始数据
    # 生成 20 个在 [0, 1) 之间的随机数作为输入特征
    x = np.sort(np.random.rand(100))
    # 根据正弦函数生成对应的目标值,并添加噪声
    y = np.sin(2 * np.pi * x) + 0.3 * np.random.randn(100)
    
    p_is1 = np.poly1d(np.polyfit(x, y, 3))  # 拟合曲线
    
    x_plot = np.linspace(0, 1, 100) 
    
    plt.scatter(x, y, label='Training data', color='blue')
    plt.plot(x_plot, p_is1(x_plot), label="predict data")
    plt.title('fitting curve')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    

    1739436806_zfayb8n4k7.png1739436805904.png

    二、Torch 实现

    1739448558_dkfblgxycn.png1739448557822.png

    import torch
    import torch.nn as nn
    from torch.utils.data import TensorDataset, DataLoader
    
    # 1. 准备数据
    # 生成一些示例数据
    n_samples = 100
    x1 = torch.randn(n_samples, 1)
    x2 = torch.randn(n_samples, 1)
    # 真实的权重和偏置
    true_w1 = 2.0
    true_w2 = 3.0
    true_b = 1.0
    # 生成标签
    y = true_w1 * x1 + true_w2 * x2 + true_b + 0.1 * torch.randn(n_samples, 1)
    
    # 合并特征
    X = torch.cat((x1, x2), dim=1)
    
    # 创建数据集和数据加载器
    dataset = TensorDataset(X, y)
    batch_size = 10
    dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
    
    # 2. 定义模型
    class LinearRegression(nn.Module):
        def __init__(self):
            super(LinearRegression, self).__init__()
            self.linear = nn.Linear(2, 1)  # 输入维度为 2,输出维度为 1
    
        def forward(self, x):
            return self.linear(x)
    
    model = LinearRegression()
    
    # 3. 定义损失函数和优化器
    criterion = nn.MSELoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
    
    # 4. 训练模型
    num_epochs = 100
    for epoch in range(num_epochs):
        for inputs, labels in dataloader:
            # 前向传播
            outputs = model(inputs)
            loss = criterion(outputs, labels)
    
            # 反向传播和优化
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
    
        if (epoch + 1) % 10 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
    
    # 输出最终的权重和偏置
    print("Final weights:", model.linear.weight.tolist())
    print("Final bias:", model.linear.bias.item())
    

    1739449817_swgyxklg7f.png1739449816827.png

    三、拟合程度

    3.1 展示

    代码:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 生成原始数据
    # 生成 20 个在 [0, 1) 之间的随机数作为输入特征
    x = np.sort(np.random.rand(100))
    # 根据正弦函数生成对应的目标值,并添加噪声
    y = np.sin(2 * np.pi * x) + 0.3 * np.random.randn(100)
    
    p_over = np.poly1d(np.polyfit(x, y, 15))  # 过饱和曲线
    p_under = np.poly1d(np.polyfit(x, y, 1))  # 过饱和曲线
    p_is1 = np.poly1d(np.polyfit(x, y, 3))  # 拟合曲线
    p_is2 = np.poly1d(np.polyfit(x, y, 4))  # 拟合曲线
    
    
    # 绘制结果`
    plt.figure(figsize=(12, 6))
    
    x_plot = np.linspace(0, 1, 100) 
    
    # 绘制训练集数据和拟合曲线
    plt.subplot(2, 2, 1)
    plt.scatter(x, y, label='Training data', color='blue')
    plt.plot(x_plot, p_over(x_plot), label="predict data")
    plt.title('1. Supersaturation fitting curve')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    
    # 绘制测试集数据和拟合曲线
    plt.subplot(2, 2, 2)
    plt.scatter(x, y, label='Training data', color='green')
    plt.plot(x_plot, p_under(x_plot), label="predict data")
    plt.title('2. Undersaturated fitting curve')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    
    # 绘制测试集数据和拟合曲线
    plt.subplot(2, 2, 3)
    plt.scatter(x, y, label='Training data', color='green')
    plt.plot(x_plot, p_is1(x_plot), label="predict data")
    plt.title('3. Three order fitting curve')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    
    # 绘制测试集数据和拟合曲线
    plt.subplot(2, 2, 4)
    plt.scatter(x, y, label='Training data', color='green')
    plt.plot(x_plot, p_is2(x_plot), label="predict data")
    plt.title('4. Four order fitting curve')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    
    plt.tight_layout()
    plt.show()
    

    1738978302_438sjyc25r.png1738978301378.png

    1. 图一为过拟合图像
    2. 图二为欠拟合图像

    3.2 过拟合

    过拟合是指模型在训练数据上表现得非常好,能够很好地拟合训练数据中的模式和细节,但在新的、未见过的数据(测试数据)上表现却很差,泛化能力弱的现象。简单来说,就是模型过度学习了训练数据中的噪声和特殊情况,而没有真正捕捉到数据背后的一般规律,从而导致在面对新数据时无法准确预测或分类。

    解决方法:

  • 增加训练数据:获取更多的数据进行训练,使模型能够学习到更多的样本特征,减少对训练数据中噪声和特殊情况的依赖,提高模型的泛化能力。
  • 降低模型复杂度:可以采用简化模型结构的方法,如减少神经网络的层数或神经元数量、限制决策树的深度等。也可以使用正则化方法,如 L1 和 L2 正则化,通过在损失函数中添加惩罚项来限制模型参数的大小,防止模型过度拟合。
  • 采用早停法:在训练过程中,监控模型在验证集上的性能,当验证集上的性能不再提升甚至开始下降时,停止训练,避免模型过度拟合训练数据。
  • 使用集成学习:将多个不同的模型进行组合,如随机森林、梯度提升树等集成算法,通过综合多个模型的预测结果来降低过拟合的风险,提高模型的稳定性和泛化能力。
  • 3.3 欠拟合

    欠拟合是指模型在训练数据和新数据上的表现都很差,无法很好地捕捉数据中的规律,导致模型的预测能力和泛化能力都不足。简单来说,就是模型还没有充分学习到数据中的特征和关系,对数据的拟合程度过低,不能很好地对数据进行建模和预测。

    解决方法:

  • 增加模型复杂度:选择更复杂的模型结构,如使用多层神经网络代替单层神经网络,增加决策树的深度或节点数量等,以提高模型的表达能力,使其能够更好地拟合数据中的复杂关系。
  • 特征工程:对数据进行更深入的特征提取和选择,挖掘更多有价值的特征,或者对现有特征进行组合、变换等操作,让模型有更多的信息可以学习。例如对文本数据进行词向量表示、对图像数据提取更多的特征描述子等。
  • 提高数据质量:对训练数据进行清洗,去除噪声和异常值,对缺失值进行处理,确保数据的准确性和完整性,为模型提供更好的学习样本。
  • 增加训练时间和数据量:适当延长模型的训练时间,让模型有足够的时间进行学习和收敛。同时,增加训练数据的数量,使模型能够学习到更多的数据特征和规律,提高模型的泛化能力。
  • 作者:码海探幽

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python多项式拟合详解与实践

    发表回复