1.torch.autograd
Autograd是python中的自动求导库
PyTorch 作为一个深度学习平台,在深度学习任务中比 NumPy 这个科学计算库强在哪里呢?一是 PyTorch 提供了自动求导机制,二是对 GPU 的支持。由此可见,自动求导 (autograd) 是 PyTorch,乃至其他大部分深度学习框架中的重要组成部分。
2.torch.optim
转自知乎:
https://zhuanlan.zhihu.com/p/349072157
torch.optim模块中,包含了大部分现在已有的流行的优化方法。
使用:
optimizer = optim.Adam(model.parameters())
创建一个optimizer对象,这个对象会保存当前的状态,并根据梯度更新参数。
作用:
根据网络反向传播的梯度信息来更新网络的参数,以起到降低loss函数计算值,
从优化器的作用出发,要使得优化器能够起作用,需要两个主要东西:
(1)优化器需要知道当前使用的是什么模型的参数空间。因此在训练文件中,正式开始训练前,需要把网络的参数放到优化器中。比如:optimizer = optim.Adam(model.parameters())。
(2)需要知道反向传播的梯度信息。
使用流程:
首先,在创建优化器对象的时候,要传入网络模型的参数,并设置学习率等优化方法的参数。然后使用函数zero_grad将梯度置为零。接着调用函数backward来进行反向传播计算梯度。最后使用优化器的step函数来更新参数。
optimizer = optim.Adam(model.parameters())
for epoch in range(num_epoches):
train_loss=0
for step,(seq, label) in enumerate(data_loader):
# 损失函数
loss = criterion(model(seq), label.to(device))
# 将梯度清零
opimizer.zero_grad()
# 损失函数backward进行反向传播梯度的计算
loss.backward()
train_loss += loss.item()
# 使用优化器的step函数来更新参数
optimizer.step()
优化算法主要分为两大类:
(1)SGD及其改进(加Momentum)
(2)逐参数适应学习率方法,包括AdaGrad,RMSProp,Adam等
3.torch.optim.adam优化算法
参数:
class Adam(Optimizer):
#Implements Adam algorithm.
def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8,
weight_decay=0, amsgrad=False):
params(iterable)待优化参数的iterable或者是定义了参数组的dict
lr (float,可选):学习率(步长因子),默认le-3=0.001,控制了权重的更新比率.较大的值(如0.3)在学习率更新前会有更快地初始学习,而较小的值如le-5会令训练收敛到更好的性能。
betas=[beta1,beta2],可选:用于计算梯度以及梯度平方的运行平均值的系数,默认为[0.9,0.999],beta1是一阶矩阵的指数衰减率,beta2是二阶矩阵的指数衰减率,该超参数在稀疏梯度(如在NLP或计算机视觉任务中)应该设置为接近1的数。
eps,epsion:该参数是非常小的数,为了增加数值计算的稳定性而加到分母里的项,默认le-8,为了防止在实现中除以零;
weight_decay,可选:权重衰减,L2乘法,默认0
特点:
1、结合了adagrad善于处理稀疏梯度和RMSprop善于处理非平稳目标的优点;
2、对内存需求较小
3、为不同的参数计算不同的自适应学习率
4、也适用于大多非凸优化–适用于大数据集和高维空间。
4.torch.nn.Conv2d()
5.torchvision.transforms
是pytorch中的图像预处理包(图像变换),一般用Compose把多个步骤整合到一起。
6.torch.nn
Pytorch提供了几个设计得非常棒的模块和类,比如 torch.nn,torch.optim,Dataset 以及 DataLoader,来帮助程序员设计和训练神经网络。
nn是Neural Network的简称,帮助程序员方便执行如下的与神经网络相关的行为:
(1)创建神经网络
(2)训练神经网络
(3)保存神经网络
(4)恢复神经网络
7.torch.nn.functional
nn.functional概述
nn.functional定义了创建神经网络所需要的一些常见的处理函数。如没有激活函数的神经元,各种激活函数等。
nn.functional函数分类
nn.functional包括神经网络前向和后向处理所需要到的常见函数。
(1)神经元处理函数
(2)激活函数
激活函数的案例
(1)relu案例
# nn.functional.relu( )
print(y_output)
out = nn.functional.relu(y_output)
print(out.shape)
print(out)
(2)sigmoid案例
# nn.functional.sigmoid( )
print(y_output)
out = nn.functional.sigmoid(y_output)
print(out.shape)
print(out)
8.nn.Conv2d()
二维卷积应该是最常用的卷积方式了,在Pytorch的nn模块中,封装了nn.Conv2d()类作为二维卷积的实现。使用方法和普通的类一样,先实例化再使用。下面是一个只有一层二维卷积的神经网络,作为nn.Conv2d()方法的使用简介:
class Net(nn.Module):
def __init__(self):
nn.Module.__init__(self)
self.conv2d = nn.Conv2d(in_channels=3,out_channels=64,kernel_size=4,stride=2,padding=1)
def forward(self, x):
print(x.requires_grad)
x = self.conv2d(x)
return x
print(net.conv2d.weight)
print(net.conv2d.bias)
前三个参数是必须手动提供的,后面的有默认值。接下来将一一介绍:
in_channels
即输入张量的channels数。
out_channels
即期望的四维输出张量的channels数
kernel_size
卷积核的大小,一般我们会使用5x5、3x3这种左右两个数相同的卷积核,因此这种情况只需要写kernel_size = 5这样的就行了。如果左右两个数不同,比如3x5的卷积核,那么写作kernel_size = (3, 5),注意需要写一个tuple,而不能写一个列表(list)。
stride = 1
卷积核在图像窗口上每次平移的间隔,即所谓的步长。
padding = 0
Pytorch与Tensorflow在卷积层实现上最大的差别就在于padding上。
Padding即所谓的图像填充,后面的int型常数代表填充的多少(行数、列数),默认为0。需要注意的是这里的填充包括图像的上下左右,以padding = 1为例,若原始图像大小为32x32,那么padding后的图像大小就变成了34x34,而不是33x33。
Pytorch不同于Tensorflow的地方在于,Tensorflow提供的是padding的模式,比如same、valid,且不同模式对应了不同的输出图像尺寸计算公式。而Pytorch则需要手动输入padding的数量,当然,Pytorch这种实现好处就在于输出图像尺寸计算公式是唯一的。
dilation = 1
这个参数决定了是否采用空洞卷积,默认为1(不采用)。从中文上来讲,这个参数的意义从卷积核上的一个参数到另一个参数需要走过的距离,那当然默认是1了,毕竟不可能两个不同的参数占同一个地方吧(为0)。
groups = 1
决定了是否采用分组卷积
bias = True
即是否要添加偏置参数作为可学习参数的一个,默认为True。
padding_mode = ‘zeros’
即padding的模式,默认采用零填充。
9.nn.BatchNorm2d()
在卷积神经网络的卷积层之后总会添加BatchNorm2d进行数据的归一化处理,这使得数据在进行Relu之前不会因为数据过大而导致网络性能的不稳定,BatchNorm2d()函数数学原理如下:
BatchNorm2d()内部的参数如下:
1.num_features:一般输入参数为batch_sizenum_featuresheight*width,即为其中特征的数量
2.eps:分母中添加的一个值,目的是为了计算的稳定性,默认为:1e-5
3.momentum:一个用于运行过程中均值和方差的一个估计参数(我的理解是一个稳定系数,类似于SGD中的momentum的系数
4.affine:当设为true时,会给定可以学习的系数矩阵gamma和beta
10.PyTorch的nn.Linear()
PyTorch的nn.Linear()是用于设置网络中的全连接层的,需要注意在二维图像处理的任务中,全连接层的输入与输出一般都设置为二维张量,形状通常为[batch_size, size],不同于卷积层要求输入输出是四维张量。其用法与形参说明如下:
in_features指的是输入的二维张量的大小,即输入的[batch_size, size]中的size。
out_features指的是输出的二维张量的大小,即输出的二维张量的形状为[batch_size,output_size],当然,它也代表了该全连接层的神经元个数。
从输入输出的张量的shape角度来理解,相当于一个输入为[batch_size, in_features]的张量变换成了[batch_size, out_features]的输出张量。
用法示例:
import torch as t
from torch import nn
# in_features由输入张量的形状决定,out_features则决定了输出张量的形状
connected_layer = nn.Linear(in_features = 64*64*3, out_features = 1)
# 假定输入的图像形状为[64,64,3]
input = t.randn(1,64,64,3)
# 将四维张量转换为二维张量之后,才能作为全连接层的输入
input = input.view(1,64*64*3)
print(input.shape)
output = connected_layer(input) # 调用全连接层
print(output.shape)
这段代码运行结果为:
input shape is %s torch.Size([1, 12288])
output shape is %s torch.Size([1, 1])
11.nn.MSELoss()
MSE是mean squared error的缩写,即平均平方误差,简称均方误差。
MSE是逐元素计算的,计算公式为:
旧版的nn.MSELoss()函数有reduce、size_average两个参数,新版的只有一个reduction参数了,功能是一样的。
12.torch.unsqueeze()
转自知乎:https://zhuanlan.zhihu.com/p/86763381
torch.unsqueeze(input, dim, out=None)
作用:扩展维度
返回一个新的张量,对输入的既定位置插入维度 1
注意: 返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。
如果dim为负,则将会被转化dim+input.dim()+1
参数:
tensor (Tensor) – 输入张量
dim (int) – 插入维度的索引
out (Tensor, optional) – 结果张量
import torch
x = torch.Tensor([1, 2, 3, 4]) # torch.Tensor是默认的tensor类型(torch.FlaotTensor)的简称。
print('-' * 50)
print(x) # tensor([1., 2., 3., 4.])
print(x.size()) # torch.Size([4])
print(x.dim()) # 1
print(x.numpy()) # [1. 2. 3. 4.]
print('-' * 50)
print(torch.unsqueeze(x, 0)) # tensor([[1., 2., 3., 4.]])
print(torch.unsqueeze(x, 0).size()) # torch.Size([1, 4])
print(torch.unsqueeze(x, 0).dim()) # 2
print(torch.unsqueeze(x, 0).numpy()) # [[1. 2. 3. 4.]]
print('-' * 50)
print(torch.unsqueeze(x, 1))
# tensor([[1.],
# [2.],
# [3.],
# [4.]])
print(torch.unsqueeze(x, 1).size()) # torch.Size([4, 1])
print(torch.unsqueeze(x, 1).dim()) # 2
print('-' * 50)
print(torch.unsqueeze(x, -1))
# tensor([[1.],
# [2.],
# [3.],
# [4.]])
print(torch.unsqueeze(x, -1).size()) # torch.Size([4, 1])
print(torch.unsqueeze(x, -1).dim()) # 2
print('-' * 50)
print(torch.unsqueeze(x, -2)) # tensor([[1., 2., 3., 4.]])
print(torch.unsqueeze(x, -2).size()) # torch.Size([1, 4])
print(torch.unsqueeze(x, -2).dim()) # 2
# 边界测试
# 说明:A dim value within the range [-input.dim() - 1, input.dim() + 1) (左闭右开)can be used.
# print('-' * 50)
# print(torch.unsqueeze(x, -3))
# IndexError: Dimension out of range (expected to be in range of [-2, 1], but got -3)
# print('-' * 50)
# print(torch.unsqueeze(x, 2))
# IndexError: Dimension out of range (expected to be in range of [-2, 1], but got 2)
# 为何取值范围要如此设计呢?
# 原因:方便操作
# 0(-2)-行扩展
# 1(-1)-列扩展
# 正向:我们在0,1位置上扩展
# 逆向:我们在-2,-1位置上扩展
# 维度扩展:1维->2维,2维->3维,...,n维->n+1维
# 维度降低:n维->n-1维,n-1维->n-2维,...,2维->1维
# 以 1维->2维 为例,
# 从【正向】的角度思考:
# torch.Size([4])
# 最初的 tensor([1., 2., 3., 4.]) 是 1维,我们想让它扩展成 2维,那么,可以有两种扩展方式:
# 一种是:扩展成 1行4列 ,即 tensor([[1., 2., 3., 4.]])
# 针对第一种,扩展成 [1, 4]的形式,那么,在 dim=0 的位置上添加 1
# 另一种是:扩展成 4行1列,即
# tensor([[1.],
# [2.],
# [3.],
# [4.]])
# 针对第二种,扩展成 [4, 1]的形式,那么,在dim=1的位置上添加 1
# 从【逆向】的角度思考:
# 原则:一般情况下, "-1" 是代表的是【最后一个元素】
# 在上述的原则下,
# 扩展成[1, 4]的形式,就变成了,在 dim=-2 的的位置上添加 1
# 扩展成[4, 1]的形式,就变成了,在 dim=-1 的的位置上添加 1
13.permute(dims)
将tensor的维度换位。
参数: - dims (int …*) - 换位顺序
x = torch.randn(2, 3, 5)
x.size()
torch.Size([2, 3, 5])
x.permute(2, 0, 1).size()
torch.Size([5, 2, 3])
14.np.random.uniform()
np.random.uniform()作用于从一个均匀分布的区域中随机采样。
np.random.uniform(low, high ,size)
其形成的均匀分布区域为[low, high)
1.low:采样区域的下界,float类型,默认值为0
2.high:采样区域的上界,float类型,默认值为1
3.size:输出样本的数目(int类型或者tuple类型)
4.返回对象:ndarray类型,形状和size中的数值一样
自动调节上下界了,可以前一个数大于后一个数!
np.random.uniform(1.75, 1, 100000000)
#输出结果
array([1.25930467, 1.40160844, 1.53509096, ..., 1.57271193, 1.25317863,
1.62040797])
15.torch.from_numpy()
简单说一下,就是torch.from_numpy()方法把数组转换成张量,且二者共享内存,对张量进行修改比如重新赋值,那么原始数组也会相应发生改变。
>>> a = numpy.array([1, 2, 3])
>>> t = torch.from_numpy(a)
>>> t
tensor([ 1, 2, 3])
>>> t[0] = -1
>>> a
array([-1, 2, 3])