基础知识部分
1.张量数据类型
对张量的概述:
数学中有标量、向量和矩阵的概念,它们的维度分别是0、1、2。也就是说,标量中元素的位置固定,向量中元素的位置需要通过其索引确定,矩阵中的元素位置需要通过其行号和列号确定。张量可以视为矩阵的扩展,可以用于表示无穷维度的数据。
张量(Tensor)是Pytorch库中的基本数据类型,Pytorch中各种基本数字类型都有其对应的Tensor类型,但是在Pytorch中没有内嵌的字符串类型。
1.1.常用的张量数据类型
常用的Pytorch数值型数据类型:
- torch.FloatTensor(单精度浮点型);
- torch.DoubleTensor(双精度浮点型);
- torch.IntTensor(基本整型);
- torch.LongTensor(长整型);
- torch.ByteTensor(字节整型)。
由于Pytorch库中没有布尔类型,因此常常使用字节整型张量来表示布尔值。
上面的类型都是针对CPU而言的,对于在GPU上的数据类型,还需要添加一个cuda,也就是下面这些形式:
- torch.cuda.FloatTensor(GPU单精度浮点型);
- torch.cuda.DoubleTensor(GPU双精度浮点型);
- torch.cuda.IntTensor(GPU基本整型);
- torch.cuda.LongTensor(GPU长整型);
- torch.cuda.ByteTensor(GPU字节整型)。
将一个普通张量类型转化为GPU张量类型的方法:普通张量变量名.cuda()
。该函数返回一个GPU张量的引用。
查看张量数据类型的方法:直接使用Python自带的type函数查看Tensor的具体类型是不行的,这样返回的类型值始终是“torch.Tensor"。因此需要使用到下面的两种方法。
- type方法:使用
张量名.type()
的方式可以查看张量的具体类型。 - isinstance函数:isinstance函数是Python的自带函数,其使用语法为
isinstance(张量名,类型名)
,返回值是一个布尔值。譬如下面的这个例子:
isinstance(torch.randn(2,3),torch.FloatTensor)
1.2.张量的属性获取
张量的形状确定:
- 属性确定:可以使用张量的shape属性确定张量的形状;
- 方法确定:可以使用张量的size()方法确定张量的形状。
张量占用内存的大小确定:张量名.numel()
。
张量的维度确定:张量名.dim()
。
1.3.将其他数据类型转换为张量
将不同类型的数据转化为张量:可以通过已有的单个数值、Python列表、Numpy数组等方式来生成张量。也可以先不指定所生成的张量的元素值,而只生成指定元素个数的张量。
- 标量(零维张量)的生成方法:
torch.tensor(标量值)
。标量也就是一个数字。 - 将Python一维列表转换为张量:
torch.tensor(一维列表)
- 生成元素个数和元素类型指定的一维张量的方法:
torch.FloatTensor(数据个数)
。所生成的张量中的全部元素都是零。 - 将Numpy数组转换为张量:
torch.from_numpy(numpy数组)
。
备注1:可以通过使用Python的list()函数将张量转化为Python列表。
备注2:tensor函数的接收参数只能是标量值、Python列表或Numpy数组;带有元素数据类型的大写Tensor函数(如FloatTensor)可以接收上面这三种数据类型作为参数,也可以接收一个表示生成张量的形状的列表(或标量)。由于直接使用tensor函数更加容易,因此更推荐只使用tensor函数。
1.4.生成满足条件的张量
设置所有生成的张量的默认元素类型:torch.set_default_tensor_type(类型名)
。Pytorch的默认张量类型是torch.FloatTensor。增强学习中使用DoubleTensor的使用会更多。
生成指定形状的随机张量:
- 生成不经过元素初始化的指定形状的张量:
torch.empty(维度1长度,维度2长度...)
。
备注:不推荐使用empty函数来生成张量,因为如果忘记对张量中的元素进行初始化则可能产生相当麻烦的错误。
- 生成元素服从0到1均匀分布的指定形状的张量:
torch.rand(维度1长度,维度2长度...)
。 - 生成与指定张量形状相同的元素服从0到1均匀分布的张量:
torch.rand_like(张量名)
。 - 生成元素为指定区间均匀分布整数的指定形状的张量:
torch.randint(最小值,最大值,形状列表)
。注意该区间不包括右端点(最大值)。 - 生成元素服从标准正态分布的指定形状的张量:
torch.randn(维度1长度,维度2长度...)
。 - 生成元素服从指定均值和标准差的正态分布的一维张量:
torch.normal(表示均值的一维张量,表示标准差的一维张量)
。
备注:randn方法和normal方法在返回值上的最大区别在于,normal方法返回的仍然是一个一维张量,如果想要得到其他形状和维度的张量,则需要对张量进行维度变换。
- 生成全部元素为1的指定形状的张量:
torch.ones(形状元组)
。 - 生成全部元素为0的指定形状的张量:
torch.zeros(形状元组)
。 - 生成指定填充值的指定形状的张量:
torch.full(形状列表,填充值)
。 - 生成元素满足对角矩阵的指定形状的张量:
torch.eye(行数,列数)
。
生成等差张量和等比张量(一维):
- 生成指定区间和步长的等差张量:
torch.arange(起始值,终止值,steps=步长)
。生成数字的区间不包括终止值。 - 生成指定区间和元素个数的等差张量:
torch.linspace(起始值,终止值,steps=生成元素个数)
。同样,生成的数字的区间不包括终止值。 - 生成指定区间和指定元素个数的十对数张量:
torch.logspace(起始值,终止值,steps=元素个数)
。生成的每一个元素都是对当前值求log10对数的结果。
生成随机打散的整数张量:
tensor.randperm(n)
:返回一个含有n个元素的一维张量,张量中的元素位置随机,但是都是从0到n-1之间的不重复的整数。
1.5.对张量进行索引和切片
- 对张量进行索引:
张量名[维度1,维度2...]
。 - 对张量进行切片:
张量名[维度1起始位置:维度1终止位置,维度2起始位置:维度2终止位置...]
。
备注:
①如果需要对整个维度进行切片,则直接使用冒号“:
”表示整个维度即可。
②切片区间是左闭右开的,也就是不包含终止位置的元素。
③和Python中的列表相同,张量的索引和切片也可以用负数形式的反向索引和切片。
④进行切片时还可以指定步长,其语法形式为起始位置:终止位置:步长
。
- 选择某一维度上指定位置的元素(对于一维张量):
张量名.index_select(维度,位置)
。注意位置需要用一个一维张量来进行表示。
# 取0维度上的1、5、6号对象
TestTensor.index_select(0,torch.tensor([1,5,6]))
- 从多维张量中选择所有指定位置的元素:
masked_select 是 Pytorch 库中的一个函数,可以用来从输入张量中按照给定的掩码(mask)选取元素。掩码是一个布尔类型的张量,其形状和输入张量相同,掩码中每个元素的值决定了是否选取输入张量中对应位置的元素。
masked_select(input, mask)
函数接受两个参数:
input:要从中选取元素的输入张量,可以是任意形状的张量。
mask:用来控制选取哪些元素的掩码,必须是一个形状和 input 相同的布尔类型张量。
函数返回一个一维张量,其中包含了所有符合条件的元素。
以下是一个示例:
import torch
# 创建一个 2x3 的张量
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
# 创建一个与 x 相同形状的掩码
mask = torch.tensor([[True, False, True], [False, True, False]])
# 使用掩码从 x 中选取符合条件的元素
result = torch.masked_select(x, mask)
print(result) # 输出 tensor([1, 3, 5])
1.6.对张量进行维度变换
注意事项:对张量进行维度变换并不改变张量本身的存储方式,只是对原本存储的内容换了一种方法进行解释。
- 对张量进行数据量不变的维度变换:
张量名.reshape(新维度1,新维度2...)
。
备注:使用reshape操作一定要确保变换前后的张量具有相同数量的元素。同时,使用reshape操作会使得原始张量的维度信息丢失,因此使用时一定要谨慎。
- 在张量中插入新的维度:
张量名.unsqueeze(插入索引)
。插入索引表示在当前哪一个维度的索引前插入新的维度。索引可以用正向索引和可以用负向索引,但是不建议负向索引,因为容易混淆。 - 对张量的维度进行删减:
张量名.squeeze(删除位置索引)
。删除位置表示删除哪一个维度的索引。只有长度为1的维度才能进行挤压,否则原始张量不会发生变化。 - 对张量形状进行扩展:
张量名.expand(维度1长度,维度2长度...)
。使用此方法要求扩展前后的张量的维度必须相同,同时原来被扩张的各个维度的大小都必须为1。expand方法执行速度快,但是并不会对扩展部分的数据进行初始化,因此需要程序员对扩展部分的数据进行手动初始化。 - 对张量形状进行扩展的另一种方法:
张量名.repeat(维度1拷贝次数,维度2拷贝次数...)
。和expand方法不同的是,repeat方法在进行形状扩展的同时还会进行数据的复制过程,因此其相应地也比expand执行速率更低。 - 对二维张量(矩阵)进行转置:
二维张量名.t()
。 - 交换张量中的两个维度:
张量名.transpose(维度1,维度2)
。 - 对张量进行维度重排:transpose方法一次只能交换两个维度,如果需要对整个张量进行维度重排,就需要使用到permute方法。permute方法的语法如下:
output_tensor = input_tensor.permute(*dims)
其中,input_tensor是要进行维度重排的张量,dims是一个整数序列,表示新的维度顺序。*dims表示将序列解包成独立的参数。output_tensor是维度重排后得到的新张量。
例如,假设有一个大小为(3, 4, 5)的张量x,要将维度顺序变为(4, 5, 3),可以使用如下代码:
import torch
x = torch.randn(3, 4, 5)
y = x.permute(1, 2, 0)
在某些情况下,Pytorch 要求 tensor 的数据必须是连续的,否则会抛出运行时错误。这种情况通常涉及到 tensor 之间的操作,如矩阵乘法等。当 tensor 不是连续的时候,我们可以使用 contiguous() 函数来将其转换为连续的 tensor。
将张量进行连续存储:张量名.contiguous()
。
1.7.Broadcasting机制解析
broadcasting机制的作用:在 Pytorch 中,broadcasting 是一种自动扩展张量形状的机制,使得不同形状的张量可以进行算术运算。其实现方式是在需要进行运算的张量上自动添加维度,使其形状能够匹配另一个张量的形状。
Broadcasting机制是如何进行的:如果两个张量在某个维度上的形状不同,而这个维度的长度为 1,那么 Pytorch 会自动地沿着这个维度进行复制,使得两个张量在这个维度上的长度相同,从而能够进行算术运算。这个过程会一直持续到两个张量在所有维度上的形状都相同为止。
例如,如果有一个形状为 (3, 1) 的张量 a 和一个形状为 (1, 4) 的张量 b,那么在对它们进行加法运算时,PyTorch 会自动地将它们扩展为形状分别为 (3, 4) 的张量,然后进行加法运算。
这种自动扩展张量形状的机制可以大大简化代码的书写,提高程序的可读性和可维护性。但是在使用时,需要注意张量形状的匹配关系,以免出现意外的错误。
1.8.对张量的拼接和拆分
- 对多个张量进行拼接:
torch.cat([张量1,张量2...],dim=拼接维度下标)
。使用该函数要求所拼接的张量除了需要进行拼接的维度的值不同外,维度相同且其他维度的数值都相同。 - 将两个张量在一个更高的维度进行拼接:
torch.stack([张量1,张量2...],dim=新创建维度)
。要求进行拼接的两个张量的形状必须完全相同。 - 将一个张量在指定维度上拆分为多个长度指定的张量:
torch.split([张量1长度,张量2长度...],dim=被拆分的维度)
。被拆分得到的多个张量以一个元组的形式作为返回值返回。 - 将一个张量在指定维度上拆分为指定个数的张量:
torch.chunk(拆分个数,dim=被拆分的维度)
。
1.9.张量的数学运算
- 可以直接使用加减乘除运算符对两个张量对应位置的元素进行运算,但是两个操作数需要满足张量运算的规则。
四则运算函数:除了直接使用运算符外,也可以使用对应的函数进行运算。加减乘除的对应函数分别为torch.add()、torch.sub()、torch.mul()、torch.div(),传入的参数是进行运算的两个张量。
- 对两个二维张量进行矩阵相乘:
torch.matmul(张量1,张量2)
。这个函数也可以对更高维度的张量进行运算,具体结果形式此处不再解释。
备注:在pytorch中,运算符@也是表示两个矩阵相乘。
- 对张量的元素进行幂运算:
张量名.pow(次数)
。 - 对张量的元素进行开方运算:
张量名.sqrt()
。 - 对张量的元素进行自然指数运算:
torch.exp(张量名)
。具体来说,就是以张量的元素为指数,求出自然对数e的幂。 - 对张量的元素求自然对数:
torch.log(张量名)
。如果需要以2为底数或以10为底数,可以分别使用torch.log2()和torch.log10()两个函数。 - 对张量的元素进行向下/向上取整:
张量名.ceil()
/张量名.floor()
。 - 对张量的元素进行四舍五入:
张量名.round()
。 - 裁剪出张量的整数部分和小数部分:
张量名.trunc()
/张量名.frac()
。 - 设置张量元素的取值区间:
张量名.clamp(最小值,最大值)
。使用该函数后,张量中本来比最小值还要小的元素将被修改为最小值,比最大值还要大的元素将被修改为最大值。
1.10.张量的布尔值运算
- 判断是否张量中的所有元素都是True:
torch.all(张量名)
。该函数返回一个零维张量,如果元素为1表示所有元素都是True,否则返回0。 - 判断两个形状相同的张量的对应元素是否相等:
torch.eq(张量1,张量2)
。该函数返回一个布尔类型的张量。 - 判断第一个张量中的元素是否大于等于第二个张量中的对应元素:
torch.ge(张量1,张量2)
。 - 判断第一个张量中的元素是否大于第二个张量中的对应元素:
torch.gt(张量1,张量2)
。 - 判断第一个张量中的元素是否小于等于第二个张量中的对应元素:
torch.le(张量1,张量2)
。 - 判断第一个张量中的元素是否小于第二个张量中的对应元素:
torch.lt(张量1,张量2)
。
1.11.张量的统计值计算
- 求张量的指定阶数的范数:
张量名.norm(范数阶数,dim=需要求范数的维度)
。 - 求张量的最大值/最小值:
张量名.max(dim=需要求最大值的维度)
和张量名.min(dim=需要求最小值的维度)
。
keepdim参数:对于max函数和min函数,有一个可选参数keepdim,该参数是一个布尔值。如果为了保留原始的维度信息,就可以将该keepdim参数设置为True。
- 求张量的平均值:
张量名.mean()
。 - 求张量的累加结果或累乘结果:
张量名.sum()
和张量名.prod()
。 - 求张量的最大值或最小值的索引:
张量名.argmax(dim=求解维度)
和张量名.argmin(dim=求解维度)
。 - 求张量中最大/小的前K个元素:
张量名.topk(元素个数,dim=求最值的维度,largest=最大/最小)
。largest为True表示求最大的几个元素;largest为False表示求最小的几个元素。该方法会返回两个张量,第一个张量表示最大或最小的元素,第二个张量表示这些元素各自的索引。 - 求张量中第K小的元素:
张量名.kthvalue(K,dim=求最值的维度)
。该方法也会像topk方法一样返回两个张量。
1.12.where函数和gather函数
where函数的使用方法:
在 Pytorch 中,torch.where() 函数的作用是根据条件选择输入张量的元素,并返回一个新的张量。
函数的使用方法如下:
torch.where(condition, x, y)
其中,condition 是一个布尔类型的张量,x 和 y 分别是两个张量,它们的形状可以不相同,但是必须有相同的维度。函数返回一个新的张量,其形状与 condition 张量相同,其元素根据 condition 张量中的值选择自 x 或 y 中的相应元素。
具体地说,当 condition[i] 为 True 时,新张量的第 i 个元素将等于 x[i],否则为 y[i]。
下面是一个简单的示例,说明如何使用 torch.where() 函数:
import torch
x = torch.randn(3, 3)
y = torch.ones(3, 3)
result = torch.where(x > 0, x, y)
print(result)
在上面的例子中,我们首先创建了两个 3x3 的张量 x 和 y,其中 x 中的元素是随机的,y 中的元素都是 1。然后,我们使用 torch.where() 函数根据 x > 0 的条件选择 x 或 y 中的元素,将结果保存到 result 张量中,并打印输出。
gather函数的使用方法:
在 Pytorch 中,gather() 函数用于按索引从输入张量中收集元素,并将它们组成一个新的张量返回。
函数的使用方法如下:
torch.gather(input, dim, index, out=None)
其中,input 是输入张量,dim 是指定的维度,index 是索引张量,out 是输出张量(可选参数)。函数返回一个新的张量,其形状与 index 张量相同。
具体地说,对于 2D 张量 input,dim 可以是 0 或 1,分别表示在行或列上进行索引。而对于多维张量 input,dim 则可以是任意维度。
下面是一个简单的示例,说明如何使用 gather() 函数:
import torch
input = torch.tensor([[10, 20], [30, 40], [50, 60]])
index = torch.tensor([[0, 1], [1, 0], [0, 1]])
output = torch.gather(input, 1, index)
print(output)
在上面的例子中,我们首先创建了一个 3x2 的张量 input,其中包含了一些元素。然后,我们创建了一个与 input 相同大小的索引张量 index,用于按行收集元素。最后,我们使用 gather() 函数按行从 input 张量中收集元素,并将结果保存到 output 张量中,并打印输出。
输出结果为:
tensor([[10, 20],
[40, 30],
[50, 60]])
可以看到,输出张量中的每个元素都是从 input 张量中按照相应的索引收集而来的。例如,第一个元素 10 是来自 input[0, 0],第二个元素 20 是来自 input[0, 1],以此类推。
2.深度学习的基础内容
2.1.激活函数
- Sigmoid激活函数值:
torch.sigmoid(张量名)
。该方法可以对输入张量中的每一个元素求出其对应的Sigmoid函数值。 - Tanh激活函数值:
torch.tanh(张量名)
。这是一种在RNN中常使用的激活函数。该函数可以对输入张量中的每一个元素求出其对应的Tanh函数值。 - Relu激活函数值:
torch.relu(张量名)
。这是目前深度学习中最热门的激活函数,因为这个函数的形式难以出现梯度离散和梯度爆炸的情况。 - Softmax激活函数值:
torch.nn.functional.softmax(输入张量,dim=运算维度)
。该激活函数适用于多分类问题,常常与交叉熵搭配使用。Softmax激活函数的优秀性质在于其可以用于表示分类的概率。这种激活函数会把本身很大的数值的相对大小进一步放大,对原先数值较小的数值的相对大小进一步压缩。 - LeakyRelu函数值:
torch.nn.LeakyRelu(输入张量,dim=运算维度)
。这种激活函数是对Relu激活函数的优化,使得当自变量取值为负数时函数值并非直接取零,而是取一个线性的非常小的负数。这个函数相较于Relu函数可以更好地避免梯度离散现象。
备注:对Relu函数的优化另外还有Selu函数和SoftPlus函数,但是这些函数相较于LeakyRelu函数使用较少。
2.2.损失函数
- 求解均方误差:
torch.nn.functional.mse_loss(表示预测值的张量,表示实际标签值的张量)
。函数的返回值也是一个张量。
2.3.张量的梯度计算
autograd.grad函数的使用方法:
在PyTorch中,autograd.grad函数用于计算张量的梯度,可以用于自定义损失函数、计算梯度等任务。
autograd.grad函数的基本用法如下:
import torch
x = torch.tensor([3.0], requires_grad=True)
y = x ** 2 + 2 * x + 1
grads = torch.autograd.grad(y, x)
print(grads)
在上面的代码中,我们首先定义了一个张量x,将requires_grad参数设置为True,这意味着我们将跟踪计算与x相关的梯度信息。然后我们定义了一个表达式y,该表达式是x的平方加上2乘以x再加1。
接下来,我们使用autograd.grad函数计算表达式y关于x的梯度。autograd.grad函数的第一个参数是计算梯度的张量,第二个参数是需要求导的张量。函数返回一个元组,包含了求导张量的梯度。
在本例中,我们将求导张量设置为x,因此grads变量将包含表达式y关于x的梯度,即6.0。
需要注意的是,当使用autograd.grad计算梯度时,需要将相关张量的requires_grad属性设置为True,以启用自动微分功能。
backward方法的具体使用:
在PyTorch中,backward方法用于计算张量的梯度并更新模型参数,是自动微分的核心方法。backward方法的基本用法如下:
import torch
# 定义模型和损失函数
model = torch.nn.Linear(1, 1)
loss_fn = torch.nn.MSELoss()
# 定义输入和真实值
x = torch.tensor([[1.0], [2.0], [3.0], [4.0]])
y_true = torch.tensor([[2.0], [4.0], [6.0], [8.0]])
# 前向传播
y_pred = model(x)
# 计算损失
loss = loss_fn(y_pred, y_true)
# 反向传播
loss.backward()
# 更新模型参数
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
optimizer.step()
在上面的代码中,我们首先定义了一个包含单个线性层的模型和一个均方误差损失函数。然后,我们定义了输入张量x和真实值张量y_true。接下来,我们使用模型对输入进行前向传播,计算预测值y_pred,并计算预测值与真实值之间的损失。然后,我们调用backward方法计算损失关于模型参数的梯度。最后,我们定义了一个优化器(这里使用随机梯度下降),并调用step方法更新模型参数。
需要注意的是,在调用backward方法之前,需要将损失张量对应的图节点(通常是模型输出)的requires_grad属性设置为True,以启用自动微分功能。此外,在调用backward方法之前,需要清除之前的梯度信息,可以使用optimizer.zero_grad()
方法或手动清除梯度。如果不清除之前的梯度信息,则可能会导致梯度计算错误。
总之,backward方法是Pytorch中实现自动微分的重要方法之一。它可以方便地计算张量的梯度,并通过反向传播更新模型参数,实现神经网络的训练。
2.4.使用GPU加速计算
下面是使用PyTorch进行GPU加速计算的一些基本步骤:
- 检查是否有可用的GPU设备:在PyTorch中,可以使用
torch.cuda.is_available()
函数检查系统中是否有可用的GPU设备。如果返回True,则表示有可用的GPU设备。 - 将模型和数据移动到GPU上:在PyTorch中,可以使用
.to()
方法将模型和数据移动到GPU上。例如:
import torch
# 检查是否有可用的GPU设备
if torch.cuda.is_available():
device = torch.device('cuda')
else:
device = torch.device('cpu')
# 定义一个模型
model = MyModel()
# 将模型移动到GPU上
model.to(device)
# 加载数据
data = DataLoader(...)
# 将数据移动到GPU上
data = data.to(device)
- 使用GPU进行计算:在PyTorch中,可以通过在需要进行计算的张量上使用.cuda()方法将计算移动到GPU上。例如:
# 计算模型输出
output = model(input.cuda())
需要注意的是,在计算完成后,结果需要使用.cpu()方法将数据移动回CPU上进行处理。例如:
# 将结果移动回CPU上
output = output.cpu()
备注:使用GPU进行计算可以大大提高深度学习模型的训练和推理速度。但是,需要注意的是,在GPU上进行计算会消耗大量的显存,因此需要根据具体情况调整batch size等参数,以避免出现内存不足的问题。
2.5.测试模型时关闭梯度计算
在 PyTorch 中,with torch.no_grad()
是一种常见的使用 with 的方式,用于关闭梯度计算,以提高前向传播的速度。
在测试模型时,我们通常只需要计算模型的输出,而不需要计算梯度,因此可以使用 with torch.no_grad() 来关闭梯度计算。
重要:使用Pytorch进行深度学习的一般步骤
Torchvision部分
torchvision是PyTorch的一个官方包,它提供了一些用于计算机视觉任务的工具和函数,包括数据集加载、图像预处理、模型定义、模型训练、模型评估等。
torchvision包含以下模块:
- datasets:用于加载常见的计算机视觉数据集,例如CIFAR、MNIST、ImageNet等。
- transforms:用于数据预处理和数据增强,例如图像缩放、剪裁、旋转、翻转等。
- models:包含一些常用的计算机视觉模型,例如VGG、ResNet、DenseNet等。
- utils:包含一些实用函数,例如计算图像分类的准确率、可视化特征图等。
通过使用torchvision,我们可以更加便捷地进行计算机视觉任务的开发和实验,同时也可以快速地搭建和训练基于深度学习的视觉模型。
3.Pytorch中自带的图像数据集(torchvision.datasets)
简单介绍:torchvision.datasets是PyTorch中的一个模块,它包含了一些常见的计算机视觉数据集,可以方便地用于模型训练和测试。这些数据集通常被用于图像分类、目标检测、图像分割等计算机视觉任务的研究和实验中。
torchvision.datasets中的数据集:
- CIFAR:CIFAR-10和CIFAR-100是两个小型图像分类数据集,每个数据集包含10或100个不同类别的32x32 RGB图像。
- MNIST:MNIST是一个手写数字识别数据集,包含60000个训练图像和10000个测试图像,每个图像大小为28x28像素。
- Fashion-MNIST:Fashion-MNIST是一个类似于MNIST的数据集,但它包含了10个不同种类的时装图像,用于图像分类任务的研究。
- COCO:COCO是一个大型目标检测、分割和人体姿态估计数据集,包含超过330K张图像和250K个实例。
- ImageNet:ImageNet是一个大型图像分类数据集,包含1000个类别,每个类别有大约1000个图像。该数据集已成为深度学习模型训练的标准基准数据集。
- VOC:PASCAL VOC是一个经典的图像识别数据集,包含20个物体类别和大约5000个标注的图像,常用于目标检测和图像分割任务的研究。
这些数据集的使用非常简单,可以通过torchvision.datasets模块中的Dataset类来加载。可以使用该模块中的一些辅助函数来对数据进行预处理,并将其转换为PyTorch中的张量形式,以供模型使用。
导入datasets中的指定数据集的语法:以导入CIFAR10数据集为例。
cifar10_train = CIFAR10(root='./data', train=True, download=True, transform=None)
- root:指定数据集的根目录,数据集会被存储在该目录下。
- train:指定是否加载训练集,如果为True,则加载训练集,否则加载测试集。
- download:指定是否从互联网上下载数据集,如果为True,则从互联网上下载数据集,否则不下载数据集。
- transform:指定数据集的预处理方式,可以使用torchvision.transforms中的一些函数对数据进行预处理,例如图像缩放、裁剪、翻转、归一化等。如果不需要进行任何预处理,则将该参数设置为None。
查看数据集的大小:print(len(cifar10_train))
获取数据集中单个样本的内容和标签:image, label = cifar10_train[0]
指定训练集和测试集的样本个数:
from torchvision.datasets import CIFAR10
# 定义 CIFAR10 数据集,将训练集元素个数设置为 1000,测试集元素个数设置为 500
train_set = CIFAR10(root='./data', train=True, download=True, transform=None)
train_set.data = train_set.data[:1000]
train_set.targets = train_set.targets[:1000]
test_set = CIFAR10(root='./data', train=False, download=True, transform=None)
test_set.data = test_set.data[:500]
test_set.targets = test_set.targets[:500]
4.Pytorch中的图像预处理和数据增强(torchvision.transforms)
数据预处理器概述:Torchvision是一个在Pytorch中专门用于图像处理的包,其中包含了一系列的transforms类,用于对图像进行预处理或增强操作。数据预处理器就是一个transforms类对象。下面介绍一些常用的transform类及其功能。
具体使用时,需要先定义一个预处理器,在这个预处理器中根据实际需求设置预处理内容。
4.1.将其他数据类型转换为张量
ToTensor():该数据预处理器将PIL图像或numpy数组转换为Pytorch中的张量数据类型,同时将图像的像素值从0-255转换为0-1之间的浮点数。
4.2.对输入张量进行标准化
Normalize(): 该数据预处理器对张量进行标准化操作。可以通过传入mean和std参数来指定标准化的均值和标准差。这通常在训练和测试数据之间进行数据预处理时很有用。
备注:标准化可以让数据更加符合正态分布,有助于提高模型的训练效果。
4.3.图像的尺寸调整
Resize():该数据预处理器用于调整图像的尺寸大小。Resize()方法可以接受一个参数,指定调整后的目标大小,也可以接受一个参数元组,指定调整后的目标尺寸大小。
尺寸调整的必要性:在深度学习中,图像尺寸大小通常需要进行标准化处理,以便在模型训练时保持输入数据的一致性。例如,如果训练集中的图像大小不一致,需要使用Resize()方法将它们调整为相同的尺寸大小,以确保模型的输入张量具有相同的大小和形状。
使用例子:
# 定义Resize()函数,将图像的尺寸大小调整为指定大小
transform = transforms.Resize((224, 224))
4.4.对图像进行裁剪
图像裁剪的意义:在深度学习中,数据集通常需要在预处理过程中进行图像裁剪,以便在模型训练时保持输入数据的一致性。例如,在使用卷积神经网络(CNN)训练图像分类模型时,我们通常会将图像裁剪为相同的大小,以确保输入张量具有相同的大小和形状。
- 中心位置裁剪CenterCrop():
CenterCrop()
是torchvision.transforms模块中的一个函数,用于将图像从中心位置裁剪为指定大小。CenterCrop()方法可以接受一个参数,指定裁剪后的目标大小。
备注:需要注意的是,如果要使用CenterCrop()方法对数据集进行裁剪,通常需要先确定裁剪后的目标大小。通常情况下,目标大小可以根据模型的输入张量大小来确定。在实际应用中,可以根据模型的输入张量大小来选择合适的裁剪方法和目标大小,以确保模型的输入张量具有相同的大小和形状。
- 随机裁剪RandomCrop():torchvision.transforms模块中的一个函数,用于对图像进行随机裁剪。RandomCrop()方法可以接受一个参数,指定裁剪后的目标大小。
- 随机裁剪并缩放RandomResizedCrop():该类是torchvision.transforms中的一个数据增强方法,用于随机裁剪并缩放图片。其具体使用方法如下:
transforms.RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(0.75, 1.3333333333333333), interpolation=2)
其中:
size:输出图片的尺寸,可以是一个整数或者一个元组(height, width);
scale:随机裁剪的尺度,是一个元组(min, max),其中min和max分别为随机裁剪面积占原图面积的下限和上限,取值范围是0到1,默认值为(0.08,1.0);
ratio:随机裁剪的宽高比,是一个元组(min, max),其中min和max分别为随机裁剪的宽高比下限和上限,默认值为(0.75, 1.3333333333333333);
interpolation:插值方法,默认为PIL.Image.BILINEAR。
4.5.对图像进行翻转或旋转
意义分析:对图像进行翻转或旋转是一种常见的数据增强手段,因为它可以使数据更加丰富,增加模型对不同方向输入数据的适应能力。
- 图像随机水平翻转:
RandomHorizontalFlip
类是torchvision.transforms中的一个数据增强方法,用于对图像进行随机水平翻转。使用该函数的方法如下:其中,p参数是进行水平翻转的概率,它是一个在0到1之间的值,默认为0.5。
transforms.RandomHorizontalFlip(p=0.5)
- 图像随机垂直翻转:
RandomVerticalFlip
的作用是随机垂直翻转,其使用方法和RandomHorizontalFlip类似。 - 图像随机角度旋转:
RandomRotation
函数是torchvision.transforms中的一个数据增强方法,用于对图像进行随机旋转。具体来说,该函数会以给定的旋转角度范围内随机选择一个角度对输入图像进行旋转。旋转角度可以是一个数值,表示从0度到该值之间的随机角度;也可以是一个长度为2的元组,表示从第一个值到第二个值之间的随机角度。使用该函数的方法如下:
transforms.RandomRotation(degrees, resample=False, expand=False, center=None)
其中,degrees参数表示旋转角度的范围,可以是一个数值或者是一个元组。resample参数表示重采样方法,默认为False,即使用像素区域内的值进行插值;expand参数表示是否扩大图像,以便旋转后图像不被裁剪,默认为False;center参数表示旋转中心,默认为图像中心。
4.6.修改图像的亮度、对比度和饱和度
ColorJitter
函数是torchvision.transforms中的一个数据增强方法,用于对图像进行颜色扭曲操作,包括亮度、对比度、饱和度和色调的变化。
具体来说,该函数会以给定的参数随机调整输入图像的亮度、对比度、饱和度和色调,以产生具有差异化的训练样本。
使用该函数的方法如下:
transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0)
其中,brightness参数表示亮度调整的范围,可以是一个数值或者是一个长度为2的元组,表示从第一个值到第二个值之间的随机亮度变化;contrast参数表示对比度调整的范围,可以是一个数值或者是一个长度为2的元组,表示从第一个值到第二个值之间的随机对比度变化;saturation参数表示饱和度调整的范围,可以是一个数值或者是一个长度为2的元组,表示从第一个值到第二个值之间的随机饱和度变化;hue参数表示色相调整的范围,可以是一个数值或者是一个长度为2的元组,表示从第一个值到第二个值之间的随机色相变化。
示例代码:
import torchvision.transforms as transforms
transform = transforms.Compose([
transforms.ColorJitter(brightness=0.4, contrast=0.4, saturation=0.4, hue=0.1),
])
以上代码表示,对于输入的图像,会对其亮度、对比度、饱和度和色相进行随机的调整,亮度、对比度和饱和度的调整范围都是从0到0.4之间的随机变化,色相的调整范围是从-0.1到0.1之间的随机变化。
备注:需要注意的是,颜色抖动的范围不能太大,否则可能会导致图像失真或丢失重要信息。在选择范围时需要谨慎。
4.7.对图片进行仿射变换
RandomAffine
函数是torchvision.transforms中的一个数据增强方法,用于对输入图像进行随机仿射变换,包括平移、旋转、缩放、剪切等操作,从而扩充数据集。
使用该函数的方法如下:
transforms.RandomAffine(degrees, translate=None, scale=None, shear=None, resample=False, fillcolor=0)
其中,degrees表示随机旋转的角度范围,可以是一个数字或者是一个长度为2的元组,表示从第一个值到第二个值之间的随机角度变化;translate表示随机平移的范围,可以是一个长度为2的元组,表示横向和纵向平移的范围;scale表示随机缩放的范围,可以是一个长度为2的元组,表示横向和纵向缩放的范围;shear表示随机剪切的范围,可以是一个长度为2的元组,表示横向和纵向剪切的角度范围;resample表示是否使用重采样,如果为True则使用重采样,否则使用插值;fillcolor表示空白区域的填充颜色,默认为黑色。
示例代码:
import torchvision.transforms as transforms
transform = transforms.Compose([
transforms.RandomAffine(degrees=30, translate=(0.2, 0.2), scale=(0.8, 1.2), shear=10),
])
以上代码表示,对于输入的图像,会随机进行平移、缩放、剪切和旋转等仿射变换,平移的范围为图像宽度和高度的20%,缩放的范围为0.8到1.2之间的随机变化,剪切的角度范围为-10到10度之间的随机变化,旋转的角度范围为-30到30度之间的随机变化。
备注:仿射变换的范围也需要谨慎选择,否则可能会导致图像失真或丢失重要信息。在选择范围时需要根据具体应用场景进行调整。
4.8.将彩色图片转化为灰度图
RandomGrayscale
是torchvision.transforms中的一个数据增强方法,用于对输入图像进行随机灰度化处理,从而扩充数据集。
使用该函数的方法如下:
transforms.RandomGrayscale(p=0.1)
其中,p表示图像进行随机灰度化处理的概率,取值范围为0到1之间的浮点数。默认为0.1,表示有10%的概率对输入图像进行灰度化处理。
备注:灰度化处理会丢失彩色图像的信息,因此在某些任务中不适用。在使用时需要根据具体应用场景进行选择。
4.9.将数据转换为图像
transforms.ToPILImage
是torchvision.transforms中的一个转换函数,可以将张量或数组形式的图像转换为PIL格式的图像。
使用该函数的方法如下:
transforms.ToPILImage()(tensor_image)
其中,tensor_image表示要转换的张量或数组形式的图像,transforms.ToPILImage()将该图像转换为PIL格式的图像。
转换后的PIL图像与原始图像的大小、格式、通道数等属性可能会发生变化,具体变化取决于输入的张量或数组形式的图像的属性和转换函数的参数。因此,在使用transforms.ToPILImage函数时需要注意图像属性的变化。
备注:tensor_image的数据类型必须是torch.Tensor或numpy.ndarray类型。
4.10.不同处理方式的抽取和组合
transforms.RandomChoice
:它可以从给定的一组转换函数中随机选择一个进行数据增强。
使用该函数的方法如下:
transforms.RandomChoice([transform1, transform2, ...])(image)
其中,[transform1, transform2, …]表示一组转换函数,transforms.RandomChoice将从这组函数中随机选择一个进行数据增强,image表示要进行增强的图像。
transforms.RandomApply
:它可以以一定的概率随机应用给定的一组转换函数,用于数据增强。
使用该函数的方法如下:
transforms.RandomApply([transform1, transform2, ...], p=0.5)(image)
其中,[transform1, transform2, …]表示一组转换函数,p表示应用这组函数的概率,image表示要进行增强的图像。
transforms.RandomOrder
:它可以以一定的概率随机应用一组给定的转换函数,并将它们随机组合起来。该函数可以在数据增强过程中增加随机性,增强模型的泛化能力。
使用该函数的方法如下:
transforms.RandomOrder([transform1, transform2, ...])(image)
其中,[transform1, transform2, …]表示一组转换函数,image表示要进行增强的图像。
4.11.多种数据处理的串联
transforms.Compose
:是一个将多个数据变换组合在一起的类,用于将多个数据变换操作串联起来,构成一个数据变换的管道。其使用方法如下:
- 导入transforms模块;
- 创建多个转换函数;
- 创建一个转换函数序列;
- 将数据集应用于转换函数序列。
5.Pytorch中预训练好的模型(torchvision.models)
torchvision.models模块介绍:torchvision.models 模块是 Pytorch 的一个子模块,它包含了一些预训练的深度学习模型以及一些用于构建和训练新模型的工具。
该模块中包含了很多经典的深度学习模型,如 AlexNet、VGG、ResNet、Inception、DenseNet 等,这些模型在 ImageNet 上预训练得到了优秀的结果。这些模型通常被用来进行迁移学习,将模型的权重加载到新模型中,用于特定的任务,以提高模型的性能。
总之,torchvision.models 模块是构建和训练深度学习模型的重要工具之一,为用户提供了一些预训练的模型和辅助函数,可以帮助用户更快速地构建和训练自己的深度学习模型。
Torch部分
6.Pytorch中的实用工具(torch.utils)
torch.utils概述:torch.utils
是 Pytorch 中一个提供多种实用工具和数据结构的模块。它包含了一些有用的类和函数,能够帮助用户更方便地进行深度学习任务的开发。
torch.utils 中常用的一些类和函数:
- DataLoader:一个提供数据加载功能的类,可以将数据集加载为一个迭代器,便于用户逐批次地读取数据进行训练或测试。DataLoader 可以指定一些参数,例如每次读取的数据批次大小、是否打乱数据顺序等。
- TensorBoard:一个用于可视化模型训练过程和结果的工具类。用户可以将模型训练过程中的损失函数值、精度、参数分布等信息记录下来,通过 TensorBoard 可以实现数据的可视化展示。
- checkpoing:一个用于模型保存和加载的工具函数,可以将训练过程中的模型保存为文件,便于下次训练或测试时加载。checkpoint 函数的使用方式类似于 torch.save 和 torch.load。
- make_grid:一个用于将多张图片合并为一张网格状图片的函数。这个函数可以方便地将多张图片展示在同一张图上,便于用户查看模型的输出结果。
- set_rng_state 和 get_rng_state:用于保存和恢复随机数生成器状态的函数。这些函数可以帮助用户控制随机数生成器的状态,以便实现可复现的结果。
6.1.数据加载器对象
DataLoader对象的创建:创建 DataLoader 对象需要指定数据集对象、批处理大小、是否随机打乱、使用的线程数等参数。例如:
from torch.utils.data import DataLoader
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True, num_workers=4)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False, num_workers=4)
- dataset:必选参数,指定要加载的数据集。
- batch_size:可选参数,默认值为 1,指定每个批次加载的样本数。在训练过程中,每个批次的数据会被同时输入到模型中进行计算。通常情况下,batch_size 的值越大,模型训练过程的速度就越快,但是内存占用也会相应增加。
- shuffle:可选参数,默认值为 False,指定是否在每个 epoch 开始前对数据集进行随机重排。当 shuffle 设置为 True 时,每个 epoch 的数据顺序都会被随机化,这有助于模型学习到更多的样本信息,提高模型的泛化能力。
- num_workers:可选参数,默认值为 0,指定数据加载时使用的线程数。该参数通常用于加速数据加载过程,例如可以设置 num_workers 为 4,让数据加载过程并行化,从而提高数据加载速度。
使用数据加载器遍历数据集:创建好 DataLoader 对象后,可以通过 for 循环遍历数据集,每次迭代会返回一个批次的数据。例如:
for batch_idx, (data, target) in enumerate(train_loader):
# 进行模型训练或测试等操作
pass
DataLoader 中的每个批次数据是一个元组,其中第一个元素为输入数据,第二个元素为对应的标签。
7.Pytorch中的神经网络模型(torch.nn)
7.1.神经网络模型的基类(torch.nn.Module)
模块介绍:nn.Module 是 PyTorch 中一个重要的基类,用于定义神经网络模型。nn.Module 包含了神经网络模型的基本功能,例如参数管理、前向传播和反向传播等。通过继承 nn.Module 类,可以快速地搭建出各种神经网络模型。
自定义神经网络模型的方法:
在定义一个自己的神经网络模型时,一般需要继承 nn.Module 类,并实现以下两个方法:
- init 方法:也就是构造方法。该方法用于初始化模型的参数,例如卷积核大小、卷积层通道数、全连接层节点数等。
- forward 方法:用于实现模型的前向传播过程,也就是输入数据经过网络层后得到输出的过程。在 forward 方法中,可以使用 PyTorch 提供的各种网络层,例如卷积层、池化层、全连接层等。
继承已有的神经网络模块:在继承 nn.Module 类时,还可以使用 self.add_module(name, module)
方法,将其他的 nn.Module 子类添加为当前模型的子模块,以便对其进行管理和访问。这个方法还可以将一些不需要更新的变量注册到模型中,例如平移向量等。下面是这个方法的使用示例:
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.layer1 = nn.Linear(10, 5)
self.layer2 = nn.Linear(5, 1)
self.add_module("activation", nn.ReLU())
在上面的代码中,我们定义了一个名为 MyModule 的自定义模块,并向其中添加了两个线性层和一个 ReLU 激活函数层。其中,我们使用了 add_module 方法将 ReLU 激活函数层添加为当前模块的一个子模块,命名为 “activation”。
通过使用 add_module 方法,我们可以为当前模块添加任意数量的子模块,以构建更加复杂的深度神经网络结构。在实际应用中,我们经常会使用多个子模块组合成一个完整的模型,例如 ResNet、VGG 等经典的深度神经网络模型,其中每个子模块负责不同的特征提取和转换任务。
可以通过对象名.子模块名
的方式来访问一个模块的子模块。
使用nn.Module的注意事项:
- 如果在 nn.Module 子类中定义了一些需要更新的变量,例如权重和偏置等,需要将其设置为
nn.Parameter
类型。 - 在 forward 方法中,需要使用
torch.autograd.Function
来定义网络层的前向传播过程,以便 PyTorch 自动计算反向传播时的梯度。 - 在定义神经网络模型时,可以利用 Pytorch 提供的
nn.Sequential
类和nn.ModuleList
类,将多个网络层组合起来,形成一个完整的神经网络模型。
7.2.Pytorch中神经网络模型的各种神经层
神经网络模型中的各种神经层包括全连接层、卷积层的设置、最大池化层、平均池化层、DropOut层等。
- 全连接层nn.Linear类:
nn.Linear
是 PyTorch 中的一个类,用于创建全连接层。在创建全连接层时,我们需要指定输入和输出的大小,nn.Linear
会自动为该层创建权重和偏置参数,并在前向传播时自动进行计算。以下是使用 nn.Linear 函数的示例:
import torch
import torch.nn as nn
# 定义一个输入大小为 10,输出大小为 5 的全连接层
linear_layer = nn.Linear(10, 5)
# 生成一个随机输入张量
input_tensor = torch.randn(3, 10)
# 前向传播计算
output_tensor = linear_layer(input_tensor)
print("input size: ", input_tensor.size()) # 输出:input size: torch.Size([3, 10])
print("output size: ", output_tensor.size()) # 输出:output size: torch.Size([3, 5])
在上述示例中,我们首先使用 nn.Linear 创建了一个输入大小为 10,输出大小为 5 的全连接层 linear_layer,然后生成一个大小为 3 × 10 3\times10 3×10 的随机输入张量 input_tensor,并通过前向传播计算得到输出张量 output_tensor,其大小为 3 × 5 3\times5 3×5。
备注:nn.Linear 中的输入和输出大小都是指数据张量的最后一维的大小,即对于一个大小为 ( n 1 , n 2 , . . . , n k ) (n_1, n_2, ..., n_k) (n1,n2,...,nk)的输入张量,输入大小为 n k n_k nk,对应的输出张量大小也是由输出大小 m m m 决定的。
此外,nn.Linear 也可以通过 bias参数指定是否启用偏置。默认情况下,nn.Linear 会自动创建偏置参数。
- 2D卷积层nn.Conv2d类:
nn.Conv2d
是 PyTorch 中的一个类,用于创建 2D 卷积层。在使用 nn.Conv2d 时,我们需要指定输入和输出的通道数、卷积核的大小和数量、卷积的步幅、填充等参数。以下是使用 nn.Conv2d 函数的示例:
import torch
import torch.nn as nn
# 定义一个输入通道数为 3,输出通道数为 16,卷积核大小为 3x3,步幅为 1,填充为 1 的 2D 卷积层
conv_layer = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1)
# 生成一个随机输入张量
input_tensor = torch.randn(1, 3, 32, 32)
# 前向传播计算
output_tensor = conv_layer(input_tensor)
print("input size: ", input_tensor.size()) # 输出:input size: torch.Size([1, 3, 32, 32])
print("output size: ", output_tensor.size()) # 输出:output size: torch.Size([1, 16, 32, 32])
需要注意的是,在 nn.Conv2d 中,输入和输出的通道数、卷积核的大小和数量等都需要指定为整数。此外,也可以通过 padding_mode 参数指定填充的方式,如 padding_mode=‘zeros’ 表示使用零填充。
默认情况下,nn.Conv2d 中的卷积核的权重参数会自动初始化为随机值,可以通过设置 weight 参数手动指定权重。如果需要使用偏置参数,可以将 bias 参数设置为 True。
- 2D最大池化层nn.MaxPool2d:nn.MaxPool2d 是 PyTorch 中的一个类,用于创建 2D 最大池化层。在使用 nn.MaxPool2d 时,我们需要指定池化核的大小和步幅等参数。
以下是使用 nn.MaxPool2d 函数的示例:
import torch
import torch.nn as nn
# 定义一个池化核大小为 2x2,步幅为 2 的 2D 最大池化层
pool_layer = nn.MaxPool2d(kernel_size=2, stride=2)
# 生成一个随机输入张量
input_tensor = torch.randn(1, 16, 32, 32)
# 前向传播计算
output_tensor = pool_layer(input_tensor)
print("input size: ", input_tensor.size()) # 输出:input size: torch.Size([1, 16, 32, 32])
print("output size: ", output_tensor.size()) # 输出:output size: torch.Size([1, 16, 16, 16])
需要注意的是,在 nn.MaxPool2d 中,池化核的大小和步幅等参数也需要指定为整数。默认情况下,nn.MaxPool2d 中的池化核的大小和步幅等参数的值相同。
- 2D平均池化层AvgPool2d:Pytorch中二维平均池化层的实现,用于对输入的二维特征图进行平均池化操作。其使用方法如下:
import torch.nn as nn
# 创建AvgPool2d实例,参数为池化核大小和步长
avg_pool = nn.AvgPool2d(kernel_size=2, stride=2)
# 假设输入特征图的形状为[batch_size, channels, height, width]
x = torch.randn(16, 32, 64, 64) # 输入特征图的随机数据
# 对输入特征图进行平均池化
y = avg_pool(x)
# 输出特征图的形状,将会是原始形状的一半,即[batch_size, channels, height/2, width/2]
print(y.shape)
在上面的例子中,我们首先创建了一个AvgPool2d实例,其中kernel_size参数表示池化核的大小,stride参数表示池化操作的步长。然后,我们定义了一个输入特征图x,随机生成了一些数据。最后,我们使用avg_pool对x进行了平均池化,得到了输出特征图y,并输出了其形状。
需要注意的是,AvgPool2d的输入特征图必须是四维张量,即包含batch_size、通道数、高度和宽度四个维度。此外,输出特征图的高度和宽度将会是输入特征图的一半,因为在上面的例子中我们将池化核大小和步长都设置为了2。如果需要更改这些参数,只需要修改AvgPool2d的参数即可。
- 自适应2D最大池化层:
AdaptiveMaxPool2d
是PyTorch中自适应二维最大池化层的实现,它可以对输入特征图进行自适应的最大池化操作,输出固定形状的特征图。
相比于传统的最大池化层,AdaptiveMaxPool2d不需要指定池化核大小和步长,而是根据输出特征图的大小自适应地调整池化核的大小和步长。下面是一个简单的例子:
import torch
import torch.nn as nn
# 创建AdaptiveMaxPool2d实例,参数为输出特征图的大小
adaptive_max_pool = nn.AdaptiveMaxPool2d(output_size=(3, 3))
# 假设输入特征图的形状为[batch_size, channels, height, width]
x = torch.randn(16, 32, 64, 64) # 输入特征图的随机数据
# 对输入特征图进行自适应最大池化
y = adaptive_max_pool(x)
# 输出特征图的形状,将会是[batch_size, channels, 3, 3]
print(y.shape)
- DropOut层: nn.Dropout 是 PyTorch 中的一个类,用于实现 Dropout 层。Dropout 是一种常用的正则化技术,其通过随机丢弃神经网络中的一些神经元来避免过拟合的发生。
在使用 nn.Dropout 时,我们需要指定 dropout 概率,即将输入张量中的元素以指定的概率设为 0。同时,我们还需要注意,在模型的训练和测试阶段,nn.Dropout 的行为是不同的。在训练阶段,nn.Dropout 会随机丢弃输入张量中的一些元素,从而起到正则化的效果;而在测试阶段,nn.Dropout 不会对输入张量进行任何处理,仅仅将其传递给下一层。
以下是使用 nn.Dropout 的示例:
import torch
import torch.nn as nn
# 定义一个 dropout 概率为 0.5 的 Dropout 层
dropout_layer = nn.Dropout(p=0.5)
# 生成一个随机输入张量
input_tensor = torch.randn(1, 16)
# 前向传播计算
output_tensor = dropout_layer(input_tensor)
print("input: ", input_tensor) # 输出:input: tensor([[ 1.2222, 0.2195, 0.6908, -0.2049, -1.3126, -0.8331, -0.0946, -0.2113,
0.5126, 1.2111, -0.3068, -0.5277, -0.8499, -0.9301, -0.4993, 1.6586]])
print("output: ", output_tensor) # 输出:output: tensor([[ 0.0000, 0.4390, 0.0000, -0.0000, -2.6251, -1.6663, -0.0000, -0.4226,
0.0000, 2.4222, -0.0000, -0.0000, -1.6998, -0.0000, -0.0000, 0.0000]])
需要注意的是,在实际使用中,为了避免 dropout 对模型的性能造成过大的影响,我们通常会将 dropout 概率设置为比较小的值,例如 0.1 或者 0.2。
同时,如果我们在模型训练过程中使用了 Dropout,我们在进行模型评估时也需要将其设置为 eval()。
7.3.Pytorch中对模型的评价
交叉熵:
- 交叉熵概述和相应类:
nn.CrossEntropyLoss
是一个用于多分类问题的损失函数,在PyTorch中经常被用于训练分类模型。其主要功能是将模型预测值与真实标签进行比较,计算出预测结果与真实结果之间的差距,然后反向传播优化模型参数。 - CrossEntropy类的使用方法:首先定义
nn.CrossEntropyLoss
实例,在实例化时可以设置一些参数,例如权重、忽略某些标签等;接着在模型训练过程中,将模型预测结果和真实标签传入nn.CrossEntropyLoss
实例中计算损失,然后调用反向传播算法进行模型参数优化。下面是一个简单的示例代码:
import torch
import torch.nn as nn
# 定义模型预测值和真实标签
inputs = torch.randn(10, 5) # 10个样本,5个类别
targets = torch.randint(5, (10,)) # 10个样本的真实标签,取值为0~4
# 定义损失函数
criterion = nn.CrossEntropyLoss()
# 计算损失
loss = criterion(inputs, targets)
# 反向传播更新模型参数
loss.backward()
其中,inputs是模型预测值,targets是真实标签。在计算损失时,我们将inputs和targets传给nn.CrossEntropyLoss实例,它会自动计算损失。最后,我们调用loss.backward()进行反向传播更新模型参数。
8.Pytorch中的各种优化器(torch.optim)
基本概述:torch.optim
是PyTorch中用于实现各种优化算法的模块,包含了常用的优化算法(如SGD,Adam等)的实现。其主要作用是实现神经网络的参数优化,即通过调整网络中的参数使得网络的输出能够更好地拟合目标值。
核心类Optimizer中的方法:
zero_grad()
: 将所有参数的梯度设为0。step()
: 根据梯度更新参数值。add_param_group(param_group)
: 将一个新的参数组加入到优化器中。
优化器的使用步骤:
- 在使用时,我们需要先创建一个Optimizer对象,传入需要优化的参数和优化算法的相关参数(如学习率、动量等)。
- 在每次反向传播计算梯度后调用zero_grad()清空梯度,最后调用step()方法进行参数更新。
例如,使用SGD算法进行参数优化,可以按照以下步骤进行:
import torch.optim as optim
# 创建需要优化的参数
params = model.parameters()
# 定义优化器
optimizer = optim.SGD(params, lr=0.01, momentum=0.9)
# 在每次反向传播后调用zero_grad()清空梯度
optimizer.zero_grad()
# 计算损失并反向传播
loss.backward()
# 调用step()方法进行参数更新
optimizer.step()
8.1.随机梯度下降优化算法(SGD)
基本介绍:optim.SGD
是PyTorch中的一个优化器,它实现了随机梯度下降算法。SGD是深度学习中常用的一种优化方法,其主要思想是通过反向传播算法计算梯度并不断地更新模型参数,使得损失函数最小化。下面是optim.SGD的使用方法:
import torch.optim as optim
optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=momentum)
其中,model.parameters()表示需要优化的参数集合,lr是学习率,momentum是动量因子,这两个参数可以根据具体问题进行调整。在训练过程中,我们可以在每个batch的训练中使用optimizer来更新模型参数。