【动手学深度学习笔记】之Pytorch实现线性回归

时间:2022-07-23
本文章向大家介绍【动手学深度学习笔记】之Pytorch实现线性回归,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

框架实现线性回归

创建数据集

创建数据集与之前一样,因为没有数据集,所以需要直接创建数据集。

#生成数据集
num_inputs = 2  #特征数,数据集的列数
num_examples = 1000  #样本数,数据集的行数
true_w = [2,-3.4]  #线性模型的真实权重
true_b = 4.2    #线性模型的真实偏差

featrues = torch.randn(num_examples,num_inputs,dtype = torch.float32)
#使用随机张量函数,生成一个1000行2列的随机张量
labels = true_w[0]*featrues[:,0]+true_w[1]*featrues[:,1]+true_b
#使用随机张量作为输入生成一组标签
labels += torch.tensor(np.random.normal(0,0.01,size = labels.size()),dtype = torch.float32)
#为标签加随机噪声,生成随机噪声方法:使用numpy库的random.normal生成一个均值为0,标准差为0.0.1的正态分布,其大小为1行2000个的行向量。
#在这一部分,使用了两种随机矩阵生成的方法,主要区别是第二个为正态分布。且第二种生成的行向量。

读取数据

2020/2/23/19:35

pytorch提供了data包来读取数据。

import torch.utils.data as Data
#避免重名,换名处理

batch_size = 10		#小批量数设置为10
dataset = Data.TensorDataset(features,labels)
#将features和labels转化为pytorch框架可以识别的数据集类型。
#数据集的类型是TensorDataset。
data_iter = Data.DataLoader(dataset,batch_size,shuffle=True)
#DataLoader,生成一个迭代器,shuffle:是否开启打乱顺序。

Data.DataLoader包含多个参数

参数

功能

dataset

Dataset类型,从其中加载数据

batch_size

int类型,每个批量加载多少个数

shuffle

bool类型,每个学习周期都打乱顺序

num_workers

int类型,加载数据时使用多少子进程。默认值为0.

collate_fn

定义如何取样本,可通过定义自己的函数来实现。(太深奥,暂且跳过)

pin_memory

锁页内存处理。(太深奥了,暂且跳过)

drop_last

bool类型,如果有剩余的样本,True表示丢弃;Flase表示不丢弃

使用时牢记

  1. 第一步导入:import torch.utils.data as Data
  2. 第二步转化类型:数据集 = Data.TensorDataset(样本集1,样本集2)
  3. 第三步生成迭代器:迭代器 = Data.DataLoader(数据集,加载数)

定义模型

Pytorch提供了大量预定义的层,使用框架时,主要是需要关注使用哪些层来构造模型。

方法一

使用nn.Module搭配forward来撰写网络或层

class LinearNet(nn.module):
    def __init__(self,n_feature):
        super(LinearNet,self).__init__()
        #类中固有的
        
        self.linear = nn.Linear(n_feature,1)
        #定义一个层。
        
    #定义前向传播
    def forward(self,x):
        y = self.linear(x)
        return y
    
#这一步是打印出网络的结构
net = LinearNet(num_inputs)
print(net)

方法二

使用nn.Sequential来搭建网络,Sequential是一个有序容器,网络层将按照传入容器的顺序依次添加到计算图中。

#这里只介绍一种方法
net = nn.Sequential(
	nn.Linear(num_inputs,1)
    #还可以添加其他层
)

#同样的输出方法
print(net)
#输出第一层
print(net[0])

查看模型参数

通过net.parameters(),可查看模型所有的可学习参数(如权重和偏差),注意:net.parameters()是一个生成器,而非一个函数,所以通过for循环来查看。

for param in net.parameters():
    print(param)

初始化模型参数

使用网络前,需要初始化模型参数,如线性回归模型中的权重和偏差。

#首先导入pytorch中的init模块
from torch.nn import init

#使用init.normal_将第一层的权重参数初始化为均值为0,标准差为0.01的正态分布
init.normal_(net.linear.weight,mean=0,std=0.01)	#这种写法对应方法一
init.normal_(net[0].weight,mean=0,std=0.01)		#这种写法对应方法二

