Pytorch之线性回归
从零开始实现
%matplotlib inline
import torch
import numpy as np
import random
生成数据集
设训练数据集样本数为1000,特征数为2,使用线性回归模型真实权重 $$ w=[2,-3.4]^T $$ 和偏差 $$ b=4.2 $$, 以及一个噪声项 $$ \epsilon $$ 来生成标签: $$ y=Xw+b+\epsilon $$
其中噪声项服从均值0,标准差0.01的正态分布
num_inputs=2
num_examples=1000
true_w=[2,-3.4]
true_b=4.2
features=torch.from_numpy(np.random.normal(0,1,(num_examples,num_inputs)))
labels=true_w[0]*features[:,0]+true_w[1]*features[:,1]+true_b
labels+=torch.from_numpy(np.random.normal(0,0.01,size=labels.size()))
features.dtype
torch.float64
labels.dtype
torch.float64
labels.shape
torch.Size([1000])
a=torch.tensor([2,3]).view(2,1)
a.dtype
torch.int64
features@a
RuntimeError Traceback (most recent call last)
in
----> 1 features@a
RuntimeError: expected scalar type Double but found Long
上面报错说明,两个tensor如果dtype不一致,那么实行矩阵乘法会报错
- 数据类型的转换
(1)不会改变原tensor的数据类型
a = torch.tensor([1, 2, 3])
b = a.long() # torch.int 64
b = a.half() # torch.float 16
b = a.int() # torch.int32
b = a.double() # torch.float64
b = a.float() # torch.float32
b = a.char() # torch.int8
b = a.byte() # torch.unint8
b = a.short() # torch.int16
(2)不会改变原tensor的数据类型
a = torch.tensor([1, 2, 3])
b = a.type(torch.float) # 不改变a的类型
b = a.type(torch.FloatTensor)
(3)不会改变原tensor的数据类型
a = torch.LongTensor([1, 2, 3])
b = torch.DoubleTensor([1, 2, 3])
c = a.type_as(b) # 不改变a的类型
a=a.double()
a.dtype
torch.float64
(features@a).shape # 现在可以进行矩阵乘法
torch.Size([1000, 1])
读取数据
在训练模型时,我们需要遍历数据集并不断读取小批量数据样本。我们定义一个函数:每次返回batch_size
个随机样本的特征和标签。
def data_iter(batch_size,features,labels):
num_examples=len(features)
indices=list(range(num_examples))
random.shuffle(indices)
for i in range(0,num_examples,batch_size):
j=torch.LongTensor(indices[i:min(i+batch_size,num_examples)]) # index_select(dim,index)中的index必须是LongTensor类型,否则报错
yield features.index_select(0,j),labels.index_select(0,j) #生成迭代器对象
初始化模型参数
将权重初始化为均值为0,标准差为0.01的正态随机数,偏差初始化为0.
w=torch.tensor(np.random.normal(0,0.01,(num_inputs,1)),dtype=torch.float64) #与features的数据类型保持一致!
b=torch.zeros(1,dtype=torch.float64)
w.requires_grad_(requires_grad=True)
b.requires_grad_(requires_grad=True) #打开梯度追踪
tensor([0.], dtype=torch.float64, requires_grad=True)
定义模型
def linreg(X,w,b):
return torch.mm(X,w)+b
定义loss损失函数
def squared_loss(y_hat,y):
return (y_hat-y.view(y_hat.size()))**2/2 # y_hat的形状是10*1 而y的形状的10
定义优化算法
def sgd(params,lr,batch_size):
"""
lr:learning rate
"""
for param in params:
param.data-=lr*param.grad/batch_size
训练模型
lr=0.03
epochs=3
net=linreg #网状结构
loss=squared_loss #损失函数
batch_size=10
for epoch in range(epochs):
for X,y in data_iter(batch_size,features,labels):
l=squared_loss(net(X,w,b),y).sum() #前向传播,并得到loss,注意要sum形成标量才可以向后传播
l.backward() #实施向后传播
sgd([w,b],lr,batch_size) #梯度下降,优化算法来更改权重
w.grad.data.zero_()
b.grad.data.zero_() #梯度清零
train_1=loss(net(features,w,b),labels) #计算本轮的loss
print('epoch %d, loss %f'%(epoch+1,train_1.mean().item()))
epoch 1, loss 0.041714
epoch 2, loss 0.000164
epoch 3, loss 0.000052
print(true_w,w)
[2, -3.4] tensor([[ 1.9992],
[-3.3993]], dtype=torch.float64, requires_grad=True)
print(true_b,b)
4.2 tensor([4.1989], dtype=torch.float64, requires_grad=True)
可以发现用线性回归学到的参数与真实的参数非常接近!
简洁实现
生成数据集
num_inputs=2
num_examples=1000
true_w=[2,-3.4]
true_b=4.2
features=torch.tensor(np.random.normal(0,1,(num_examples,num_inputs)),dtype=torch.float)
labels=true_w[0]+features[:,0]+true_w[1]*features[:,1]+true_b
labels+=torch.tensor(np.random.normal(0,0.01,labels.size()),dtype=torch.float)
读取数据
Pythorch
提供了data
包来读取数据。由于data
常用作变量名,可以将导入的data
模块用Data
代替,每次迭代中,随机读取包含10个数据样本的小批量。
import torch.utils.data as Data
batch_size=10
dataset=Data.TensorDataset(features,labels) # 形成数据集合
data_iter=Data.DataLoader(dataset,batch_size,shuffle=True) # 小批量加载数据
这里data_iter
的使用跟上一节的一样。
for X,y in data_iter:
print(X,y)
break
tensor([[-0.1835, -0.4796],
[ 0.7839, 0.6707],
[ 0.6548, 0.2327],
[-1.1723, 1.4427],
[-0.5087, -0.4832],
[-0.2282, 1.2669],
[ 0.0427, -0.0728],
[-0.6034, 0.7240],
[ 1.9960, -0.0139],
[-0.5563, -0.0912]]) tensor([7.6456, 4.6837, 6.0557, 0.1332, 7.3290, 1.6784, 6.4854, 3.1342, 8.2342,
5.9319])
定义模型
Pytorch
提供了大量的预定义层,这使得我们只需要关注使用哪些层来构造模型。下面将使用Pytorch更简洁的定义线性回归。
首先导入torch.nn
模块,实际上,'nn'是'neural networks'的缩写。该模块定义了大量神经网络的层。nn
的核心数据结构是Module
,它是一个抽象的概念,既可以表示神经网络的某个层,也可以表示一个包含很多层的神经网络。在实际使用中,最常见的方法是继承nn.Module
,撰写自己的层。一个nn.Module
实例应包含一些层及返回输出的前向传播(forward)方法。
from torch import nn
class LinearNet(nn.Module):
def __init__(self,n_feature):
super().__init__()
self.linear=nn.Linear(n_feature,1)
def forward(self,x):
y=self.linear(x)
return y
net=LinearNet(num_inputs)
net
LinearNet(
(linear): Linear(in_features=2, out_features=1, bias=True)
)
事实上,我们还可以用nn.Sequential
来更加方便的搭建网络。Sequential
是一个有序的容器,网络层将按照传入Sequential
的顺序依次被添加到计算容器中。
# 写法一
net=nn.Sequential(
nn.Linear(num_inputs,1)
#此处可以传入其他层
)
#写法二
net=nn.Sequential()
net.add_module('linear',nn.Linear(num_inputs,1))
#net.add_module...
#写法三
from collections import OrderedDict
net=nn.Sequential(OrderedDict([
('linear',nn.Linear(num_inputs,1)),
#.....
]))
print(net)
print(net[0])
Sequential(
(linear): Linear(in_features=2, out_features=1, bias=True)
)
Linear(in_features=2, out_features=1, bias=True)
可以通过net.parameters()
来查看模型所有可学习参数,此函数返回一个生成器。
for param in net.parameters():
print(param)
Parameter containing:
tensor([[0.5336, 0.3508]], requires_grad=True)
Parameter containing:
tensor([-0.1604], requires_grad=True)
线性回归作为一个单层神经网络,线性回归输出层中的神经元和输入层中的各个输入完全连接,因此,线性回归的输出层又叫全连接层。
初始化模型参数
在使用net
前,我们需要初始化模型参数,如线性回归模型中的权重和偏差。Pytorch在init
模块中提供了多种参数初始化方法,通过init.normal_
将权重参数每个元素初始化为随机采样于均值为0,标准差为0.01的正态分布,偏差初始化为0.
from torch.nn import init
init.normal_(net[0].weight,mean=0,std=0.01)
init.constant_(net[0].bias,val=0) #此处可以直接修改bias的data:net[0].bias.data.fill_(0)
Parameter containing:
tensor([0.], requires_grad=True)
定义损失函数
Pytorch在nn
模块中提供了各种损失函数,这些损失函数可看作一个特殊的层,故,Pytorch也将这些损失函数实现为nn.Module
的子类。用它提供的均方差损失作为模型的损失函数:
loss=nn.MSELoss()
定义优化算法
我们无需自己实现小批量随机梯度算法。torch.optim
模块提供了很多常用的优化算法比如SGD,Adam和RMSProP等,下面创建一个用于优化net
所有参数的优化容器实例,并指定学习率为0.03的小批量随机梯度为优化算法。
import torch.optim as optim
optimizer=optim.SGD(net.parameters(),lr=0.03)
print(optimizer)
SGD (
Parameter Group 0
dampening: 0
lr: 0.03
momentum: 0
nesterov: False
weight_decay: 0
)
我们还可以为不同子网络设置不同的学习率,这在微调时常用到:
optimizer=optim.SGD([
#如果对某参数不指定学习率,就使用最外层的默认学习率
{'params':net.subnet1.parameters()},
{'params':net.subnet2.parameters(),'lr':0.01},
lr=0.03
]
有时候,不想让学习率固定为一个常数,那么如何调整学习率?(1)修改optimizer.param_groups
中对应的学习率,另一种也是更简单的也是推荐做法:新建优化器,optimizer非常轻量级,构建开销小,但是后者对于使用动量的优化器(如Adam),会丢失栋梁状态信息,造成损失函数收敛震荡。
for param_group in optimizer.param_groups:
param_group['lr']*=0.1 #学习率是之前的0.1倍
训练模型
在训练模型时,我们通过调用optim
实例的step
函数来迭代模型参数。按照小批量随机梯度的定义,在step
函数中指明批量的大小,从而对批量中样本梯度求平均。
num_epochs=20
for epoch in range(1,num_epochs+1):
for X,y in data_iter:
output=net(X)
l=loss(output,y.view(-1,1))
optimizer.zero_grad()
l.backward()
optimizer.step()
print('epoch %d, loss %f'%(epoch,l.item()))
epoch 1, loss 15.379764
epoch 2, loss 5.109397
epoch 3, loss 1.277820
epoch 4, loss 0.790176
epoch 5, loss 0.274319
epoch 6, loss 0.052126
epoch 7, loss 0.022905
epoch 8, loss 0.009597
epoch 9, loss 0.000860
epoch 10, loss 0.000556
epoch 11, loss 0.000128
epoch 12, loss 0.000181
epoch 13, loss 0.000131
epoch 14, loss 0.000097
epoch 15, loss 0.000073
epoch 16, loss 0.000114
epoch 17, loss 0.000154
epoch 18, loss 0.000056
epoch 19, loss 0.000076
epoch 20, loss 0.000099
dense=net[0]
print(dense.weight)
print(dense.bias)
Parameter containing:
tensor([[ 1.0000, -3.4000]], requires_grad=True)
Parameter containing:
tensor([6.1995], requires_grad=True)
Pytorch之线性回归的更多相关文章
- 03_利用pytorch解决线性回归问题
03_利用pytorch解决线性回归问题 目录 一.引言 二.利用torch解决线性回归问题 2.1 定义x和y 2.2 自定制线性回归模型类 2.3 指定gpu或者cpu 2.4 设置参数 2.5 ...
- Pytorch 实现线性回归
Pytorch 实现线性回归 import torch from torch.utils import data from torch import nn # 合成数据 def synthetic_d ...
- 从头学pytorch(三) 线性回归
关于什么是线性回归,不多做介绍了.可以参考我以前的博客https://www.cnblogs.com/sdu20112013/p/10186516.html 实现线性回归 分为以下几个部分: 生成数据 ...
- Pytorch实战学习(一):用Pytorch实现线性回归
<PyTorch深度学习实践>完结合集_哔哩哔哩_bilibili P5--用Pytorch实现线性回归 建立模型四大步骤 一.Prepare dataset mini-batch:x.y ...
- 【项目实战】用Pytorch实现线性回归
视频教程:https://www.bilibili.com/video/BV1Y7411d7Ys?p=5 准备数据 首先配置了环境变量,这里使用python3.9.7版本,在Anaconda下构建环境 ...
- 用Pytorch训练线性回归模型
假定我们要拟合的线性方程是:\(y=2x+1\) \(x\):[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] \(y\):[1, 3, 5, 7, ...
- 【动手学pytorch】线性回归
代码及解释 错题整理
- 神经网络架构PYTORCH-宏观分析
基本概念和功能: PyTorch是一个能够提供两种高级功能的python开发包,这两种高级功能分别是: 使用GPU做加速的矢量计算 具有自动重放功能的深度神经网络从细的粒度来分,PyTorch是一个包 ...
- pytorch从入门到放弃(目录)
目录 前置基础 Pytorch从入门到放弃 推荐阅读 前置基础 Python从入门到放弃(目录) 人工智能(目录) Pytorch从入门到放弃 01_pytorch和tensorflow的区别 02_ ...
- [Pytorch框架] 2.2 深度学习基础及数学原理
文章目录 2.2 深度学习基础及数学原理 2.2.1 监督学习和无监督学习 2.2.2 线性回归 (Linear Regreesion) 2.2.3 损失函数(Loss Function) nn.L1 ...
随机推荐
- 什么是极限编程 (XP)?
极限编程(XP) 是2000 年代初期最广为人知和使用最多的敏捷方法之一.XP 是Kent Beck.Ron Jeffries和Ward Cunningham的创意,基于他们在戴姆勒克莱斯勒的集体经验 ...
- TVbox蜂蜜影视_v3.1.6:智能电视观影新选择,简洁界面与强大功能兼具
蜂蜜影视是一款基于猫影视开源项目 CatVodTVJarLoader 开发的智能电视软件,专为追求简洁与高效观影体验的用户设计.该软件从零开始编写,界面清爽,操作流畅,特别适合在智能电视上使用.其最大 ...
- mysql 卸载安装教程链接
https://blog.csdn.net/weixin_56952690/article/details/129678685 https://blog.51cto.com/u_16213646/70 ...
- 大模型基础补全计划(二)---词嵌入(word embedding)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明 无 前言 本文是这个系列第二篇,它们是: &l ...
- mac环境配置本地nfs服务
前言 在这篇文章中,讲了在Mac端开启NFS服务,并通过NFS协议让其他设备挂载到你的Mac上. 步骤一:增加配置文件 首先,我们需要编辑NFS的配置文件,以便定义哪些目录可以被远程访问. 打开终端, ...
- breach1靶机渗透学习
靶机下载 https://www.vulnhub.com/ 找Breach-1.0,不过这个是老靶机了,可以看网上其他博客附带有靶机下载的网盘链接,靶机官网访问很慢而且网站好像出问题了排版很乱,不打也 ...
- docker swarm CA证书到期
1.现象 在portain平台查看日志,发现一些节点日志无法查看报错为:Error grabbing logs: rpc error: code = Unknown desc = warning: i ...
- 使用PowerPoint优雅地更改证件照底色
使用PowerPoint优雅地更改证件照底色 首先我们打开一张空白的演示文稿,并将要修改的证件照进行粘贴.(图片来自窝窝摄影,侵删) 选中图片,点击 格式,再点击 删除背景. 点击标记要保留的区域,对 ...
- ANSYS 命令流导航
常见书籍 ANSYS 命令流导航 GitHub 项目:ANSYS_Code Gitee 镜像:ANSYS_Code 欢迎补充~ 文件说明 doc 中包括 ANSYS, ABAQUS, LS-DYNA ...
- 【MathJax】语法总结
基础语法 1.显示公式 在行中显示的 (inline mode),就用 $...$ 单独一行显示 (display mode),则用 $$...$$ 2.希腊字母 要显示希腊字母,可以用 \alpha ...