Pytorch从0到1之线性回归——(2)

开篇

Linear Regression是很基础的一个模型,用pytorch实现也不是什么难事,主要用到的还是我们上次说到的Linear这个模块来进行线性构建。这次我们会随机生成一些数据,利用pytorch构建线性模型进行拟合,最后画图表示出来。我们开始吧。
库的引入

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt

这次我们引入matplotlib这个库进行画图直观表示,大家应该很熟悉了
超参数的定义

input_size = 1 //输入数据尺寸
output_size = 1//输出数据尺寸
num_epochs = 60//训练轮数
learning_rate = 0.001//学习率

自定义一个数据

x_train = np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],
                    [9.779],[6.182],[7.59],[2.167],[7.042],
                    [10.791], [5.313], [7.997], [3.1]],dtype=np.float32)
y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],
                    [3.366], [2.596], [2.53], [1.221], [2.827],
                    [3.465], [1.65], [2.904], [1.3]], dtype=np.float32)

x_train与y_train分别表示训练数据的输入与输出。
构建线性模型,函数损失函数以及优化器

model = nn.Linear(input_size,output_size)
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate)

训练模型

for epoch in range(num_epochs):
    # 将numpy数据转化成tensor
    inputs = torch.from_numpy(x_train)
    targets = torch.from_numpy(y_train)

    # 利用我们刚刚创建的线性模型前向传播
    outputs = model(inputs)
    # 参数是input与target
    loss = criterion(outputs,targets)

    # 反向传播求导及优化,这一步是自动求导
    # 我们要先将optimizer进行导数清0处理,反正与之前的导数造成误差
    optimizer.zero_grad()
    # 反向传播自动求导
    loss.backward()
    # 优化器进行优化
    optimizer.step()

    if (epoch + 1) % 5 == 0:
        print('Epoch [{}/{}],Loss:{:.4f}'.format(epoch+1,num_epochs,loss.item()))

可视化

predicted = model(torch.from_numpy(x_train)).detach().numpy()
plt.plot(x_train,y_train,'ro',label = 'Original data')
plt.plot(x_train,predicted,label = 'Fitted line')
plt.legend()
plt.show()

在这里插入图片描述
模型保存

torch.save(model.state_dict(),'model.ckpt')

在这里我们讨论一个细节,就是在画图中的代码第一行,有一个detach的操作,所以我们来介绍一下detach和detach_的关系。
具体的作用是:
返回一个新的tensor,从当前计算图中分离下来的,但是仍指向原变量的存放位置
不同之处只是requires_grad为false,得到的这个tensor永远不需要计算其梯度,不具有grad
即使之后重新将它的requires_grad置为true,它也不会具有梯度grad
这样我们就会继续使用这个新的tensor进行计算
后面当我们进行反向传播时,到该调用detach()的tensor就会停止
不能再继续向前进行传播
注意:
使用detach返回的tensor和原始的tensor共用同一个内存,即一个修改另一个也会跟着改变。
当使用detach()分离tensor但是没有更改这个tensor时,并不会影响backward()
当使用detach()分离tensor,然后用这个分离出来的tensor去求导数,会影响backward(),会出现错误
当使用detach()分离tensor并且更改这个tensor时,即使再对原来的out求导数,会影响backward(),会出现错误
detach_:
将一个tensor从创建它的图中分离,并把它设置成叶子tensor
其实就相当于变量之间的关系本来是x -> m -> y
这里的叶子tensor是x,但是这个时候对m进行了m.detach_()操作,其实就是进行了两个操作:
将m的grad_fn的值设置为None,这样m就不会再与前一个节点x关联
这里的关系就会变成x, m -> y,此时的m就变成了叶子结点
然后会将m的requires_grad设置为False,这样对y进行backward()时就不会求m的梯度
往后我们还会见到.data()函数,这种函数虽然不起眼并且基本一看就知道大概什么意思,但是大家还是要把它弄懂,以后用到或者看源码的时候才不会拿不准。.data()可以与.tensor()相同理解,假如out = tensor.data(),则out发生改变,tensor也会发生改变,这个时候如果我们再对tensor进行反向传播就会造成巨大的错误,但是我们并不能发现,因为程序不会告诉我们的,这个requird_grad其实是个False,而且共用一个内存地址,一个变另一个也会变。但是由于不报错,我们的程序就会无阻碍的执行,从而酿成大祸。所以我们就用了.detach(),它与.data()作用几乎一致,只不过它在上述情况会报错来提醒我们

RuntimeError: one of the variables needed for gradient computation has been modified by an

总结

下一篇介绍Pytorch实现Logistic Regression

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值