线性回归的从零开始实现

参考: 李沐老师

代码如下

import random
import torch
from d2l import torch as d2l
def data(w,b,num_exam):
    #从(0,1)标准正态分布中找num_exam个列数是w的样本,s
    x = torch.normal(0,1,(num_exam,len(w)))
    #y=x×w后+偏差b
    y = torch.matmul(x,w)+b
    #往公式y中加入随机噪音, 均值为0, 方差为0.01, 形状与y一样
    y+=torch.normal(0,0.01,y.shape)
    # 将x与y做成列向量后返回, reshape中-1表示自动计算行,1代表为1列
    return x,y.reshape((-1,1))
def data_lter(batch_size,features,labels):
    # num_examples代表取x的第一列的个数
    num_examples = len(features)
    #indices代表以x的数目形成的数列
    indices = list(range(num_examples))
    #这些样本是随机读取的, 没有特定的顺序
    random.shuffle(indices)
    #打乱数列indices的数据
    for i in range(0,num_examples,batch_size):
        batch_indices = torch.tensor(indices[i:min(i+batch_size,num_examples)])
        #从indices中选取不定长的数据,最长为indices的长度
        yield features[batch_indices],labels[batch_indices]
        #从x和y中随机选取值输出
def linreg(x,w,b):
    #执行矩阵乘法, 返回的是预测
    return torch.matmul(x,w)+b
#定义损失函数
def squared_loss(y_hat,y):
    #均方损失
    #将y定义为与y_hat同行同列
    return ((y_hat-y.reshape(y_hat.shape))**2)/2
#定义优化算法
#params代表参数, lr代表学习率
def sgd(params,lr,batch_size):
    with torch.no_grad():#不采用梯度计算
        for param in params:
            #/batch_size代表求均值, w与b在减去各自的梯度后乘lr再除batch_size, 将结果见赋到新的w, b
            param-=lr*param.grad/batch_size
            #将梯度设为0
            param.grad.zero_()
#y=wx+b相当于向量之间做点积后再相加
true_w = torch.tensor([2,-3.4])
true_b=4.2
teatures,labels = data(true_w,true_b,1000)#随机取出一定长度的数据
lr = 0.01
batch_size=10
num_epochs =3#代表将数据扫3遍
net = linreg#net代表一个模型, 此时net代表y=wx+b
loss = squared_loss
#选取2个期望为0, 方差为0.01, 个数为2, 列数为1的样本, requires_grad代表需要计算梯度
w = torch.normal(0,0.01,(2,1),requires_grad=True)
#zeros创建1行1列的向量
b = torch.zeros((1),requires_grad=True)
for epoch in range(num_epochs):
    #从结果中随机取出一定数据赋于x,y
    for x,y in data_lter(batch_size,teatures,labels):
        l=loss(net(x,w,b),y)#计算损失函数, 最终目的是求w与b, 此时先随机定义一个w与b
        l.sum().backward()#将损失函数求和后算梯度
        sgd([w,b],lr,batch_size)
    with torch.no_grad():
        train_1 = loss(net(teatures,w,b),labels)
        print("epoch",epoch+1,",","loss",float(train_1.mean()))
print("w的误差",true_w-w.reshape(true_w.shape))

运行结果如下

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值