从零实现线性回归(pytorch)(3)

获取噪声散点图

def synthetic_data(w,b,num_examples):     #输入w,b, 返回带噪声的y=xw+b,num_examples为返回坐标的点数
    """
        生成y=Xw+b的噪声
    """
    X=torch.normal(0,1,(num_examples,len(w)))   #生产高斯噪声(num_examples,len(w))为噪声的维度这里是输入w是维度2向量,len为2
    print("X.shape:", X.shape)         # 所以维度等于[num_examples,2]
    y=torch.matmul(X,w)+b               #[1000 2]* [2]    w是维度[2]向量  得到y是维度1000向量
    y+=torch.normal(0,0.01,y.shape)             #获取y=xw+b后再加上等于y自身维度的高斯噪声 均值0 标准差0.01
    print("y.shape", y.shape)
    return  X, y.reshape((-1,1))  #将y重塑成(1000,1)并返回


#*************调用synthetic_data获取带噪声的散点图**************/
    true_w = torch.tensor([2, -3.4])
    print(true_w.shape)
    true_b = 4.2
    features, labels = synthetic_data(true_w, true_b, 1000)
    # print('features:',features,'\nlabel:',labels)
    print('features:', features[0, 1], '\nlabel:', labels[0])
    d2l.set_figsize()
    d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1);  # 绘制散点图
    # features[:, 1].detach().numpy()  横坐标,detach()将features分离出计算图,numpy转换numpy数组,1:散点大小
    d2l.plt.show()  # 显示图片

设计迭代器

#迭代器:接收批量大小、特征矩阵和标签向量,生成大小为batchsize的小批量数据
def data_iter(batch_size,features,labels):
    num_examples =len(features)     #获取特征矩阵元素数量
    indices =list(range(num_examples)) #生成从0-num_examples-1的列表
    # print("indices type",type(indices))
    # print("indices len", len(indices))
    random.shuffle(indices)#打乱列表顺序

    for i in range(0,num_examples, batch_size):  #以batch_size为步长,从零遍历到num_examples
        #print("i:", i)
        batch_indices =torch.tensor(indices[i:min(i+batch_size,num_examples)])  #每一次遍历从i开始取batch_size个索引,min函数保证索引不超过最大值
        yield  features[batch_indices], labels[batch_indices]
        #yield的生成迭代器办法可以帮助节省内存
        #yield是一个定义生成器的关键字,生成器是一种特殊的函数,逐个产生一系列的值并返回
        #而函数会保留当前转态,下次调用迭代器时,又会从当前yield处开始运行,返回下一批新的batch个数据
        # 使用迭代器的办法用for循环
        # for x,y in data_iter(batch_size,features,labels)  就会迭代循环调用这个迭代器直到迭代运行结束
#*************迭代器使用**************/
batch_size =10
for X,y in data_iter(batch_size,features,labels):
    print('x:',X,'\n','y:',y)
    break#只迭代运行一次迭代器就退出

训练

def linreg(X,w,b):
    """线性回归模型"""
    return  torch.matmul(X,w)+b

def squared_loss(y_hat,y):

    return  (y_hat-y.reshape(y_hat.shape))**2/2  #均方损失, /2只是为了压缩


def sgd(params, lr,batch_size):
    """小批量随机梯度下降"""
    with torch.no_grad(): #表示解下进行操作,不会自动取计算梯度信息
        for param in params: #params是模型参数的集合,每个参数的对应的点都有对应的梯度信息,迭代每个参数更新梯度信息
                param -= lr*param.grad/batch_size  #之前是多个batch进行计算求梯度,梯度信息是累计的
                                                    #所以更新梯度时要取平均
                param.grad.zero_()  #每次进行梯度下降后,清除当前参数的梯度信息    

#*************初始化模型参数**************/
    w = torch.normal(0, 0.01, size=(2,1),requires_grad=True)#用高斯分布初始化w,shape为[2,1]
    b = torch.zeros (1,requires_grad=True)

    # *************训练**************/
    lr =0.03 #学习率
    num_epochs =3
    net =linreg #获取线性模型网络
    loss = squared_loss

    for epoch in range (num_epochs):
        for X,y in data_iter(batch_size,features ,labels):
            l=loss(net(X,w,b),y) #计算网络输出和实际y的损失

            l.sum().backward()  #更新梯度
            sgd([w,b],lr,batch_size) #计算梯度信息后将网络参数、学习率、batchsize输入sgd 进行随机梯度下降

        with torch.no_grad():
            train_l= loss(net(features,w,b),labels)  #计算所有数据的均方损失
            print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

    print("w:",w)
    print("b:",b)
    print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
    print(f'b的估计误差: {true_b - b}')
    #打印出输出发现求得的w,b与用于生成数据集的真实的true_w true_b非常接近
    #    true_w = torch.tensor([2, -3.4])
    #         print(true_w.shape)
    #            true_b = 4.2

完整代码(复制就能跑)

