【pytorch】基本元素操作和运算操作

pytorch基本元素操作

  1. 创建一个没有初始化的矩阵
import torch
x = torch.empty([2,3])
print(x)
------------------------------------------------------------------------------
tensor([[6.2937e+06, 1.0916e-42, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00]])
  1. 创建一个初始化后的矩阵,值从0到1均匀分布
x = torch.rand([2,3])
print(x)
------------------------------------------------------------------------------
tensor([[0.9353, 0.7258, 0.4007],
        [0.9609, 0.6947, 0.9185]])
  1. 创建一个全零矩阵,数据类型为long
x = torch.zeros(2,3,dtype=torch.long)
print(x)
------------------------------------------------------------------------------
tensor([[0, 0, 0],
        [0, 0, 0]])
  1. 直接通过已有数据创建张量
x = torch.tensor([2.5,3.5])
print(x)
------------------------------------------------------------------------------
tensor([2.5000, 3.5000])
  1. 通过已有张量,创建尺寸相同的张量
x = x.new_ones(5,3,dtype=torch.double)
print(x)
y = torch.randn_like(x,dtype=torch.float32) # 均值为0,方差为1的值
print(y)
------------------------------------------------------------------------------
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
tensor([[ 0.0773, -0.6255,  1.4551],
        [ 0.6771, -1.1565,  0.9222],
        [ 0.3726,  0.2611,  1.4186],
        [ 0.4260,  1.3753,  0.1571],
        [-1.5539, -1.4486,  1.0401]])
  1. 得到张量的形状
print(x.shape) 
print(x.size())
------------------------------------------------------------------------------
torch.Size([5, 3])
torch.Size([5, 3])
  1. 用a,b分别接收张量形状
a,b = x.shape
print("a=",a)
print("b=",b)
------------------------------------------------------------------------------
a= 5
b= 3

pytorch基本运算操作

加法操作

  1. 加法操作1
x = x.new_ones(5,3,dtype=torch.double)
y = torch.rand(5,3)
print(x+y)
------------------------------------------------------------------------------
tensor([[1.4191, 1.5567, 1.5551],
        [1.4531, 1.4027, 1.4756],
        [1.7324, 1.4052, 1.5504],
        [1.7082, 1.0447, 1.8590],
        [1.4321, 1.5458, 1.2708]], dtype=torch.float64)
  1. 加法操作2
z = torch.add(x,y)
print(z)
------------------------------------------------------------------------------
tensor([[1.4191, 1.5567, 1.5551],
        [1.4531, 1.4027, 1.4756],
        [1.7324, 1.4052, 1.5504],
        [1.7082, 1.0447, 1.8590],
        [1.4321, 1.5458, 1.2708]], dtype=torch.float64)
  1. 加法操作3
result = torch.empty(5,3)
torch.add(x,y,out = result)
print(result)
------------------------------------------------------------------------------
tensor([[1.4191, 1.5567, 1.5551],
        [1.4531, 1.4027, 1.4756],
        [1.7324, 1.4052, 1.5504],
        [1.7082, 1.0447, 1.8590],
        [1.4321, 1.5458, 1.2708]])
  1. 加法操作4,直接把x加到y中
y.add_(x)
print(y)
------------------------------------------------------------------------------
tensor([[1.4191, 1.5567, 1.5551],
        [1.4531, 1.4027, 1.4756],
        [1.7324, 1.4052, 1.5504],
        [1.7082, 1.0447, 1.8590],
        [1.4321, 1.5458, 1.2708]])

索引和切片操作

假设模拟的是cifar10的数据,每个图片形状为3*32*32

  1. 根据索引获取数据
image = torch.rand(4,3,32,32) # (b,c,h,w) b是batch_size,c是rgb,h是height,w是width
print(image.shape)

#获取batch_size = 0的数据形状
print(image[0].shape)

#获取batch_size = 0, c = "r"的形状
print(image[0,0].shape)

