零基础利用实战项目学会Pytorch

目录

pytorch简介

1.线性回归

2.数据类型

2.1数据类型检验

2.2Dimension=0/Rank=0

[2.3 Dim=1/Rank=1](#2.3 Dim=1/Rank=1)

[2.4 Dim=2/Rank=2](#2.4 Dim=2/Rank=2)

3.一些方法

4.Pytorch完成分类任务

4.1模型参数

[4.2 前向传播](#4.2 前向传播)

4.3训练以及验证

[4.4 三行搞定!](#4.4 三行搞定!)

[4.5 准确率](#4.5 准确率)

5、Pytorch完成回归任务

[5.1 One-hot编码](#5.1 One-hot编码)

[5.2 保存一些量](#5.2 保存一些量)

[5.3 标准化操作](#5.3 标准化操作)

[5.4 构建网络模型](#5.4 构建网络模型)

[5.5 简单方法构建网络模型](#5.5 简单方法构建网络模型)

6、Pytorch实现卷积神经网络

6.1导入数据集

[6.2 卷积网络模块构建](#6.2 卷积网络模块构建)

6.3前向传播

6.4准确率

6.5训练网络模型

7、图像识别常用模块解读

7.1数据读取与图像预处理

7.2加载models中提供的模型,并直接用训练好的权重当作初始化参数

7.3设置哪些层需要训练

7.4参数更新

[7.5 训练模块](#7.5 训练模块)

8、Dataloader文件标注

8.1任务1:读取txt文件中的路径和标签

8.2任务2:分别把标签和数据存放在list中

8.3任务3:数据路径得完整

8.4任务4:将上述三步写在一起

8.5任务5:数据预处理(transform)

8.6任务6:根据写好的class类实例化自己的dataloader

8.7任务7:用前试试,整个数据和标签对应下,看看对不对

9、LSTM文本任务

[9.1 文本任务数据预处理](#9.1 文本任务数据预处理)


pytorch简介

通常,PyTorch 的用途如下:

  • 替代 NumPy 以利用 GPU 的强大功能。
  • 提供最大灵活性和速度的深度学习研究平台。

PyTorch 是一个由以下组件组成的库

|-----------------------|---------------------------------------------------------------|
| Component | 描述 |
| torch | 类似 NumPy 的 Tensor 库,具有强大的 GPU 支持 |
| torch.autograd | 基于 Tape 的自动微分库,支持 Torch 中所有可微分的张量操作 |
| torch.jit | 编译堆栈 (TorchScript),用于从 PyTorch 代码创建可序列化和可优化的模型 |
| torch.nn | 与 autograd 深度集成的神经网络库,旨在实现最大的灵活性 |
| torch.multiprocessing | Python 多处理,但具有跨进程的神奇 torch Tensors 内存共享功能。适用于数据加载和 Hogwild 训练 |
| torch.ultis | DataLoader 和其他实用函数以方便使用 |

**总的来说,是支持 GPU 的张量库,**如果您使用 NumPy,那么您就使用了 Tensors(又名 ndarray)。

本文需要python语言的基础。对于pytorch,学习方法是,边用边学,Torch只是个框架,查的过程才是学习的过程。

1.线性回归

求loss的最小值,得出y与WiX+bi最接近的Wi和bi,这里y是(-∞ + ∞) 的,这就称为Linear Regression(线性回归,拟合)。在Linear Regression添加激活函数,使得y是0 *,*的,这就是Logistic Regression

2.数据类型

之前Numpy一般是在CPU上运行,数据类型是ndarray,而在Pytorch上,数据类型是Tensor(张量),且一般是在GPU上运行的。

对于string类型,pytorch没有提供,但是可以①利用one-hot方法,即将字母改为一个1维向量。

对于输入的数据,一般是array类型,需要将其转换为Tensor类型,方法如下:x_in_trans=map(torch.tensor,(x_in)),其中map是一个映射函数,将x_in转换为x_in_trans,格式由array转换为tensor。

|------------------------|----------------------------|--------------------|-------------------------|
| Data Tpye | dytpe | CPU Tensor | GPU Tensor |
| 32bit floating point | torch.float32/torch.float | torch.FloatTensor | Torch.cuda.FloatTensor |
| 64bit floating point | torch.float64/torch.double | torch.DoubleTensor | Torch.cuda.DoubleTensor |
| 8bit integer(unsigned) | torch.uint8 | torch.ByteTensor | Torch.cuda.ByteTensor |
| 8bit integer(signed) | torch.int8 | torch.CharTensor | torch.cuda.CharTensor |
| 16bit integer(signed) | torch.int16/torch.short | torch.ShortTensor | Torch.cuda.ShortTensor |
| 32bit integer(signed) | torch.int32/torch.int | torch.IntTensor | Torch.cuda.IntTensor |
| 64bit integer(signed) | torch.int64/torch.long | torch.LongTensor | torch.cuda.LongTensor |

2.1数据类型检验

可以用a.type()显示数据类型,也可以用isinstance(a,torch.FloatTensor)进行检验,利用这个data=data.cuda(),可以将数据转换在cuda上

2.2Dimension=0/Rank=0

Dim=0的数据(标量),用于loss值的计算。

2.3 Dim=1/Rank=1

可以是1*n的向量,在torch统称为张量,常用于Bias偏置量,也用于Linear Input线性层的输出。

2.4 Dim=2/Rank=2

注意,Dim指的是维度,如a是2行3列的矩阵,则它的维度dim=2是2维的,size是它的形状,是size([2,3]),表示它的形状是2行3列的,也就是shape。即a.shape输出torch.size([2,3]),size是列表。a.size(0)表示的是size的第一个数据,即为2。同样的a.shape[0]输出也是2。Dim=2的张量,常用于LinearInput batch

3.一些方法

x.shape即可获取x的格式。torch.size返回一个元组(tuple),包含了 PyTorch 张量 x 的各个维度的尺寸信息。注意,x.shape也返回一个元组(tuple),包含了 PyTorch 张量 x 的各个维度的尺寸信息。

torch.nn.functional内置了一些常用的损失函数和激活函数。如cross_entropy交叉熵损失函数。import torch.nn.functional as F;然后loss_func=F.cross_entropy,即可指定loss_func是交叉熵损失函数。

x.mm(weights)+bias即实现wx+b操作,mm指的是矩阵乘法。对于w,它最开始是随机初始化weights=torch.randn([a,b],dtype=torch.float,requires_grad=True)即可完成对weights的随机初始化为a行b列的矩阵,randn是随机初始化方法,dtype=torch.float指的是元素为float类型,requires_grad=True表示是否需要更新。

4.Pytorch完成分类任务

4.1模型参数

python 复制代码
class Model_Name (nn.Module):
	def __init__(self):
		super().__init__()
		self.hidden1=nn.Linear(784a,128b)
self.hidden2=nn.Linear(128a,256b)	
self.out=nn.Linear(256a,10b)
self.dropout=nn.Dropout(0.5)

Model_Name 是要定义的类名,它必须继承nn.Module父类。def init(self)是构造函数,这是接下来构建模型时必备的一些属性、一些参数。self.hidden1=nn.Linear(a,b)是利用了Linear函数实现"全连接"(wx+b),其中a表示输入,b表示输出(即输入784,输出128),需要几层就构建几层,对于分类任务,最后输出也是全连接,就是self.out=nn.Linear(256a,10b),即输出10个分类. self.dropout=nn.Dropout(0.5)表示Dropout,0.5表示按照50%杀死部分"神经元"。以上就是模型所需的参数、属性。

在torch中,前向传播需要自行定义,反向传播是自动的。

4.2 前向传播

python 复制代码
def forward(self,x):
		x=F.relu(self.hidden1(x))
		x=self.dropout(x)
		x=F.relu(self.hidden2(x))
x=self.dropout(x)
x=self.out(x)
return x

输入是x,这个x是数据中的batch数据的特征,如x是64*784,表示 batch是64,特征是784个(64个样本,每个样本784个特征)。这个前向传播利用到了模型参数中的东西。

以上过程貌似没有定义权重参数,但是实则是pytorch自动定义了。利用以下方法获取哥哥权重参数:

python 复制代码
net = Model_Name()
for name,parameter in net.named_parameter():
	print(name,parameter,parameter.size())

利用net实例化,再利用net调用named_parameter()即可获取这些参数的名字及参数。

4.3训练以及验证

python 复制代码
def fit(steps,model,loss_func,opt,train_dl,valid_dl):
	for step in range(steps):
		model.train()
		for xb,yb in train_dl:
			loss.batch(model,loss_func,xb,yb,opt)
		
		model.valid()
		with torch.no_grad():
			losses,nums=zip(
*[loss_batch(model,loss_func,xb,yb) for xb,yb in valid_dl]
)
			Val_loss=np.sum(np.multiply(losses,nums))/np.sum(nums)
			print('当前step:'+str(step),'验证集损失:'+str(val_loss))	

steps指的是迭代次数,model是模型,loss_func是损失函数,opt是优化器,train_dl,valid_dl是训练集和验证集。这里的steps相当于epoch,而下面的for循环指的是batch(假如一共有 1000 个数据,每次训练100 个,则batch 就是100 (每次训练100 个数据),而epoch 就是10 (次迭代))。后面的zip就是python的基础了,是打包解包的方法。

以下是优化器的定义:

python 复制代码
def get_model():
       model= Model_Name()
       return model,optim.SGD(model.parameters(),lr=0.001)

其中model定义了模型,optim调用SGD优化器,表示的是梯度下降,model.parameters()表示的是接下来要更新什么参数(这里就是全更新),lr是学习率。除了SGD,还有Adam,更为常用。

以下是loss.batch 的定义:

python 复制代码
def loss_batch(model,loss_func,xb,yb,opt=None):
	loss=loss_func(model(xb),yb)
	if opt is not None:
		loss.backward()
		opt.step()
		opt.zero_grad()
	return loss.item(),len(xb)

这个loss_batch函数的目的就是求出损失loss(model(xb)是预测值,yb是真实值),其次是更新权重参数w,b(如果有优化器,就利用backward()进行反向传播,step()就是参数更新)。原本第一次,第二次,第n次迭代毫无关系,但是torch会进行累计,所以利用opt.zero_grad()将梯度置为零。将这三步视为必备,必须这样写。

4.4 三行搞定!

python 复制代码
train_dl,valid_dl=get_data(train_ds,valid_ds,bs)
	model,opt=get_model()
	fit(20,l,loss_func,opt,train_dl,valid_dl)

获取数据,获得模型和优化器,训练以及验证

4.5 准确率

python 复制代码
correct=0
total=0
for xb,yb in valid_ld:
	outputs = model(xb)
	_,predicted=torch.max(outputs.data,1)
	total+=yb.size(0)
	correct+=(predicted==yb).sum().item()
print('Aurracy of network :%d,%%'%(100*correct/total))

准确率在验证集或者测试集上完成计算.

5、Pytorch完成回归任务

回归任务就是经过一系列神经网络,返回一个值

5.1 One-hot编码

利用pandas的get_dummies函数完成

5.2 保存一些量

①将标签值存下②去掉标签值的那一列存下③保存名字④将features转换为ndarray格式。

5.3 标准化操作

将原本不是以中心对称的数据点,拉回来,使其中心对称

5.4 构建网络模型

将输入数据转换为tensor格式。requires_grad表示要进行梯度更新。并指定学习率(就是更新梯度幅度的大小,再乘上学习率,就是在已知更新方向的基础上,要走多少距离,这个距离要小一点),在定义losses损失列表。

这是前向传播的部分,mm是矩阵乘法,hidden经过wx+b操作,在进行relu非线性激活函数,在一层后得到预测结果,并计算损失,将损失值添加进losses损失列表中(转化为ndarray格式,是因为matplotlib支持ndarray而不支持tensor)

(以上代码依然在前向传播的for循环中)反向传播直接利用backward()完成,更新参数时,利用w.grad.data拿到梯度值,并乘以学习率,负号是因为:**看似是梯度下降,是下山问题,但是实际是沿着梯度反方向去更新,是想找什么参数,让损失最低。**由于每次迭代无关,所以然后清零。更新参数这个写法比较麻烦,实际是可以直接调包的。

5.5 简单方法构建网络模型

batch_size是方便计算损失的(原先的是每个数据都进行计算损失,但是实际上数据量及其庞大,所以每batch_size大小的数据再进行一次损失计算)。Sequential就是顺序进行,按顺序完成操作(先全连接,再激活函数:sigmoid和relu都行,再全连接)。损失计算也是调包,利用MSELoss损失函数。然后就是优化器,之前是w拿到梯度乘上学习率再添负号,现在是直接利用Adam优化器,并指定优化参数和学习率。Adam思想如下,利用惯性方向,进行平行四边形法则,得到最优方向。

利用batch思想进行。每次只训练一个batch的数据(要加上start和end索引,以方便取出)。

6、Pytorch实现卷积神经网络

6.1导入数据集

导入MNIST数据集,train=True指定训练集,train=False指定验证集,利用transform包将数据更改为tensor类型.

6.2 卷积网络模块构建

CNN是类名字,init()是构造函数,Conv2d表示的二维卷积,Conv3d就是三位卷积,一般用于视频;Conv2d里面的元素,一是in_channel是通道数,1就是灰度图,3就是RGB图像;out_channel输出特征图个数(也是卷积核的个数);kernel_size是卷积核大小;stride是步长;padding是填充操作,padding为2就是在图像周围添加两圈的0。然后就是Relu非线性映射。再然后就是MasPool2d最大池化(kernelSize=2是在2*2进行池化)。

然后就是第二个卷积,(16是in_channel是上个卷积的输出,32是out_channel,5是卷积核大小,1是步长,2是填充)。再继续进行,最终要进行全连接。

6.3前向传播

x是输入,是batch×C×H×W的张量。x.view类似于reshape操作,将数据变为H为x.size(0),W为自动计算的结果,-1表示自动计算。全连接之前先要进行reshape(即view)操作。

6.4准确率

pred后面的[1]表示:max会返回两个值,第一个是这个最大值,第二个是最大值对于的索引,pred拿到的就是索引。然后统计相等的总数。

6.5训练网络模型

nn.CrossEntropyLoss()为常用的交叉熵损失函数的写法,损失函数为交叉熵损失函数,并定义优化器。

利用enumerate枚举,可以得出一batch idx,他就是个计数(1,2,3.......),利用该计数,可以在后面的batch idx%100=0的情况下进行validation(即每过100次跑一次验证集)。net train就是训练;output得到预测值;loss计算损失;梯度清理;反向传播;参数更新;算准确率正确多少个;将多少个正确的保存。

准确率计算是在验证集if语句下的,用于计算准确率,并打印。

7、图像识别常用模块解读

7.1数据读取与图像预处理

data_transformer中制定了所有图像的预处理操作,ImageFolder假设所有的文件按文件夹保存好,每个文件夹下面存储同一类图片,文件夹名字为分类名字。

Data Augmetation 数据增强:所有黑体

++训练集预处理++ :transformer.Compose指的是按顺序完成下列操作:Resize将图像转换为指定长宽的大小(这个大小很重要,越大效果越好但是时间越慢);RandomRoatation (a)指的是在-a到a之间的角度随机旋转(最大45);CenterCrop (64)指的是从中心随机裁剪为长宽是64的图像;RandomHorizontaFlip (p=0.5)是随机垂直翻转, p=0.5是翻转概率;ColorJitter (brightness=0.2,contrast=0.1,saturation=0.3,hue=0.1)依次分别是亮度、对比度、饱和度、色相(这个方法用的很少);RandomGrayscale(p=0.025)指的是概率转换为灰度图(用的更少)。ToTensor转行为tensor格式,Normalize标准化(第一个是标准差,第二个是均值,每个元素指的是RGB三通道,这个数据来源是大型数据集的结果)

++验证集预处理++:不用数据增强。直接resize成想要的的大小,并转化为tensor,并且进行归一化(数据用的是训练集的均值方差数据)。

x是字典的key,在datasets调用ImageFolder。这里的方法不重要,后续有更为通用的方法。

7.2加载models中提供的模型,并直接用训练好的权重当作初始化参数

就是backbone特征提取器,常见的有resnet,alexnet,vgg等等。使用方法有两个,一是在别人论文源码中,将模型复制过来,二是torchvision收录了一些经典网络,可以直接调包。

迁移学习:利用被人的模型以及权重训练自己的数据集。 那么别人的模型如resnet并没有训练过花朵的数据集,这些权重能直接用吗?答案是可以的 ,因为它本身就是提取特征的,权重描述了提取特征好坏的能力 ,而不是针对不同数据集有不同权重。我们要做的只是**微调。**如何微调?调什么参数?若你的数据集比较小,则大部分不用改,只改小部分(如只改输出层)这个方法称为"冻住"。若数据集不大不小,则"冻住"区域小一些(只改从输出层向上几层)。若数据集很大,则每一层都调整权重。最少最少输出层得调整。

model_name指定为resnet,feature extract指定为ture,指的是不更新任何权重。

判断训练设备,是CPU还是GPU。

指定模型为resnet18,即用的是18层的resnet,速度较快,也可以50层的或者153层的,根据条件选择。观察它的网络结构,发现每次卷积完会有BatchNorm2d操作,是因为开始预处理时已经经过了归一化操作,但是在每次卷积之后,分布会发生变化,所以需要再次归一化,使网络学习更好。这个BN层在每次卷积之后都添加。在最后全连接之前,resnet18进行的是全局平均池化(指定步长为1),类似于reshape(学习卷积时在全连接之前将数据拉为长条),加入现在数据是14*14*512,就是将14*14的数据取平均为一个值,512分别操作得到512个值。

设置set_parameter_requires_grad函数用于判断是否更新权重参数,for循环是遍历所有的模型参数,查看是否更新。

通过如下函数,将模型更改为自己的。

7.3设置哪些层需要训练

模型保存为pt文件(保存的是网络结构图,所有的w,b权重参数,以后可以直接用该pt文件)。然后将所有的模型参数保存在param_to_update,如果当params.requires_grad为True的时候,才将param放进param_to_update。这些参数要在opt优化器进行更新。

7.4参数更新

利用Adam更新参数,并定义了衰减策略,用的是stepLR,stepsize是每10次执行衰减,gamma表示学习率变为原来的gamma倍。还定义了交叉熵损失函数。

7.5 训练模块

定义时间、最好的准确率、训练设备、四个list、学习率、最好的模型

8、Dataloader文件标注

标注文件一般是txt文件、json文件、xaml文件等等。

原始数据,先进行随机打乱random shuffle,得到队列,每多少个构成一个batch。

8.1任务1:读取txt文件中的路径和标签

定义一个字典数据data infos,key是图片名字,v是图片内容,然后打开文件,以readline每行去读,strip是去掉换行符等等、split是字符串切分,以空格切分,将其存放在samples列表变量中(格式是[xxx,lables],xxx是名字,一个大list有许多小list)。然后遍历samples这个大list,再在data infos以xxx为key,以lables为v,构建字典。

8.2任务2:分别把标签和数据存放在list中

需要把所有的keys转换为list,所有的values转化为list,这是dataloader将来会在这里提数据。

8.3任务3:数据路径得完整

因为一会要用这个路径去读取数据,所以路径得加上前缀。任务不同,数据不同,方法不同,但是一定要读到图像数据。

把前面的train dir与img路径合并。

8.4任务4:将上述三步写在一起

首先导入Dataset和Dataloader包。并且构造函数__init__和__getitem__函数必须存在。完成的是两个list,一个是存放所有图像数据路径的list,一个是存放所有标签的list。

__init__完成的是两个list,一个是存放所有图像数据路径的list,一个是存放所有标签的list。__getitem__的两个参数都不要更改,idx是随机的索引,首先是得到图像数据和标签数据,判断要不要数据增强,并将标签数据转换为tensor格式。会执行batch次__getitem__函数,batch自己指定,这batch个数据会进入模型。

load annotation函数是将字典转换成list。

8.5任务5:数据预处理(transform)

同样在__getitem__函数中完成。在transform这里就完成了数据转换为tensor格式。代码和之前一模一样。

8.6任务6:根据写好的class类实例化自己的dataloader

实例化两个,train dataset和val dataset。

利用Dataloader包完成构建dataloader,传入对应的参数即可。

8.7任务7:用前试试,整个数据和标签对应下,看看对不对

利用iter.(train_loader).next()试试,是一个batch数据。suqeeze是压缩某个没用的维度,可有可无。permute是转换维度的,tensor是BGR格式,先转为RGB格式,再变为numpy格式,方便画图。

9、LSTM文本任务

文本数据标签文件。新闻主题分类,包含训练集、验证集、测试集。

9.1 文本任务数据预处理

Google认为英文文本适合分词,中文文本适合分字,我们以分字进行,这是第一步。第二部是ID替换,有一个大的预料表(包含5000个常用字),每个字对应一个ID序号,将每个字替换为序号,这样文本转换为一个数字组成的list。第三步是映射表,即就是Embedding,词嵌入,将这个list转换为一个词向量(这个向量是大型企业训练出的,如搜狗,腾讯)。综上所述,预料表将文本转换为ID,映射表将ID转换为向量。

相关推荐
不朽の燃梦6 分钟前
OpenCV基础(1)
人工智能·opencv·计算机视觉
studyForMokey7 分钟前
[Kotlin标准函数] run、with、apply、also、let、use等
前端·python·kotlin
前鼻音太阳熊14 分钟前
【数据结构和算法】-布隆过滤器
数据结构·算法
Star Patrick14 分钟前
算法训练(leetcode)二刷第二十五天 | *134. 加油站、*135. 分发糖果、860. 柠檬水找零、*406. 根据身高重建队列
python·算法·leetcode
蓝天星空14 分钟前
tensorflow有哪些具体影响,和chatgpt有什么关系
人工智能
南宫生15 分钟前
力扣-Hot100-链表其一【算法学习day.34】
java·学习·算法·leetcode·链表
罔闻_spider15 分钟前
递归(二)---力扣22括号生成,力扣78求子集
开发语言·python
若石之上16 分钟前
DeepSpeed:PyTorch优化库,使模型分布式训练能高效使用内存和更快速
pytorch·内存·gpu·deepspeed·速度·zero
数据媛18 分钟前
TensorFlow_T7 咖啡豆识别
人工智能·python·深度学习·机器学习·tensorflow
亮~23 分钟前
力扣(leetcode)面试经典150题——27. 移除元素
算法·leetcode·面试