import random
import torch
from d2l import torch as d2l
#获取带噪声散点图
def synthetic_data(w,b,num_examples):     #输入w,b, 返回带噪声的y=xw+b,num_examples为返回坐标的点数
    """
        生成y=Xw+b的噪声
    """
    X=torch.normal(0,1,(num_examples,len(w)))   #生产高斯噪声(num_examples,len(w))为噪声的维度这里是输入w是维度2向量,len为2
    print("X.shape:", X.shape)         # 所以维度等于[num_examples,2]
    y=torch.matmul(X,w)+b               #[1000 2]* [2]    w是维度[2]向量  得到y是维度1000向量
    y+=torch.normal(0,0.01,y.shape)             #获取y=xw+b后再加上等于y自身维度的高斯噪声 均值0 标准差0.01
    print("y.shape", y.shape)
    return  X, y.reshape((-1,1))  #将y重塑成(1000,1)并返回


#迭代器:接收批量大小、特征矩阵和标签向量,生成大小为batchsize的小批量数据
def data_iter(batch_size,features,labels):
    num_examples =len(features)     #获取特征矩阵元素数量
    indices =list(range(num_examples)) #生成从0-num_examples-1的列表
    # print("indices type",type(indices))
    # print("indices len", len(indices))
    random.shuffle(indices)#打乱列表顺序

    for i in range(0,num_examples, batch_size):  #以batch_size为步长,从零遍历到num_examples
        #print("i:", i)
        batch_indices =torch.tensor(indices[i:min(i+batch_size,num_examples)])  #每一次遍历从i开始取batch_size个索引,min函数保证索引不超过最大值
        yield  features[batch_indices], labels[batch_indices]
        #yield的生成迭代器办法可以帮助节省内存
        #yield是一个定义生成器的关键字,生成器是一种特殊的函数,逐个产生一系列的值并返回
        #而函数会保留当前转态,下次调用迭代器时,又会从当前yield处开始运行,返回下一批新的batch个数据
        # 使用迭代器的办法用for循环
        # for x,y in data_iter(batch_size,features,labels)  就会迭代循环调用这个迭代器直到迭代运行结束

def linreg(X,w,b):
    """线性回归模型"""
    return  torch.matmul(X,w)+b

def squared_loss(y_hat,y):

    return  (y_hat-y.reshape(y_hat.shape))**2/2  #均方损失, /2只是为了压缩


def sgd(params, lr,batch_size):
    """小批量随机梯度下降"""
    with torch.no_grad(): #表示解下进行操作,不会自动取计算梯度信息
        for param in params: #params是模型参数的集合,每个参数的对应的点都有对应的梯度信息,迭代每个参数更新梯度信息
                param -= lr*param.grad/batch_size  #之前是多个batch进行计算求梯度,梯度信息是累计的
                                                    #所以更新梯度时要取平均
                param.grad.zero_()  #每次进行梯度下降后,清除当前参数的梯度信息

if __name__== "__main__":
    #*************调用synthetic_data获取带噪声的散点图**************/
    true_w = torch.tensor([2, -3.4])
    print(true_w.shape)
    true_b = 4.2
    features, labels = synthetic_data(true_w, true_b, 1000)
    # print('features:',features,'\nlabel:',labels)
    print('features:', features[0, 1], '\nlabel:', labels[0])
    d2l.set_figsize()
    d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1);  # 绘制散点图
    # features[:, 1].detach().numpy()  横坐标,detach()将features分离出计算图,numpy转换numpy数组,1:散点大小
    d2l.plt.show()  # 显示图片
    #*************迭代器使用**************/
    batch_size =10
    for X,y in data_iter(batch_size,features,labels):
        print('x:',X,'\n','y:',y)
        break#只迭代运行一次迭代器就退出

    #*************初始化模型参数**************/
    w = torch.normal(0, 0.01, size=(2,1),requires_grad=True)#用高斯分布初始化w,shape为[2,1]
    b = torch.zeros (1,requires_grad=True)

    # *************训练**************/
    lr =0.03 #学习率
    num_epochs =3
    net =linreg #获取线性模型网络
    loss = squared_loss

    for epoch in range (num_epochs):
        for X,y in data_iter(batch_size,features ,labels):
            l=loss(net(X,w,b),y) #计算网络输出和实际y的损失

            l.sum().backward()  #更新梯度
            sgd([w,b],lr,batch_size) #计算梯度信息后将网络参数、学习率、batchsize输入sgd 进行随机梯度下降

        with torch.no_grad():
            train_l= loss(net(features,w,b),labels)  #计算所有数据的均方损失
            print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

    print("w:",w)
    print("b:",b)
    print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
    print(f'b的估计误差: {true_b - b}')
    #打印出输出发现求得的w,b与用于生成数据集的真实的true_w true_b非常接近
    #    true_w = torch.tensor([2, -3.4])
    #         print(true_w.shape)
    #            true_b = 4.2


























  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值