#获取batch_size = 0, c = "r"第三行,第四列的像素点的值
print(image[0,0,2,3])
------------------------------------------------------------------------------
torch.Size([4, 3, 32, 32])
torch.Size([3, 32, 32])
torch.Size([32, 32])
tensor(0.8564)
  1. index中包括:start : end
# 获取batch_size = 0和1数据的形状 也就是取0到2
print(image[:2].shape)

# 获取batch_size = 0和1,c="g" 和 "b"的数据的形状
print(image[:2,1:,:,:].shape)

#逆向索引取数据:-1代表最后一个数据,这里是c="b"
print(image[:2,-1:,:,:].shape)
------------------------------------------------------------------------------
torch.Size([2, 3, 32, 32])
torch.Size([2, 2, 32, 32])
torch.Size([2, 1, 32, 32])
  1. index中包括:start : end : step
print(image[:,:,0:32:2,0:32:2].shape)
print(image[:,:,::2,::2].shape)
------------------------------------------------------------------------------
torch.Size([4, 3, 16, 16])
torch.Size([4, 3, 16, 16])
  1. index.select:选择某一个维度进行操作,其他维度不变
print(image.shape)
# 第一个参数是选择的维度,第二个参数是选择哪些数,注意第二个参数传递的是张量
# 选择0维,也就是b
print(image.index_select(0,torch.tensor([0,2])).shape)

# 选择1维,也就是c
print(image.index_select(1,torch.tensor([0,1])).shape)

# 选择2维,也就是h 这里32代表0到32
print(image.index_select(2,torch.arange(32)).shape)

# 选择3维,也就是w
print(image.index_select(3,torch.arange(8)).shape)
------------------------------------------------------------------------------
torch.Size([4, 3, 32, 32])
torch.Size([2, 3, 32, 32])
torch.Size([4, 2, 32, 32])
torch.Size([4, 3, 32, 32])
torch.Size([4, 3, 32, 8])
  1. 省略符号…的使用
# 等价于image.shape
print(image[...].shape)

# 省略后面三个维度
print(image[0,...].shape) 

# 省略后面两个维度
print(image[:,1,...].shape)

# 省略前面三个维度
print(image[...,::2].shape)
------------------------------------------------------------------------------
torch.Size([4, 3, 32, 32])
torch.Size([3, 32, 32])
torch.Size([4, 32, 32])
torch.Size([4, 3, 32, 16])

维度变换

reshape和view是等价的

# 模拟的是手写数字识别的图像数据
image = torch.rand(4,1,28,28)
print(image.shape) 

# 把后面三个维度放在一起,相当于变成4个一维数据,一维数据大小为784
print(image.reshape(4,28*28).shape)

# 把前面三个维度放在一起 4*28 = 112个一维的数据,一维数据大小为28
print(image.reshape(4*28, 28).shape)

# 把前两个维度放到一起
print(image.reshape(4*1,28,28).shape)

# 改变前后的size必须相同 错误示范:
# image.reshape(111,28)

# 改变图片的形状要符合一定意义,不然容易造成信息丢失,要记住原来图片的维度顺序
------------------------------------------------------------------------------
torch.Size([4, 1, 28, 28])
torch.Size([4, 784])
torch.Size([112, 28])
torch.Size([4, 28, 28])

unsqueeze和squeeze操作

分别代表展开和挤压
unsqueeze:

# 模拟手写数字识别操作
num_image = torch.rand((4,1,28,28))
print(num_image.shape)

# unsqueeze:展开
# 在第一个数之前插入一个维度  注意,如果是正数索引就是在当前索引之前插入,负数索引就是在当前索引之后插入
# 正数的范围[0,4] 负数的范围[-5,-1]
print(num_image.unsqueeze(0).shape)
print(num_image.unsqueeze(-5).shape)

