Pytorch实现线性回归

一维线性回归:

个人理解就是拟合直线。拟合出一条尽量符合(穿过)最多数据(点)分布的直线。

直线的公式表达是:

f(x)=ax+b

f(x)是拟合的直线的值,实际值是y。现在的目的是要f(x)尽可能地接近y。而一般使用点到直线(拟合的直线)的距离差异来衡量接近程度。即均方误差。

公式比较复杂我就不输入了。

基于均方误差最小化来进行模型求解的方法也称为“最小二乘法”。

我们将均方误差表示成一个函数。可以得到一个关于a,b的二元函数。

Loss(a,b)=\sum_{i=1}^{m}(f(xi)-yi)^{2}

而对于一个一元函数,我们知道极值是在它导数为0处取得。而对于一个多元函数,极值是在其各偏导都为0处取得。

因此通过对损失函数求偏导找到极(小)值即可得到最优参数。

多维线性回归:

大概原理同一纬相同,同样是使用最小二乘法进行估计参数。

一维线性回归代码实现:

通过pytorch实现一维线性回归。首先随机生成一堆点,通过matplotlib画出来;

# 创建随机数据
x_train = np.random.randn(10)+15 # 生成100个在15附近的数
y_train = np.random.randn(10)+10 # 生成100个在10附近的数

fig = plt.figure(figsize = (10, 10),facecolor='white')
plt.scatter(x_train,y_train) # 散点图
plt.grid() # 绘制数据分布图
plt.savefig("savefig_example_1.png")
plt.show()

随机点图:

将numpy.array转换成Tensor;

# 调整输入数据的形状: 在创建 torch 张量时,使用 unsqueeze 方法将其变为二维张量
x_train = torch.from_numpy(x_train).float().unsqueeze(1)
y_train = torch.from_numpy(y_train).float().unsqueeze(1)

建立模型;

# 构建线性模型
class LinearRegression(nn.Module):
    def __init__(self):
        super(LinearRegression,self).__init__()
        self.linear=nn.Linear(1,1) # 输入和输出都是一维的
    def forward(self,x):
        out = self.linear(x)
        return out

device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
model=LinearRegression().to(device)

定义损失函数和优化函数;

# 定义损失函数和优化器
criterion=nn.MSELoss()
optimizer=optim.SGD(model.parameters(),1e-3)

训练模型,训练好后预测结果并绘图;

# 训练模型。
Epoch=10000
for eopch in range(Epoch):
    if torch.cuda.is_available():
        inputs=Variable(x_train).cuda()
        target=Variable(y_train).cuda()
    else:
        inputs=Variable(x_train)
        target=Variable(y_train)

    # 前向传播
    inputs=inputs.float()
    out=model(inputs)
    loss=criterion(out,target)
    # 反向传播
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    # 每隔20次就打印出损失函数的值
    if eopch%20==0:
        print(loss.item())

# 将模型变成测试模式
model.eval()
model.cpu()
predict=model(Variable(x_train))
predict=predict.data.numpy()
fig = plt.figure(figsize = (10, 10),facecolor='white')
plt.plot(x_train.numpy(),y_train.numpy(),'ro',label="Original data")
plt.plot(x_train.numpy(),predict,label="Fitting Line")
plt.savefig("savefig_example_2.png")
plt.show()

回归结果图:

多维线性回归代码实现:

大致流程与一维回归相似,只是需要拟合的函数表达式变成了高次多项式,不是简答的直线方程(一元一次函数)。代码如下:

import matplotlib.pyplot as plt
import torch.nn as nn
import torch
import torch.optim as optim
from torch.autograd import Variable

# 待拟合的方程:y=0.9+0.5*x+3*x^2+2.4*x^3
# 参数方程:y=b+w1*x+w2*x^+w3*x^3

def make_features(x):
    x=x.unsqueeze(1)
    return torch.cat([x ** i for i in range(1,4)],1) # 生成 [x, x², x³]

# 需要拟合的目标参数
w_target=torch.FloatTensor([0.5,3,2.4]).unsqueeze(1)
b_target=torch.FloatTensor([0.9])

def f(x):
    return x.mm(w_target)+b_target[0] # 与生成的[x, x², x³]相乘得到所需要的真实函数表达式


# 每次取batch_size个数据点,将它们转换为矩阵的形式
def get_batch(batch_size=32):
    random=torch.randn(batch_size)
    print(random)
    x=make_features(random)
    y=f(x)
    if torch.cuda.is_available():
        inputs=Variable(x).cuda()
        target=Variable(y).cuda()
        return inputs,target
    else:
        inputs=Variable(x)
        target=Variable(y)
        return inputs, target

# 模型
class poly_model(nn.Module):
    def __init__(self):
        super(poly_model,self).__init__()
        self.poly=nn.Linear(3,1) # 模型的输入是3维,输出是1维

    def forward(self,x):
        out = self.poly(x)
        return out

if torch.cuda.is_available():
    model=poly_model().cuda()
else:
    model=poly_model()

# 三件套
criterion=nn.MSELoss()
optimizer=optim.SGD(model.parameters(),1e-3)

# 模型训练
epoch=0
while True:
    # 获取数据
    batch_x,batch_y=get_batch()
    output=model(batch_x)
    loss=criterion(output,batch_y)
    print_loss=loss.item()
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    epoch+=1
    if epoch%20==0:
        print(print_loss)
    #直到均方误差小于预设值时退出训练
    if print_loss<1e-3:
        break


# 绘制真实函数和拟合的多项式

# 生成一组固定的x值
x_plot = torch.linspace(-3, 3, 100)
x_features = make_features(x_plot)

if torch.cuda.is_available():
    x_features = x_features.cuda()

model.eval()  # 设置模型为评估模式
with torch.no_grad():
    y_pred = model(x_features).cpu().numpy()

# 计算真实的y值
y_true = f(x_features.cpu()).numpy()
# 转换x值为numpy
x_plot = x_plot.cpu().numpy()

# 绘图
plt.figure(figsize=(10, 6))
plt.scatter(x_plot, y_true, label='real curve', color='blue', alpha=0.5)
plt.plot(x_plot, y_pred, label='fitting curve', color='red')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid(True)
plt.show()

回归结果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值