线性回归代码从零开始详解

#创建数据集
import torch
import matplotlib.pyplot as plt
def create(w,b,sample):
    x=torch.normal(0,1,size=(sample,len(w))) #以方差为0,标准差为1的分布,随机生成行为sample,列为len(w)的矩阵
    y=x[:,0]*w[0]+x[:,1]*w[1]+b #生成y
    y+=torch.normal(0,0.01,y.shape) # 加噪声
    return x,y.reshape(-1,1) #(-1,1)代表生成1列,前面的行数-1会根据列数1自动算出来

t_w=torch.tensor([2,-3.4])
t_b=1
features,labels=create(t_w,t_b,100)
features[:,1].shape,labels.shape
#(torch.Size([100]), torch.Size([100, 1]))

看一下生成的数据集

plt.plot(features[:,1],labels[:,0],'r+')#(x,y,表示形状)
plt.show()

在这里插入图片描述
以上根据t_w, t_b生成的类线性数据集,现在我们来拟合一条直线

w = torch.normal(0,0.01,size=(2,1),requires_grad=True)
b = torch.zeros(1,requires_grad=True)
#tensor([[-0.0088],[ 0.0072]], requires_grad=True),
# tensor([0.], requires_grad=True)

随机生成的线性回归模型是y=w.T *x+b,

def linear(x,w,b):
    return torch.matmul(x,w)+b

但是w的较小,近乎是一条横线,可以看一下

plt.plot(features[:,1],labels[:,0],'r+')
xfit=torch.linspace(-5,5,2)
yfit=w[1].detach()*xfit+b.detach()
plt.plot(xfit,yfit,'k-')
plt.show()

在这里插入图片描述
模型出来之后,现在对模型里的损失进行优化,以均方损失为例
下面是损失函数

def loss(y_hat,y):
    return (y_hat-y)**2/2/len(y)#均方损失,整体数据的经验风险

进行优化w,b

def sgd(params,lr):
    with torch.no_grad():#现在不需要BP,所以得把梯度固定住
        for param in params:
            param -= lr*param.grad()#lr是每次前进的步长(学习率)
            param.grad.zero_()#不把梯度清零的话,前后梯度会累加

现在已经定义完成,我们开始遍历这100个样本

lr=0.5
            
for eporch in range(5):
    x,y=features,labels
    y_hat=linear(x,w,b)#构建模型
    l=loss(y_hat,y)#经验风险
    l.sum().backward()#l=loss是张量,必须转化为标量才可以求梯度
    sgd([w,b],lr)#梯度下降
    with torch.no_grad():
        print('eporch:{}, loss={}'.format(eporch+1,loss(y_hat,y).sum()))

在这里插入图片描述
根据此时的[w,b]此时我们再看一下图像
在这里插入图片描述
再增加五次遍历损失结果如下
在这里插入图片描述
此时图像如下
在这里插入图片描述

在样本集过多的情况下 不必对整个数据集进行优化,因为梯度下降比较贵,可以采用小批量随机梯度下降法
整体代码如下

import torch
import matplotlib.pyplot as plt
import numpy as np
import random
def create(w,b,sample):
    x=torch.normal(0,1,size=(sample,len(w)))
    y=x[:,0]*w[0]+x[:,1]*w[1]+b
    y+=torch.normal(0,0.01,y.shape)
    return x,y.reshape(-1,1)

t_w=torch.tensor([2,-3.4])
t_b=1
features,labels=create(t_w,t_b,100)
features[:,1].shape,labels.shape

plt.plot(features[:,1],labels[:,0],'r+')
plt.show()

w = torch.normal(0,0.01,size=(2,1),requires_grad=True)
b = torch.zeros(1,requires_grad=True)
#w,b
plt.plot(features[:,1],labels[:,0],'r+')
xfit=torch.linspace(-5,5,2)
yfit=w[1].detach()*xfit+b.detach()
plt.plot(xfit,yfit,'k-')
plt.show()

def linear(x,w,b):
    return torch.matmul(x,w)+b


def get_batch_size(features,labels,batch_size):
    num=len(labels)
    indice=list(range(num))
    random.shuffle(indice)
    for i in range(0,num,batch_size):
        batch=torch.tensor(indice[i:min(i+batch_size,num)])
        yield features[batch],labels[batch]

def loss(y_hat,y,batch_size):
    return (y_hat-y)**2/2/batch_size


def sgd(params,lr):
    with torch.no_grad():
        for param in params:
            param.data -= lr*param.grad
            param.grad.zero_()

lr=0.5
batch_size=10            
for eporch in range(5):
    for x,y in get_batch_size(features,labels,batch_size):
        y_hat=linear(x,w,b)
        l=loss(y_hat,y,batch_size)
        l.sum().backward()
        sgd([w,b],lr)
    with torch.no_grad():
        print('eporch:{}, loss={}'.format(eporch+1,loss(y_hat,y,batch_size).sum()))

在这里插入图片描述
在这里插入图片描述

建议大家在jupyter运行,可以方便看到曲线的变化

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lins H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值