# 在最后一个数之后插入一个维度
print(num_image.unsqueeze(4).shape)
print(num_image.unsqueeze(-1).shape)
------------------------------------------------------------------------------
torch.Size([4, 1, 28, 28])
torch.Size([1, 4, 1, 28, 28])
torch.Size([1, 4, 1, 28, 28])
torch.Size([4, 1, 28, 28, 1])
torch.Size([4, 1, 28, 28, 1])

例1:将a = torch.tensor([1.,2.])变成2维的数据,分别变成1行2列和2行1列的数据

a = torch.tensor([1.,2.])
print(a.shape)
# 1行2列
b = a.unsqueeze(0) # 或a.unsqueeze(-2)
print(b.shape)

# 2行1列
b = a.unsqueeze(1) # 或a.unsqueeze(-1)
print(b.shape)
------------------------------------------------------------------------------
torch.Size([2])
torch.Size([1, 2])
torch.Size([2, 1])

squeeze():

# 把所有size = 1的维度都挤压
print(b.squeeze().shape)

# 把第一个size = 1的维度挤压
print(b.squeeze(0).shape) #b.squeeze(-4).shape

# 把最后一个size = 1的维度挤压
print(b.squeeze(3).shape) #b.squeeze(-1).shape

# 一般只会挤压size = 1的维度,不等于1的维度挤压不了
print(b.squeeze(1).shape) # 没有完成挤压 
------------------------------------------------------------------------------
torch.Size([32])
torch.Size([32, 1, 1])
torch.Size([1, 32, 1])
torch.Size([1, 32, 1, 1])

expand、repeat

和扩展维度的unsqueeze不同,这两个操作用于扩充数据。
只有size = 1的维度能完成扩充,size ≠ 1的维度必须和原来size保持一致。

例2:有f和b两个参数,f = torch.rand(4,32,14,14), b = torch.rand(32) 实现f+b

# 需要先将b的维度扩展成4维
b = torch.rand([32])
print(b.shape)
b = b.unsqueeze(0).unsqueeze(2).unsqueeze(3)
print(b.shape)
------------------------------------------------------------------------------
torch.Size([32])
torch.Size([1, 32, 1, 1])

# 然后通过expand扩充数据
f = torch.rand(4,32,14,14)
print(b.shape)
print(b.expand(4,32,14,14).shape)
# 错误示范
# b.expand(4,64,14,14).shape  

# 如果某个维度不想发生变化,可以用-1表示
a = torch.rand((4,3,1,32))
print(a.expand(-1,3,32,-1).shape)
------------------------------------------------------------------------------
torch.Size([1, 32, 1, 1])
torch.Size([4, 32, 14, 14])
torch.Size([4, 3, 32, 32])

repeat是复制

print(b.shape)
# 如果要将b变成(4,64,12,1)该怎么做
print(b.repeat(4,2,12,1).shape)
------------------------------------------------------------------------------
torch.Size([1, 32, 1, 1])
torch.Size([4, 64, 12, 1])

t()、transpose()、permute()

t()代表转秩操作,只能对2D数据操作

a = torch.rand((2,3))
print(a.t().shape)
------------------------------------------------------------------------------
torch.Size([3, 2])

transpose()代表换位操作

a = torch.rand((4,3,32,32)) # (b,c,h,w)
# 用transpose交换之后如果要接view(),那么必须先进行contiguous()操作
# 如果使用reshape操作,就不需要用contiguous
a1 = a.transpose(1,3).reshape(4,3*32*32).reshape(4,3,32,32)
print(a1.shape)

# 如果需要交换a1中1和3的维度,之后再恢复成原来的维度,下面是一个错误示范
# 虽然没有报错,但这样拆出来的c可能就不是原来的c,会丢失原来的信息
a1 = a.transpose(1,3).contiguous().view(4,3*32*32).view(4,3,32,32)
print(a1.shape)

# 正确示范 手动追踪(b,c,h,w)的信息
a2 = a.transpose(1,3).contiguous().view(4,3*32*32).view(4,32,32,3).transpose(1,3)
print(a2.shape)

