【动手学深度学习笔记】之线性回归实现
时间: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什么意思。好像是对数据本身进行操作
训练模型
在训练中,多次迭代模型参数。在每次迭代中:
- 读取小批量随机样本
- 调用反向函数.backward计算样本的梯度(小批量随机梯度)
- 调用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)
- Selenium2+python自动化44-元素定位参数化(find_element)
- Selenium2+python自动化45-18种定位方法(find_elements)
- Python做文本挖掘的情感极性分析(基于情感词典的方法)
- Selenium2+python自动化42-判断元素(expected_conditions)
- 基于机器学习的文本情感极性分析
- Selenium2+python自动化43-判断title(title_is)
- hihoCoder #1142 : 三分求极值
- 容斥原理
- TensorFlow:TensorBoard可视化
- Codeforces 768B Code For 1
- 【干货】深入理解自编码器(附代码实现)
- SlopOne推荐算法(附Python源码)
- 后缀数组(一堆干货)
- POJ 1741 Tree(树的点分治,入门题)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android开发之Socket通信传输简单示例
- Android自定义对话框Dialog的简单实现
- Android编程实现Toast只显示最后一条的方法
- Android 照相机的实例应用
- Android 逐帧动画创建实例详解
- 腾讯云 Severless 项目开发和灰度发布实践之路
- C/C++ Search Extension —— 一款可以快速在地址栏搜索 C/C++ 文档的浏览器插件
- 一些小众却有用的 Node.js 包
- 用Single-spa 创建基于 React 和 Vue 的微型前端
- 为 Vue 的惰性加载加一个进度条
- 50个能帮你节省时间的开发工具
- 【技术向】高可定 低维护の博客搭建指南
- 如何学习源码 | 如何高效学习一个新知识
- 我们为什么要禁用 THP
- web前端基础