注意:千万不要想着把pytorch中的方法给全部记住,我们只需要对这个方法的使用有个大致印象就行,等到需要的时候再上网查一下具体的用法即可。因为就算你现在对这个方法很了解,如果长时间不使用该方法,那么你还是会忘记的(啊哈哈哈哈哈),所以切记不要想着背住这些方法。
文章目录
1.1 reshape()、view()方法
pytorch中reshape()、view()
都可以用来改变tensor的shape(形状、大小),但tensor本身的数据保持不变。reshape(*shape) -> Tensor
view(*shape) -> Tensor
。shape可以为:tuple、list或int。这两种方法的用法如下所示。
import torch
x = torch.tensor([[1, 3, 5], [2, 4, 6]])
y1 = x.reshape(3, 2)
y2 = x.view(3, 2)
y3 = x.reshape(-1,2) # 某个维度为-1时,会根据原tensor数据大小推出其它维度的大小。
print(f"reshape方法:{y1}")
print(f"view方法:{y2}")
print(f"自适应生成其它维度的大小:{y3}")
输出:
reshape方法:tensor([[1, 3],
[5, 2],
[4, 6]])
view方法:tensor([[1, 3],
[5, 2],
[4, 6]])
自适应生成其它维度的大小:tensor([[1, 3],
[5, 2],
[4, 6]])
我们还可以使用函数torch.reshape(input, shape)
,该函数和上面的reshape()、view()实现的功能相同。
import torch
x = torch.tensor([[1, 3, 5], [2, 4, 6]])
y1 = torch.reshape(x, (3, 2))
y2 = torch.reshape(x, (-1, 2))
print(f"torch.reshape方法:{y1}")
print(f"自适应生成其它维度的大小:{y2}")
输出:
torch.reshape方法:tensor([[1, 3],
[5, 2],
[4, 6]])
自适应生成其它维度的大小:tensor([[1, 3],
[5, 2],
[4, 6]])
1.2 expand()、repeat()方法
- pytorch中
expand()
和repeat()
方法常用于张量数据的复制和维度扩展。其中对应方法的表示形式分别为:tensor.expand(*sizes)
和tensor.repeat(*sizes)。
expand()
可以将tensor数据中形状(shape)维度为1的数据扩充到指定大小。例如:某个tensor数据的shape为torch.Size([1, 4, 4])
,其中第一个维度为1、第二、三个维度分别为4、4,expand()
方法只能在第一个维度(即为1)上进行扩展,无法作用于第二、三个维度(即分别为4,4)。从下面代码可以看出,对于shape为[1,2,2]的tensor数据将维度1扩展为维度3,相当于把原始tensor数据复制了3份。举个例子:假如每个人手里都有2个苹果和2个香蕉(shape为[1,2,2]),我们将三个人的苹果和香蕉聚集在一起(也就是扩展:expand()),最后得到了3个人的苹果和香蕉(shape为[3,2,2])
import torch
tensor = torch.randn(1, 2, 2)
# 记住:只能在1这个维度上面进行扩展,其它的维度不可以。
tensor_expand = tensor.expand(3, 2, 2)
print(f"tensor: {tensor}")
print(f"tensor_expand: {tensor_expand}")
print(f"扩展后的维度大小: {tensor_expand.shape}")
输出:
tensor: tensor([[[ 1.4252, 0.4148],
[-1.2340, 0.4633]]])
tensor_expand: tensor([[[ 1.4252, 0.4148],
[-1.2340, 0.4633]],
[[ 1.4252, 0.4148],
[-1.2340, 0.4633]],
[[ 1.4252, 0.4148],
[-1.2340, 0.4633]]])
扩展后的维度大小: torch.Size([3, 2, 2])
- 由上面可知,
expand()
只能作用于维度为1的tensor数据,那么对于不是1的维度我们可以借助repeat()
方法。其方法的形式为tensor.repeat(*sizes)
,size 表示在原始tensor数据的各个维度上复制的次数。废话少说,看下面代码吧,给各位一个建议,如果对某个方法的定义不太了解的话,那就亲自敲一下这个代码,这样慢慢的你就对该方法有个初步认识了。
import torch
tensor = torch.randn(1, 2, 2)
tensor_repeat = tensor.repeat(2, 2, 2) # 在原始tensor数据的第1、2、3个维度上均复制2次
print(f"tensor: {tensor}")
print(f"tensor_repeat: {tensor_repeat}")
print(f"扩展后的维度大小: {tensor_repeat.shape}")\
输出:
tensor: tensor([[[ 0.6281, -0.9614],
[ 0.7230, 1.2946]]])
tensor_repeat: tensor([[[ 0.6281, -0.9614, 0.6281, -0.9614],
[ 0.7230, 1.2946, 0.7230, 1.2946],
[ 0.6281, -0.9614, 0.6281, -0.9614],
[ 0.7230, 1.2946, 0.7230, 1.2946]],
[[ 0.6281, -0.9614, 0.6281, -0.9614],
[ 0.7230, 1.2946, 0.7230, 1.2946],
[ 0.6281, -0.9614, 0.6281, -0.9614],
[ 0.7230, 1.2946, 0.7230, 1.2946]]])
扩展后的维度大小: torch.Size([2, 4, 4])
参考:【Pytorch】对比expand和repeat函数
「PyTorch」repeat() 和 expand()
1.3 item()、tolist()方法
- item()方法:将包含一个元素的tensor数据转为python数字,这仅适用于具有一个元素的张量tensor;
- tolist()方法:将tensor数据转为python列表或数字返回。
import torch
tensor1 = torch.tensor([6], dtype=int)
num1 = tensor1.item()
tensor2 = torch.tensor([1, 2, 3, 4, 5, 6])
list1 = tensor2.tolist()
print(type(num1))
print(type(list1))
输出:
<class 'int'>
<class 'list'>
1.4 sum()、min()、mean()函数
- torch.sum() 表示对输入tensor数据的某一维度进行求和。共有两种用法:
torch.sum(input, dtype=None)
torch.sum(input, list: dim, bool: keepdim=False, dtype=None) → Tensor
。其中 input:输入的tensor数据;dim:进行求和的维度,可以是一个列表;keepdim:默认为False,若keepdim=True,则返回的Tensor除dim之外的维度与input相同。因为求和之后这个dim的元素个数为1,所以要被去掉,如果要保留这个维度,则应当keepdim=True。
import torch
tensor1 = torch.tensor([[1, 3, 5], [2, 4, 6]])
sum1 = torch.sum(tensor1)
sum2 = torch.sum(tensor1, dim=0)
sum3 = torch.sum(tensor1, dim=1)
print(sum1)
print(sum2)
print(sum3)
输出:
tensor(21)
tensor([ 3, 7, 11])
tensor([ 9, 12])
- torch.min() :返回tensor数据中的最小值。具体用法可以参考Pytorch的max()与min()函数
import torch
tensor1 = torch.tensor([[1, 3, 5], [2, 4, 6]])
min1 = torch.min(tensor1)
min2 = torch.min(tensor1, dim=0)
min3 = torch.min(tensor1, dim=1)
value, indices = torch.min(tensor1, dim=1)
print(min1)
print("------min dim=0-------")
print(min2)
print("------min dim=1-------")
print(min3)
print("------value indices-------")
print(f"value={value},indices={indices}")
输出:
tensor(1)
------min dim=0-------
torch.return_types.min(
values=tensor([1, 3, 5]),
indices=tensor([0, 0, 0]))
------min dim=1-------
torch.return_types.min(
values=tensor([1, 2]),
indices=tensor([0, 0]))
------value indices-------
value=tensor([1, 2]),indices=tensor([0, 0])
由上面代码返回结果可知:torch.min() 函数的返回值由values(值)和indices(索引)组成,values中存放最小值,indices存放最小值对应的索引。
3. torch.max():返回tensor数据中的最大值。用法和torch.min() 类似,就不解释这个方法了。
1.5 squeeze()、unsqueeze方法
torch.squeeze(input, dim=None, out=None)
:该函数功能是维度压缩,其中 input 中大小为1的所有维都已删除。例如:如果 input 的大小为(A×1×B×C×1×D),那么返回的tensor的大小则为(A×B×C×D)。当我们指定 dim 时,那么只在给定的维度上进行压缩操作。
import torch
tensor1 = torch.randn(512, 1, 1, 10)
squee1 = torch.squeeze(tensor1)
squee2 = torch.squeeze(tensor1, dim=1)
print(tensor1.shape)
print(squee1.shape)
print(squee2.shape)
输出:
torch.Size([512, 1, 1, 10])
torch.Size([512, 10])
torch.Size([512, 1, 10])
torch.unsqueeze(input, dim)
:该函数功能是提高tensor数据的维度,dim 表示在指定的地方增加一个维度。
import torch
tensor1 = torch.randn(512, 10)
unsquee1 = torch.unsqueeze(tensor1, dim=1)
unsquee2 = torch.unsqueeze(tensor1, dim=2)
print(tensor1.shape)
print(unsquee1.shape)
print(unsquee2.shape)
输出:
torch.Size([512, 10])
torch.Size([512, 1, 10])
torch.Size([512, 10, 1])
1.6 tensor与numpy之间的转换
- 通过
numpy()
方法将Tensor转化为NumPy数组; - 通过
from_numpy()
将NumPy数组转Tensor; numpy()、from_numpy()
两个函数所产生的NumPy数组和Tensor共享相同的内存(所以他们之间的转换很快),改变其中⼀个时另⼀个也会改变!参考如何将Tensor和NumPy相互转换
import torch
import numpy as np
print("----Tensor 转化为 NumPy----")
tensor1 = torch.tensor([1, 2, 3, 4, 5, 6])
npy1 = tensor1.numpy()
print(type(npy1))
npy1 += 1 # 修改npy1中的数据,tensor1数据也会发生改变
print(tensor1)
print("----NumPy 转化为 Tensor----")
npy2 = np.ones(5)
tensor2 = torch.from_numpy(npy2)
print(tensor2.type())
tensor2 += 1 # 修改tensor2中的数据,npy2数据也会发生改变
print(npy2)
输出:
----Tensor 转化为 NumPy----
<class 'numpy.ndarray'>
tensor([2, 3, 4, 5, 6, 7])
----NumPy 转化为 Tensor----
torch.DoubleTensor
[2. 2. 2. 2. 2.]
1.7 pytorch中拼接函数:cat()、stack()、add()
- cat() 函数: 在给定维度上对输入张量序列进行连接操作。函数表示为:
torch.cat(inputs, dim=?) → Tensor)
,其中inputs : 待连接的张量序列,可以是任意相同Tensor类型的python序列;dim : 沿着该维度连接张量序列。
import torch
tensor1 = torch.ones(2, 4)
tensor2 = torch.zeros(3, 4)
out1 = torch.cat([tensor1, tensor2], dim=0)
print("-------------dim=0-------------")
print(out1)
tensor3 = torch.zeros(2, 2)
out2 = torch.cat([tensor1, tensor3], dim=1)
print("-------------dim=1-------------")
print(out2)
输出:
-------------dim=0-------------
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
-------------dim=1-------------
tensor([[1., 1., 1., 1., 0., 0.],
[1., 1., 1., 1., 0., 0.]])
注意
对于形状大小(shape)为[b,c,h,w]的tensor数据来说,第一个维度(b)的下标索引为0,第二个维度( c)的下标索引为1,第三个维度(h)的下标索引为2,第四个维度(w)的下标索引为3。
如果我们把cat()
函数中的参数dim看成是shape某个维度的下标索引,那么当dim=0时,除了第一个维度的大小可以不同,其它维度大小均需要保持相同,否则会报错。当dim=1时,除了第二个维度的大小可以不同,其它维度大小均需要保持相同,… 。
由上面代码可知:当dim=0时,张量tensor1和tensor2的形状大小(shape)分别为[2,4]和[3,4],第一个维度大小不同,但第二个维度大小必须相同。同理,当dim=1时,张量tensor1和tensor3的形状大小(shape)分别为[2,4]和[2,2],第二个维度大小可以不同,但第一个维度大小必须相同。
总结一句话:cat()
函数沿着dim这个维度进行拼接时,需要保证除了dim以外的其它维度大小相同。
参考:Pytorch中的torch.cat()函数
torch.cat()函数
- stack() 函数:沿着一个新维度对输入张量序列进行连接,输入序列中张量的形状(shape)均应该相同,拼接之后会将tensor数据的维度增加1。该函数表示形式为
torch.stack(inputs, dim=0) → Tensor
,其中inputs为待拼接的张量序列,可以是列表或者元组;dim :新的维度 。代码如下:
import torch
a = torch.randn(6, 6)
b = torch.randn(6, 6)
out1 = torch.stack([a, b], dim=0)
out2 = torch.stack([a, b], dim=1)
out3 = torch.stack([a, b], dim=2)
print(f"dim=0: {out1.shape}")
print(f"dim=1: {out2.shape}")
print(f"dim=2: {out3.shape}")
输出:
dim=0: torch.Size([2, 6, 6])
dim=1: torch.Size([6, 2, 6])
dim=2: torch.Size([6, 6, 2])
参考:torch.stack()的官方解释,详解以及例子
【Pytorch】torch.stack()的使用
除了cat()
和stack()
, pytorch还提供了其它方式的拼接方法hstack()
函数、vstack()
函数和dstack()
函数。其中:hstack() 是将张量序列沿着水平方向进行连接;vstack() 是将张量序列沿着垂直方向进行连接;dstack() 是将张量序列沿着深度方向进行连接。
import torch
a = torch.randn(6, 6)
b = torch.randn(6, 6)
out_h = torch.hstack([a, b]) # 水平方向
out_v = torch.vstack([a, b]) # 垂直方向
out_d = torch.dstack([a, b]) # 深度方向
print(f"水平方向合并: {out_h.shape}")
print(f"垂直方向合并: {out_v.shape}")
print(f"深度方向合并: {out_d.shape}")
输出:
水平方向合并: torch.Size([6, 12])
垂直方向合并: torch.Size([12, 6])
深度方向合并: torch.Size([6, 6, 2])
参考:Pytorch 合并两个维度不同的张量
pytorch每日一学33(torch.hstack())从水平方向(列方向)叠加向量
- add() 函数:用于对两个张量进行逐元素加法运算。
import torch
a = torch.tensor([12, 6, 1])
b = torch.tensor([8, 14, 19])
out = torch.add(a, b)
print(out)
输出:
tensor([20, 20, 20])
参考:torch.cat()、 torch.add()、torch.subtract()、torch.subtract()和torch.div()函数详解和示例
1.8 pytorch中的拆分函数:split()、chunk()
- split() 函数:按照块的大小拆分tensor数据,返回一个拆分后的张量序列组成的"元组-tuple"。
torch.split(tensor, split_size_or_section, dim=0)
,其中tesnor :输入数据;split_size_or_section:需要拆分的大小(int或者list);dim:需要拆分的维度。
import torch
tensor = torch.randn(3, 64, 64)
tuple1, tuple2 = torch.split(tensor, [1, 2], dim=0) # 将第一个维度"3"进行拆分,拆分成一个"1"和一个"2"。
print(tuple1.shape)
print(tuple2.shape)
输出:
torch.Size([1, 64, 64])
torch.Size([2, 64, 64])
- chunk() 函数:按照块的数量拆分tensor数据,返回一个拆分后的张量序列组成的"元组-tuple"。
torch.chunk(input, chunks, dim=0) → List of Tensors
。
import torch
tensor = torch.randn(8, 64, 64)
tuple1, tuple2 = torch.chunk(tensor, 2, dim=0) # 将第一个维度"8"拆分成两份,也就变成了两个4。
print(tuple1.shape)
print(tuple2.shape)
输出:
torch.Size([4, 64, 64])
torch.Size([4, 64, 64])
参考:torch.split() 与 torch.chunk()
3. 还可以使用split()、chunk() 方法对tensor数据进行拆分。
import torch
tensor = torch.randn(8, 64, 64)
tuple1_split, tuple2_split = tensor.split([6, 2], dim=0)
tuple1_chunk, tuple2_chunk = tensor.chunk(2, dim=0)
print("---------split()方法------------")
print(tuple1_split.shape)
print(tuple2_split.shape)
print("---------chunk()方法------------")
print(tuple1_chunk.shape)
print(tuple2_chunk.shape)
输出:
---------split()方法------------
torch.Size([6, 64, 64])
torch.Size([2, 64, 64])
---------chunk()方法------------
torch.Size([4, 64, 64])
torch.Size([4, 64, 64])
1.9 flatten()函数
torch.flatten(input, start_dim=0, end_dim=-1) 是一个对多维数据的降维函数。其中,input 表示要被扁平化的tensor;start_dim :扁平化的起始维度;end_dim:扁平化的结束维度。
import torch
tensor = torch.randn(10, 5, 2)
flat1 = torch.flatten(tensor) # torch.flatten(tensor)等于torch.flatten(tensor,0)
flat2 = torch.flatten(tensor, 0)
flat3 = torch.flatten(tensor, 1) # dim=1表示从第二个维度开始扁平化
flat4 = torch.flatten(tensor, 2) # dim=2表示从第三个维度开始扁平化
print(f"dim=0: {flat1.shape}")
print(f"dim=0: {flat2.shape}")
print(f"dim=1: {flat3.shape}")
print(f"dim=2: {flat4.shape}")
输出:
dim=0: torch.Size([100])
dim=0: torch.Size([100])
dim=1: torch.Size([10, 10])
dim=2: torch.Size([10, 5, 2])
- torch.nn.Flatten() 默认从第二维开始扁平化。
import torch
tensor = torch.randn(10, 5, 2)
flat = torch.nn.Flatten()
tensor_flat = flat(tensor) # 默认从第二维开始扁平化
print(tensor_flat.shape)
输出:
torch.Size([10, 10])
参考:torch.flatten()与torch.nn.Flatten()
1.10 torch.eq()、torch.argmax()
- torch.eq() 函数:用于对两个张量进行逐元素的比较,若同一位置的两个元素相同,则返回True;否则返回False。
torch.eq(input, other, *, out=None)
,其中input :必须是tensor数据,该张量用于比较;other:可以是张量tensor,也可以是一个值value,该函数返回一个Boolean类型的张量。
import torch
pre_label = torch.tensor([1, 2, 3, 4, 6])
true_label = torch.tensor([1, 2, 3, 4, 5])
out = torch.eq(pre_label, true_label)
print(out)
print(out.sum()) # 统计两个张量中同一位置下相同元素的个数。
输出:
tensor([ True, True, True, True, False])
tensor(4)
参考:torch.eq与torch.ne——判断数组中的数值是否相等
- torch.argmax() 函数:返回指定维度下最大值对应的下标索引。
import torch
pred = torch.tensor([[3, 1, 4, 5, 6, 2], [1, 2, 3, 4, 5, 6]])
pred_label = torch.argmax(pred) # 没有指定dim的值,表示把pred中的元素平整化为一维向量,然后找最大值的索引。
pred_label0 = torch.argmax(pred, dim=0) # 求出每一列最大值的索引
pred_label1 = torch.argmax(pred, dim=1) # 求出每一行最大值的索引
print(pred_label)
print(pred_label0)
print(pred_label1)
输出:
tensor(4)
tensor([0, 1, 0, 0, 0, 1])
tensor([4, 5])
1.11 pytorch中cuda相关操作
import torch
print(f"查看pytorch的版本: {torch.__version__}")
print(f"查看cuda是否可用: {torch.cuda.is_available()}")
print(f"查看GPU的数量: {torch.cuda.device_count()}")
print(f"查看GPU的索引号(默认从0开始): {torch.cuda.current_device()}")
print(f"根据索引号查看GPU的名字: {torch.cuda.get_device_name(0)}")
"""
将tensor数据转移到相应的GPU上。
使用".cuda()"可以将内存中的Tensor转换到GPU上。
如果有多块GPU,可以使用.cuda(i)来表示第i块GPU所对应的显存(从0开始),cuda(0)和cuda()等价.
"""
tensor1 = torch.tensor([1, 2, 3]).cuda()
print(tensor1)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)
tensor2 = torch.tensor([1, 2, 3]).to(device)
print(tensor2)
tensor3 = torch.tensor([1, 2, 3], device=device)
print(tensor3)
输出:
查看pytorch的版本: 1.10.0
查看cuda是否可用: True
查看GPU的数量: 1
查看GPU的索引号(默认从0开始): 0
根据索引号查看GPU的名字: NVIDIA GeForce RTX 3060 Laptop GPU
tensor([1, 2, 3], device='cuda:0')
cuda:0
tensor([1, 2, 3], device='cuda:0')
tensor([1, 2, 3], device='cuda:0')