# 比较a和a1是否相等
print(torch.all(torch.eq(a,a1)))
# 比较a和a2是否相等
print(torch.all(torch.eq(a,a2)))
------------------------------------------------------------------------------
torch.Size([4, 3, 32, 32])
torch.Size([4, 3, 32, 32])
torch.Size([4, 3, 32, 32])
tensor(False)
tensor(True)

permute()操作

# 需求:image1 = torch.rand((4,3,32,28)),即(b,c,h,w),现在要把c放在最后,变成(b,h,w,c)
image1 = torch.rand((4,3,32,28))
# 方法1:可以通过transpose()完成
print(image1.transpose(1,3).transpose(1,2).shape)
# 方法2:通过permute()一步到位
print(image1.permute(0,2,3,1).shape)
------------------------------------------------------------------------------
torch.Size([4, 32, 28, 3])
torch.Size([4, 32, 28, 3])

拼接与拆分

拼接:cat和stack
cat:在某个维度上直接拼接

# 需求1:假设有5个班级,2个重点班A = torch.rand(2,50,6),3->5为普通班B = torch.rand(3,50,6)
# 模考后需要合并五个班级的成绩,如何实现?
A = torch.rand(2,50,6)
B = torch.rand(3,50,6)
grade = torch.cat([A,B],dim = 0)
print(grade.shape)
------------------------------------------------------------------------------
torch.Size([5, 50, 6])
# 需求2:想把3个batch的图片合并到一起,怎么做?
# 注意:除了拼接的size不一样,其他维度的size必须一样,否则报错
image1 = torch.rand(8,3,32,32)
image2 = torch.rand(16,3,32,32)
image3 = torch.rand(4,3,32,32)
new_batch_image = torch.cat([image1,image2,image3],dim = 0)
print(new_batch_image.shape)
------------------------------------------------------------------------------
torch.Size([28, 3, 32, 32])

stack: 会在dim维度之前增加一个维度并拼接, 要求两个张量的size必须完全相同

# 比较cat和stack的区别
a1 = torch.rand(4,3,16,32)
a2 = torch.rand(4,3,16,32)
print(torch.cat([a1,a2], dim=3).shape)
# 用stack操作
print(torch.stack([a1,a2], dim=3).shape)
------------------------------------------------------------------------------
torch.Size([4, 3, 16, 64])
torch.Size([4, 3, 16, 2, 32])
# 需求:excel中每一张sheet都代表一张表,如果想把两张表放在一起如何操作?
sheet1 = torch.rand(20,5)
sheet2 = torch.rand(20,5)
# 如果直接用cat,得到的是(40,5),这并不是我们想要的结果,此时就可以用stack
print(torch.stack([sheet1, sheet2], dim=0).shape)
------------------------------------------------------------------------------
torch.Size([2, 20, 5])

拆分:split和chunk
split:按照长度进行拆分

A = torch.rand(2, 50, 6)
B = torch.rand(3, 50, 6)
grade = torch.cat([A,B],dim=0)
print(grade.shape)

# 利用split进行拆分:可以直接指定每个单元的长度
# 直接指定单元长度,(2,3)也就是分成2,3两个部分
AA,BB = grade.split([2,3],dim=0)
print(AA.shape)
print(BB.shape)
# 也可以按照固定长度划分,如果按照固定长度2划分,就会变成(2,2,1)三份
# 注意事项:划分的时候一定要保持前后一致,拆分成几个部分,就用几个变量接收
------------------------------------------------------------------------------
torch.Size([5, 50, 6])
torch.Size([2, 50, 6])
torch.Size([3, 50, 6])

chunk:里面的参数是拆分成几部分的意思,同样拆分的部分要和变量的数量保持一致
chunk会平均拆分

print(grade.shape)
a,b,c = grade.chunk(3, dim=0)
print(a.shape)
print(b.shape)
print(c.shape)
------------------------------------------------------------------------------
torch.Size([5, 50, 6])
torch.Size([2, 50, 6])
torch.Size([2, 50, 6])
torch.Size([1, 50, 6])
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值