PyTorch-线性回归-拟合多项式

先自己定义一个多项式公式,比如:
y = 2.70 ∗ x 3 + 3.00 ∗ x 2 + 5.00 ∗ x + 0.90 y = 2.70 * x^3 + 3.00 * x^2 + 5.00 * x + 0.90 y=2.70x3+3.00x2+5.00x+0.90
然后计算出在 x x x 处于区间 [-3, 3] 时,其对应的 y y y 的值:

# 定义多项式参数
w = np.array([2.7, 3, 5])
b = np.array([0.9])

# 生成样本数据
x_sample = np.arange(-3, 3, 0.1)  # 维度: 60x1
y_sample = w[0] * x_sample ** 3 + w[1] * x_sample ** 2 + w[2] * x_sample + b[0]

现在呢,只告诉你 y_sample 的值,然后告诉你 x x x 处于 [-3, 3] 区间,要你给出这个多项式公式:
y = w 1 ∗ x 3 + w 2 ∗ x 2 + w 3 ∗ x + b y = w_1 * x^3 + w_2* x^2 +w_3 * x + b y=w1x3+w2x2+w3x+b
该如何解决呢?
这类线性问题采用 pytorch 中的全连接层就可以了

首先,构造出输入矩阵,也就是输入数据,这个数据格式长这个样子:
[ x 1 3 x 1 2 x 1 x 2 3 x 2 2 x 2 x 3 3 x 3 2 x 3 . . . . . . . . . x 60 3 x 60 2 x 60 ] \begin{bmatrix} x_1^3 & x_1^2 & x_1 \\ x_2^3 & x_2^2 & x_2 & \\ x_3^3 & x_3^2 & x_3 & \\ ... & ... & ... & \\ x_{60}^3 & x_{60}^2 & x_{60} & \\ \end{bmatrix} x13x23x33...x603x12x22x32...x602x1x2x3...x60
代码如下:

# 构建训练数据
x_train = np.array([x_sample ** i for i in [3, 2, 1]]).T  # 对3x60维度的矩阵做矩阵转置,使其变成60x3,每一行对应:  x³、x²、x

然后将 numpy 数据类型转为 pytorch 的张量类型

# 训练数据与目标值
inputs = torch.from_numpy(x_train).float()  # 转换成 float tensor
target = torch.from_numpy(y_sample).float().reshape(-1, 1)  # 将1维数组转换为二维矩阵60x1,使其可与预测值进行相减操作,计算误差

接下来定义线性回归模型:(理解 nn.Linear(3, 1) 的含义比较重要!)

class LinearRegression(nn.Module):
    def __init__(self):
        super(LinearRegression, self).__init__()
        self.linear = nn.Linear(3, 1)  # 每行输入为3个特征值: x³、x²、x  输出为1个特征值: y
        """
        输入矩阵               weight     bias     target
        ------------------------------------------------
        [[x₁³   x₁²  x₁]                            y₁
         [x₂³   x₂²  x₂]      [[w₁]                 y₂
         [x₃³   x₃²  x₃]   x   [w₂]   +  [b]   =    y₃
         ...                   [w₃]]                ..
         [x₆₀³ x₆₀² x₆₀]]                           y₆₀
        ------------------------------------------------
        """

    def forward(self, x):
        output = self.linear(x)
        return output

然后就是实例化模型,定义损失函数和优化函数

# 实例化模型
model = LinearRegression()
# 定义损失函数
criterion = nn.MSELoss()  # 均方误差
# 定义优化函数 (这里不用自己构造权重和偏执参数,pytorch内部会自己构造出参数)
optimizer = optim.SGD(model.parameters(), lr=1e-3)  # SGD:随机梯度下降,lr:学习率

OK,开始训练吧

# 定义超参数 (训练周期)
epochs = 2000

# 开始训练
model.train()
for epoch in range(epochs):
    # 正向传播
    output = model(inputs)  # 输出预测值
    loss = criterion(output, target)  # 计算损失值
    # 反向优化
    loss.backward()
    optimizer.step()  # 更新参数
    optimizer.zero_grad()  # 清零梯度

    if epoch % 100 == 0:
        print('epoch:{}, loss: {:.5f}'.format(epoch, loss))

代码是不是超简单,完了验证一下结果:

# 打印参数
state_dict = model.state_dict()
weight = state_dict['linear.weight']
bias = state_dict['linear.bias']
print(state_dict)