#使用init.constant_将偏差初始化为0
init.normal_(net.linear.bias,val=0)	#这种写法对应方法一
init.constant_(net[0].bias,val=0)	#这种写法对应方法二

#net[0]只适用于net是一个容器时

定义损失函数

pytorch提供了各种损失函数,这些损失函数可看作是一种特殊的层,所以这些损失函数实现为nn.Module的子类。

#本节使用均方差损失作为损失函数
loss = nn.MSELoss()

定义优化算法

pytorch在torch.optim模块中提供了很多优化算法

#本节使用小批量随机梯度下降算法(SGD)
import torch.optim as optim

optimizer = optim.SGD(net.parameters(),lr=0.03)
#lr,设置学习率为0.03;net.parameters()导入模型的参数
print(optimizer)	#输出优化算法的各项参数

扩展内容:

#为不同网络设置不同学习率
optimizer = optim.SGD([
    {'params':net.subnet1.parameters()},	#不设置lr,默认使用最外层的
	{'params':net.subnet2.parameters(),lr=0.01}
],lr = 0.03)
#调整学习率
for param_group in optimizer.param_groups:
    param_group['lr']*=0.1		#学习率调整为之前的0.1倍

训练模型

num_epochs = 3 #学习周期为3
for epoch in range(1,num_epochs+1):
    for X,y in data_iter:
        output = net(X)	#特征值对应的标签
        l = loss(output,y.view(-1,1))	#y.view(-1,1)将y转化为一列的形式,行数无要求
        optimizer.zero_grad()	#同样的梯度需要清零
        l.backward()	#对损失函数求梯度
        optimizer.step()#调用优化函数,计算模型参数
        
    print('epoch %d loss:%f' %(epoch,l.item()))

程序

#需要导入的库
import torch  #张量计算
from IPython import display    #嵌入显示图像
from matplotlib import pyplot as plt  #绘制图像
import numpy as np  #矩阵运算
import random  #生成随机数
import torch.utils.data as Data  #避免重名,换名处理
from torch.nn import init  #导入初始化模块
import torch.nn as nn  #导入构建层需要的模块
import torch.optim as optim  #导入内置优化算法的模块

#生成数据集
num_inputs = 2  #特征数,数据集的列数
num_examples = 1000  #样本数,数据集的行数
true_w = [2,-3.4]  #线性模型的真实权重
true_b = 4.2    #线性模型的真实偏差

featrues = torch.randn(num_examples,num_inputs,dtype = torch.float32)
#使用随机张量函数,生成一个1000行2列的随机张量
labels = true_w[0]*featrues[:,0]+true_w[1]*featrues[:,1]+true_b
#使用随机张量作为输入生成一组标签
labels += torch.tensor(np.random.normal(0,0.01,size = labels.size()),dtype = torch.float32)
#为标签加随机噪声,生成随机噪声方法:使用numpy库的random.normal生成一个均值为0,标准差为0.0.1的正态分布,其大小为1行2000个的行向量。
#在这一部分,使用了两种随机矩阵生成的方法,主要区别是第二个为正态分布。且第二种生成的行向量。
batch_size = 10
dataset = Data.TensorDataset(featrues,labels)

data_iter = Data.DataLoader(dataset,batch_size,shuffle=True)

#输出第一组X和y做测试
# for X,y in data_iter:
#     print(X,y)
#     break

#定义模型
class Linear(nn.Module):
    def __init__(self,n_feature):
        super(Linear,self).__init__()
        
        self.linear = nn.Linear(n_feature,1)
        
    def forward(self,x):
        y = self.linear(x)
        return y

net = Linear(num_inputs)  #实例化这个类

#参数初始化
init.normal_(net.linear.weight,mean=0,std = 0.01)  #初始化权重为均值为0,标准差为0.01正态分布
init.constant_(net.linear.bias,val=0)  #初始化偏差为0

#定义损失函数(均方差损失函数)
loss = nn.MSELoss()

#定义优化算法(同样的小批量随机梯度下降算法)
optimizer = optim.SGD(net.parameters(),lr = 0.03)

#训练过程
num_epochs = 3  #学习周期

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()))
    
print(true_w,'n',net.linear.weight)
print(true_b,'n',net.linear.bias)