08 线性回归 + 基础优化算法【动手学深度学习v2】

‘torch.Size‘ object is not callable

正确写法:return X,y.reshape(-1,1) #把x和y做成一个列向量返回

错误写法:return X,y.shape(-1,1) #把x和y做成一个列向量返回

把reshape写成shape报错

导入模块:

import matplotlib.pyplot as plt
import random
import torch
from d2l import torch as d2l

生成数据集

def synthetic_data(w,b,num_examples): #生成y=wx+b+噪声(num_examples)
    X = torch.normal(0,1,(num_examples,len(w))) #x是均值为0,方差为1的随机数 num_examples是说有n的样本,列数就是w的长度(len)
    y = torch.matmul(X,w) + b #y是 wx+b
    print('y shape is',y.shape)
    y += torch.normal(0,0.01,y.shape) #加入均值为0,方差为0.01的噪音,他的形状和y的长度相同

    return X,y.reshape(-1,1) #把x和y做成一个列向量返回

#定义真实的w和b
true_w = torch.tensor([2,-3.4])
true_b = 4.2

#features中每一行都包含一个二维数据样本,labels中的每一行都包含一维标签值(一个标量)
features,labels = synthetic_data(true_w,true_b,1000) #通过synethetic_data这个函数生成我们的特征和标注 feature和label
print('features',features[0],'\nlabel:',labels[0]) #打印第0个样本 features tensor([-0.8934,  1.3054])长为2的向量  标号label: tensor([-2.0286])是一个标量
# d2l.plt.show(features[:,1].detach().numpy,labels.detach().numpy(),1); 画图画不出,直接跳过看视频
定义一个data_iter函数,这个函数接收批量大小batch size,特征矩阵和标签向量作为输入,生成大小为batch_size的小批量

def data_iter(batch_size,features,labels): #创建data inter函数的目的是从所有数据中抽取部分样本,用来训练后面创建的模型
    num_examples = len(features)
    indices = list(range(num_examples)) 
  #生成对每个样本的index,转化成python的list / 生成0-999的元组,然后将range()返回的可迭代对象转为一个列表
    random.shuffle(indices) 
  #把上一行定义的下标indices完全打乱,这样以后可以用随机的顺序访问每个样本
    for i in range(0,num_examples,batch_size): 
  #对于每一次从0开始,到最后num_examples,挑batch size的大小
        batch_indices = torch.tensor(indices[i:min(i + batch_size, num_examples)]) 
  #先把batch的index找出来,从i开始,到i+batch size
  #最后一个批量可能没有那么多,所以取一个最小值min(i + batch_size, num_examples),但是这个没有影响
        yield features[batch_indices],labels[batch_indices] #产生了随机顺序的特征和随机顺序的标号
  #yield是python中return返回的一个值,并且记住这个值返回的位置,下次迭代就从这个位置以后开始

batch_size = 10

for X,y in data_iter(batch_size,features,labels):
    print(X,'\n',y) #X是10*2的tensor,y是10*1的向量
    break
定义初始化模型参数
w = torch.normal(0,0.01,size = (2,1),requires_grad=True) #w是长为2的向量,把他随机初始化成均值为0,方差为0.01的正态分布,还需要计算梯度,所有requirs_grad是True
b = torch.zeros(1,requires_grad=True) #对bias来说直接点名是一个标量,同样他更新需要requires grad = True

定义模型

#定义模型
def linreg(X,w,b): #定义线性回归模型
    return torch.matmul(X,w) + b #矩阵*向量 + bias

#定义损失函数loss function
def squared_loss(y_hat,y): #使用的均方误差 Root mean square error (RMSE) p39
    return(y_hat - y.reshape(y_hat.shape)) **2 / 2 #y hat是预测值,y是真值,为了统一,让y变成yhat的样子,这里没有做均值也没有求和,就是 1/2(y_hat -y)^2

#定义优化算法
def sgd(params,lr,batch_size): #sgd小批量随机梯度下降,输入是所有params,是一个list,里面包含了w和b;lr是给定的学习率learning rate,给定了batch size
    with torch.no_grad(): #更新的时候不参与梯度计算
        for param in params:  #对每一个参数,都减去learning rate * 梯度,因为之前的损失函数loss function没有求均值,在这里除以batch size求均值
            param -= lr * param.grad / batch_size
            param.grad.zero_() #完成一次计算以后梯度归零
把所有模块都准备好以后,开始训练过程
lr = 10 #learning rate
num_epochs = 10 #把整个数据扫3遍
net = linreg #模型的类型是线性,以后可以换成不一样的模型,比如非线性模型
loss = squared_loss #RMSE

for epoch in range(num_epochs): #第一层for循环,所有数据都扫一遍
    for X,y in data_iter(batch_size,features,labels): #每一次都拿出一个批量大小的X和y
        l = loss(net(X,w,b),y) #把X,w和b放进模型里做预测,把预测的y和真实的y做loss损失,这样的话loss(l)就是长为batch size大小的向量
        # 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,
        # 并以此计算关于[w,b]的梯度
        l.sum().backward() #对l求和以后算梯度
        sgd([w,b],lr,batch_size) #用梯度sgd对w和b进行更新
    with torch.no_grad():#这里开始总结进度,不需要再做梯度,所以no grad
        train_l = loss(net(features,w,b),labels) #计算他的预测,和真实的label做一下损失,存到train_l这个函数里,最后print
        print(f'epoch{epoch+1},loss{float(train_l.mean()):f}')
'''
打印结果:
epoch1,loss0.037733
epoch2,loss0.000137
epoch3,loss0.000052
每一次都越来越小了
'''
#查看电脑学习的y和真值的区别
print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}') #真实的w-预测的w
print(f'b的估计误差: {true_b - b}')
可以实践不同的超参数会得到什么样的结果
当lr = 0.0001时,得到的误差很大,哪怕跑了3个epoch,都是很大的
epoch1,loss17.630207
epoch2,loss17.251877
epoch3,loss16.881668
w的估计误差: tensor([ 1.9487, -3.2860], grad_fn=<SubBackward0>)
b的估计误差: tensor([4.0664], grad_fn=<RsubBackward1>)
哪怕跑了10个epoch,误差也还是很大
epoch7,loss14.790643
epoch8,loss14.488152
epoch9,loss14.191863
epoch10,loss13.901650
w的估计误差: tensor([ 1.8247, -3.0320], grad_fn=<SubBackward0>)
b的估计误差: tensor([3.8022], grad_fn=<RsubBackward1>)

当learning rate = 10 实在太大了,超过了计算机可以运算的范围,出现nan
epoch1,lossnan
epoch2,lossnan
epoch3,lossnan

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值