# 比较公式
print('real:', fx.format(w[0], w[1], w[2], b[0]))
print('pred:', fx.format(weight[0][0], weight[0][1], weight[0][2], bias[0]))

每次训练结果都是不同的,这是我本地的一次结果:

real: y = 2.70 * x^3 + 3.00 * x^2 + 5.00 * x + 0.90
pred: y = 2.80 * x^3 + 3.02 * x^2 + 4.34 * x + 0.81

emmm,我做了个GIF动图来展示这个拟合过程:

完整代码:

# -*- coding: utf-8 -*-
import torch
from torch import nn, optim
import numpy as np
import matplotlib.pyplot as plt

# 定义多项式参数
w = np.array([2.7, 3, 5])
b = np.array([0.9])

# 多项式公式,模型将尽量拟合这个公式
fx = 'y = {:.2f} * x^3 + {:.2f} * x^2 + {:.2f} * x + {:.2f}'

# 生成样本数据
x_sample = np.arange(-3, 3, 0.1)  # 维度: 60x1
y_sample = w[0] * x_sample ** 3 + w[1] * x_sample ** 2 + w[2] * x_sample + b[0]

# 构建训练数据
x_train = np.array([x_sample ** i for i in [3, 2, 1]]).T  # 对3x60维度的矩阵做矩阵转置,使其变成60x3,每一行对应:  x³、x²、x

# 训练数据与目标值
inputs = torch.from_numpy(x_train).float()  # 转换成 float tensor
target = torch.from_numpy(y_sample).float().reshape(-1, 1)  # 将1维数组转换为二维矩阵60x1,使其可与预测值进行相减操作,计算误差


class LinearRegression(nn.Module):
    def __init__(self):
        super(LinearRegression, self).__init__()
        self.linear = nn.Linear(3, 1)  # 每行输入为3个特征值: x³、x²、x  输出为1个特征值: y
        """
        输入矩阵               weight     bias     target
        ------------------------------------------------
        [[x₁³   x₁²  x₁]                            y₁
         [x₂³   x₂²  x₂]      [[w₁]                 y₂
         [x₃³   x₃²  x₃]   x   [w₂]   +  [b]   =    y₃
         ...                   [w₃]]                ..
         [x₆₀³ x₆₀² x₆₀]]                           y₆₀
        ------------------------------------------------
         
        model.parameters 是一个迭代器,可以对其进行循环,打印出里面的 weight 和 bias
        但是很纳闷,打印出来的 wieght 的维度是(1, 3),估计内部计算时对其做了矩阵转置吧
        """

    def forward(self, x):
        output = self.linear(x)
        return output


# 实例化模型
model = LinearRegression()

# 定义损失函数
criterion = nn.MSELoss()  # 均方误差
# 定义优化函数 (这里不用自己构造权重和偏执参数,pytorch内部会自己构造出参数)
optimizer = optim.SGD(model.parameters(), lr=1e-3)  # SGD:随机梯度下降,lr:学习率

# 训练前的拟合图
output = model(inputs)
plt.plot(x_train[:, -1], y_sample, label='real curve')
plt.plot(x_train[:, -1], output.data.numpy(), label='fitting curve', color='r')
plt.legend(loc='best')
plt.show()

# 定义超参数 (训练周期)
epochs = 2000

# 开始训练
model.train()
for epoch in range(epochs):
    # 正向传播
    output = model(inputs)  # 输出预测值
    loss = criterion(output, target)  # 计算损失值
    # 反向优化
    loss.backward()
    optimizer.step()  # 更新参数
    optimizer.zero_grad()  # 清零梯度

    if epoch % 100 == 0:
        print('epoch:{}, loss: {:.5f}'.format(epoch, loss))

# 训练后的拟合图
model.eval()
output = model(inputs)
plt.plot(x_train[:, -1], y_sample, label='real curve')
plt.plot(x_train[:, -1], output.data.numpy(), label='fitting curve', color='r')
plt.legend(loc='best')
plt.show()

# 保存模型
torch.save(model.state_dict(), 'linear02.pth')

# 打印参数
state_dict = model.state_dict()
weight = state_dict['linear.weight']
bias = state_dict['linear.bias']
print(state_dict)

# 比较公式
print('real:', fx.format(w[0], w[1], w[2], b[0]))
print('pred:', fx.format(weight[0][0], weight[0][1], weight[0][2], bias[0]))
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值