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

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

实现线性回归

这一节不牵扯深度学习框架,仅使用Tensor和autograd库来训练线性回归模型。

#需要导入的库import torch	#张量计算from IPython import display		#嵌入显示图像from matplotlib import pyplot as plt	#绘制图像import numpy as np		#矩阵运算import random	#生成随机数

创建一个数据集

要训练一个模型,首先需要训练数据集和数据对应的标签。

先随机生成一个样本数为1000的「随机样本特征」

然后使用真实模型 y = 2x1-3.4x2+4.2+随机噪声项,生成1000个「标签」

其中随机噪声项服从均值为0、标准差为0.01的正态分布,代表列无意义的干扰

程序实现

#生成数据集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个的行向量。#在这一部分,使用了两种随机矩阵生成的方法,主要区别是第二个为正态分布。且第二种生成的行向量。

数据可视化:绘制散点图象

def use_deg_display():    display.set_matplotlib_formats('svg')    #绘制矢量图,不同散点有深浅。    def set_figsize(figsize=(3.5,2.5)):    use_deg_display()    plt.rcParams['figure.figsize'] = figsize    #设置散点图和图像大小    set_figsize()
%matplotlib inline#使用juterpy notebook要注意,需要使用这行代码,才能显示图像
plt.scatter(featrues[:,1].numpy(),labels.numpy(),c='b');#关于散点图绘制函数的参数,见这个:https://www.imooc.com/article/29522

绘制出的散点图

读取数据

#读取数据def data_iter(batch_size,features,labels):    num_examples = len(features)    indices = list(range(num_examples))    #从0到num_examples生成一个列表indices    random.shuffle(indices)                #打乱indices这个列表(随机)        #这个for循环也叫做迭代器    for i in range(0,num_examples,batch_size):	#找到每一个小批量起始的索引(如:0 10 20...)        j = torch.LongTensor(indices[i:min(i+batch_size,num_examples)])        #将小批量对应的所有索引转换为张量j        yield features.index_select(0,j),labels.index_select(0,j)        #定义了一个生成器,节省了内存       #输出batch_size =10for X,y in data_iter(batch_size,featrues,labels):    print(X,y)    break	#只输出一次    #使用for循环来读取生成器data_iter中的数据

20202211:48

20202228:57

初始化模型参数

模型参数指:权重w1,w2;偏差b。

首先将权重初始化成均值为0,标准差为0.01的正态随机数。偏差初始化为0。

w = torch.tensor(np.randm.normal(0,0.01,(num_inputs,1)),dtype = torch.float32)#使用numpy生成大小为2*1的一个均值为0,标准差为0.01正态分布b = torch.zeros(1,dtypr = float32)#生成一个大小为1的全0矩阵

定义模型

将前文所述的矩阵形式模型

转换为程序形式

def linreg(X,w,b):	return torch.mm(X,w)+b	#torch.mm(X,b)函数,对X和b进行矩阵乘法运算。

定义损失函数

也是将之前的函数

转换为程序形式

def squared_loss(y_hat,y):	return (y_hat - y.view(y_hat_size()))**2/2	#**是平方

定义优化算法

实现上一节中的小批量随机下降算法,通过不断迭代模型参数来优化损失函数。

def sgd(params,lr,batch_size):    for param in aprams:        param.data -= lr*param.grad/batch_size        #不理解.data什么意思。好像是对数据本身进行操作

训练模型

在训练中,多次迭代模型参数。在每次迭代中:

  1. 读取小批量随机样本
  2. 调用反向函数.backward计算样本的梯度(小批量随机梯度)
  3. 调用sgd函数迭代模型参数,然后将参数的梯度清零
#当前程序迭代周期数设置为3;学习率设置为0.03lr = 0.03num_epochs = 3net = linreg 		#换名loss = squared_loss	#换名,不知道为什么
for epoch in range(num_epochs):    #一共需要num_epochs个迭代周期    #每一个迭代周期都需要遍历所有样本    for X,y in data_iter(batch_size,features,labels):        #一次接收一组读取数据得到的小批量特征与标签        l = loss(net(X,w,b),y).sum()        #首先计算模型得到的值,再计算损失函数值,由于直接计算得到的是向量的形式,无法直接求梯度,因此对他进行加和运算。        l.backward()        #对损失函数求梯度        sgd([w,b],lr,batch_size)        #利用优化算法,迭代模型参数        w.grad.data.zero_()        b.grad.data.zero_()        #对参数梯度清零            train_l = loss(net(features,w,b),labels)	#当前周期的损失函数值    print('epoch %d,loss %f' %(epoch+1,train_l.mean().item()))    #对损失值求均值。输出每一个学习周期得到的损失值。

程序

import torchfrom IPython import displayfrom matplotlib import pyplot as pltimport numpy as npimport random
#生成数据集num_inputs = 2num_examples = 1000true_w = [2,-3.4]true_b = 4.2features = torch.randn(num_examples,num_inputs,dtype = torch.float32)#1000行2列labels = true_w[0]*features[:,0]+true_w[1]*features[:,1]+true_blabels += torch.tensor(np.random.normal(0,0.01,size = labels.size()),dtype = torch.float32)
#绘制图像def use_deg_display():    display.set_matplotlib_formats('svg')    def set_figsize(figsize=(3.5,2.5)):    use_deg_display()    plt.rcParams['figure.figsize'] = figsize    # set_figsize()# %matplotlib inline# plt.scatter(featrues[:,1].numpy(),labels.numpy(),c='b');
#读取数据def data_iter(batch_size,features,labels):    num_examples = len(features)    indices = list(range(num_examples))    #从0到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)])        yield features.index_select(0,j),labels.index_select(0,j)
w = torch.tensor(np.random.normal(0,0.01,(num_inputs,1)),dtype = torch.float32)#使用numpy生成大小为2*1的一个均值为0,标准差为0.01正态分布b = torch.zeros(1,dtype = torch.float32)#生成一个大小为1的全0矩阵
w.requires_grad_(requires_grad=True)b.requires_grad_(requires_grad=True)#开始追踪其上的所有操作
def linreg(X,w,b):    return torch.mm(X,w)+b    #torch.mm(X,b)函数,对X和b进行矩阵乘法运算。    def squared_loss(y_hat,y):    return (y_hat - y.view(y_hat.size()))**2/2    #view:将y转换为与y_hat同形的    def sgd(params,lr,batch_size):    for param in params:        param.data -= lr*param.grad/batch_size        #不理解.data什么意思。好像是对数据本身进行操作
#当前程序迭代周期数设置为3;学习率设置为0.03lr = 0.03num_epochs = 3net = linreg 		#换名loss = squared_loss	#换名,不知道为什么batch_size = 10
for epoch in range(num_epochs):    #一共需要num_epochs个迭代周期    #每一个迭代周期都需要遍历所有样本    for X,y in data_iter(batch_size,features,labels):        #一次接收一组读取数据得到的小批量特征与标签        l = loss(net(X,w,b),y).sum()        #首先计算模型得到的值,再计算损失函数值,由于直接计算得到的是向量的形式,无法直接求梯度,因此对他进行加和运算。        l.backward()        #对损失函数求梯度        sgd([w,b],lr,batch_size)        #利用优化算法,迭代模型参数        w.grad.data.zero_()        b.grad.data.zero_()        #对参数梯度清零            train_l = loss(net(features,w,b),labels)	#当前周期的损失函数值    print('epoch %d,loss %f' %(epoch+1,train_l.mean().item()))    
print(true_w,'n',w)print(true_b,'n',b)