本文参加新星计划人工智能(Pytorch)赛道: https://bbs.csdn.net/topics/613989052
承接上文:自己深度学习环境搭建和免费环境使用+Tensor构造+Tensor基本操作: 从 X 入门深度学习(Pytorch版本)
1 Tensor的索引和切片
汇总:
Name | Out |
---|---|
a[i, j, k, …] = a[i][j][k][…] | 获取张量a的具体数据 |
a[start : end : step, start1 : end1 : step1, ] | 获取张量a第一维[start, end)步长为step的数据,第二维类似,详情看例子1-3 |
a[…, start : end : step] | 获取张量a前面维度所有数据,只针对最后维度数据进行切片,详情看例子4 |
布尔索引 | 详情看例子5 |
整数索引 | 详情看例子6 |
torch.nonzero() | 获得数据中非0的位置 详情看例子7 |
torch.where(condition, x, y) | conditon成立是,使用x中的数据,否则使用y中的数据,见例子8 |
a为高维张量
例子:
获取张量中的一个具体数据:
import torch
x = torch.randint(0,24, (2, 3, 4))
print(x)
print(x[1,2,3], x[1][2][3], x[1][2])
out:
tensor([[[ 3, 16, 17, 16],
[ 0, 20, 15, 19],
[23, 16, 3, 11]],
[[20, 20, 18, 0],
[13, 6, 19, 15],
[ 3, 20, 0, 18]]])
tensor(18) tensor(18) tensor([ 3, 20, 0, 18])
切片
以前也知道,但是一直没太搞清楚,这次重新学了一下,大概把规律都掌握了:
一般都是使用start : end : step来表示获取的数据范围,范围是前闭后开,step表示步长,Pytorch不支持负步长,但是支持负索引,-1指的是该维度下的最后一个索引,结合张量索引的知识点,你把他放在那个维度上,它就对那个维度起作用。
例子1:含有步长的切片
x = torch.arange(0,24).view(2,3,4)
print(x)
print(x[:, 0:3:2, ]) # 获取的是第二维上索引为0,2的数据
out:
例子2:不含有步长的切片,同时使用两种方式联合的索引
x = torch.arange(0,24).view(2,3,4)
print(x)
print(x[0][0:2]) # 获取的是第一维下的0索引后第二维下索引为0,1的全部数据 等价与x[0, 0:2]
例子3:含有负索引的切片
x = torch.arange(0,24).view(2,3,4)
print(x)
print(x[0, 0:2, 0:-1:2]) # 重点可以看一下第三维
例子4:前面维度我都要,针对最后维度的数据进行切片
x = torch.arange(0,2*3*4*5).view(2,3,4,5)
print(x)
print(x[...,0:2, 0:5:2])
例子5:布尔索引
x = torch.arange(0, 9).view(3, 3)
# x4 = torch.ones(3,3)*4
print(x) # 0-8的二维张量
index = x > 4 # 判断位置对应位置上是否大于数据4, 类似于对4进行广播成和x相同维度的数据,然后逐元素比大小
# index4 = x >x4
# print(index4)
print(index)
print(x[index]) # 针对位置值为True的数据进行获取, 获取后的数据组成一维数据
print("**************")
y = torch.randint(0,9,(3, 3))
dex = y > 4
print(y)
print(y[dex])
例子6:整数索引
x = torch.arange(0, 9).view(3, 3)
print(x)
rows = [0,1]
cols = [1,2]
print(x[rows, cols]) # 获取的数据是(0,1)和(1,2)位置上的数据组成的一维张量
例子7: torch.nonzero()这个在单目标分割中,计算评价指标和部分损失函数时会遇到
x = torch.randint(0,2,(1,2,3,4))
print(x)
index = torch.nonzero(x) # 得到x中非0数据的位置信息,同时将每个位置组成一个一维数据,一共是二维张量
print(index)
print(len(index), index.shape)
例子8: torch.where(condition, x, y) 使用
x = torch.randn(4,3)
y = torch.ones(4,3)
m = torch.where(x>0, x, y) # 这里的condition可以不用x,只需要和x,y相同维度的数据就可以了,功能类似于将布尔索引的高级使用
print(x)
print(y)
print(m)
print("使用布尔索引完成上述例子")
index = x > 0 # condition
print(index) # 得到位置信息
for i in range(len(x)):
for j in range(len(x[i])):
if index[i, j]:
m[i, j] = x[i, j]
else:
m[i, j] = y[i, j]
print(m)
2 Tensor的转换
汇总:
Name | Out |
---|---|
a.nelement() | 返回元素个数 |
a.ndimension() | 返回张量轴的个数 |
a.size() | 返回张量维度信息 |
a.shape | 返回张量维度信息 |
a.viw(i, j, …) | 对a进行数据维度变换,修改返回值,原始值也改变 ,实际中这个用的多 |
a.reshape(i, j, k) | 对a进行数据维度变换,修改返回值,原始值不一定改变 |
以上两个中的参数允许存在最多一个 -1 | 用来通过已确定的维度,计算-1位置上的维度,见例2 |
torch.squeeze(a) | 去掉a中维度为1的轴, 不指定就去掉所有,指定就去掉指定位置的,见例3 |
torch.unsqueeze(b, i) | 在b中i的位置田间一个维度为1的轴,见例4 |
torch.transpose(b, 1, 0) | 将b的维度调换位置,类似于二维矩阵的转置操作,见例5 |
torch.t(b) | 是transpose的简化书写 |
a.permute(i, j, k,…) | 将a中数据的位置按照i,j,k的位置进行重现调整,类似于高维矩阵的转置操作,见例6 |
a为高维张量, b是二维张量
例子1:
a = torch.rand(3,4,5,6,7)
print("元素个数:", a.nelement())
print("轴的个数:", a.ndimension())
print("维度信息:", a.size())
print("维度信息:", a.shape)
out:
元素个数: 2520
轴的个数: 5
维度信息: torch.Size([3, 4, 5, 6, 7])
维度信息: torch.Size([3, 4, 5, 6, 7])
例子2:使用-1进行维度推算
a = torch.randint(0,3,(3, 4))
print(a, a.shape)
b = a.view(-1,2)
print(b, b.shape)
out:
tensor([[0, 2, 0, 1],
[2, 2, 0, 0],
[1, 0, 0, 0]]) torch.Size([3, 4])
tensor([[0, 2],
[0, 1],
[2, 2],
[0, 0],
[1, 0],
[0, 0]]) torch.Size([6, 2])
例3:去掉张量中维度为1的轴
x = torch.randint(0,2, (1,1,1,2,4,1,1))
print(x.shape)
print(torch.squeeze(x, 2).shape)
print(torch.squeeze(x).shape)
out:
torch.Size([1, 1, 1, 2, 4, 1, 1])
torch.Size([1, 1, 2, 4, 1, 1])
torch.Size([2, 4])
例4: 给张量指定位置添加一个维度为1的轴
x = torch.randint(0,2,(3, 4))
print(x.shape)
print(torch.unsqueeze(x, 1).shape)
out:
torch.Size([3, 4])
torch.Size([3, 1, 4])
例5: 二维张量的转置操作
x = torch.arange(0,12).view(2,6)
print(x)
print("view操作,将数据重新写一下:\n",x.view(6, 2)) #注意二维张量的转置和View的区别
print("转置操作,将数据按照原来维度进行调换:\n",torch.transpose(x, 1, 0)) #注意二维张量的转置和View的区别
print("转置操作,将数据按照原来维度进行调换:\n",torch.t(x)) # torch.t是简化书写
out:
tensor([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11]])
view操作,将数据重新写一下:
tensor([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11]])
转置操作,将数据按照原来维度进行调换:
tensor([[ 0, 6],
[ 1, 7],
[ 2, 8],
[ 3, 9],
[ 4, 10],
[ 5, 11]])
转置操作,将数据按照原来维度进行调换:
tensor([[ 0, 6],
[ 1, 7],
[ 2, 8],
[ 3, 9],
[ 4, 10],
[ 5, 11]])
例6:高维数据的转置
x = torch.randn(3,4,2,5)
print(x.shape)
y = x.permute(1,0,2,3) # 一定要注意区分view和转置的区别
print(y.shape)
out:
torch.Size([3, 4, 2, 5])
torch.Size([4, 3, 2, 5])
3 Tensor的拼接
汇总:
Name | Out |
---|---|
torch.cat((a, b) , dim=) | 在已有的轴上拼接矩阵,默认轴为0,给定轴的维度可以不同,其余轴的维度必须相同 |
torch.stack((a, b) , dim=) | 在新的轴上拼接,默认轴为0,要求被拼接的轴的维度都相同 |
a, b 的轴最多只有一个可以不同
例子:torch.cat
import torch
a = torch.arange(0,6).view(2,3)
b = torch.ones(2,4)
print(a)
print(b)
# torch.cat
c = torch.cat([a,b],dim=1)
print("a和b在指定的轴上拼接\n", c)
d = torch.cat((a, a))
print("a和a在默认的轴上拼接\n", d)
out:
tensor([[0, 1, 2],
[3, 4, 5]])
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.]])
a和b在指定的轴上拼接
tensor([[0., 1., 2., 1., 1., 1., 1.],
[3., 4., 5., 1., 1., 1., 1.]])
a和a在默认的轴上拼接
tensor([[0, 1, 2],
[3, 4, 5],
[0, 1, 2],
[3, 4, 5]])
例子:torch.stack()
这个用法还是很抽象的,建议从结果倒退结果,最直观的是最后两个维度的呈现:
import torch
a = torch.arange(0,6).view(2,3)
b = torch.ones(2,3)
print(a, a.shape)
print(b, b.shape)
# torch.cat
c = torch.stack([a,b],dim=2)
print("a和b在指定的轴上拼接\n", c, c.shape)
d = torch.stack((a, a))
print("a和a在默认的轴上拼接\n", d, d.shape)
out:
tensor([[0, 1, 2],
[3, 4, 5]]) torch.Size([2, 3])
tensor([[1., 1., 1.],
[1., 1., 1.]]) torch.Size([2, 3])
a和b在指定的轴上拼接
tensor([[[0., 1.],
[1., 1.],
[2., 1.]],
[[3., 1.],
[4., 1.],
[5., 1.]]]) torch.Size([2, 3, 2])
a和a在默认的轴上拼接
tensor([[[0, 1, 2],
[3, 4, 5]],
[[0, 1, 2],
[3, 4, 5]]]) torch.Size([2, 2, 3])
4 Tensor的拆分
汇总:
Name | Out |
---|---|
torch.split(a, list, dim=) | 传入的是拆分后维度的大小,可以传入list,也可以传入整数,不够的放最后 |
torch.chunk(a, x, dim=) | 传入的是拆分的矩阵个数 |
a 是高维张量,list为列表,x为整数
例子:torch.split()
import torch
a = torch.randn(10, 3)
print("传入的是维度大小列表:")
for x in torch.split(a, [1, 2, 3, 4], dim=0):
print(x.shape)
print("传入的是维度大小整数:")
for x in torch.split(a, 4, dim=0): # 注意返回值是由tensor组成的元组
print(x.shape)
out:
传入的是维度大小列表:
torch.Size([1, 3])
torch.Size([2, 3])
torch.Size([3, 3])
torch.Size([4, 3])
传入的是维度大小整数:
torch.Size([4, 3])
torch.Size([4, 3])
torch.Size([2, 3])
例子:torch.chunk()
import torch
a = torch.randn(15, 6)
print("传入的是拆分后的个数:")
for x in torch.chunk(a, 3, dim=1):
print(x.shape)
out:
传入的是拆分的个数:
torch.Size([15, 2])
torch.Size([15, 2])
torch.Size([15, 2])
5 Tensor的规约操作
汇总:
Name | Out |
---|---|
torch.max(a, dim=) | 计算a中指定轴的最大值,默认是求最大值(不返回地址),指定轴返回(最大值,最大值位置) |
torch.cumsum(a, dim=) | 沿着指定轴计算累加 |
torch.cumprod(a, dim=) | 沿着指定轴计算累乘 |
a.mean() | 求均值 |
a.median | 求中值 |
a.std() | 求协方差 |
a.max() | 求最大值 |
torch.unique(a) | 寻找张量a中出现了哪些元素 |
a为高维张量
例子1:torch.max()
a = torch.tensor([[3,1],[4,7]])
print(a)
print(torch.max(a)) # 全局最大值
print(torch.max(a, dim=1)) # 在第二维度上找最大值,同时返回其位置(除指定轴外的位置,例返回【0,1】和指定轴1组成了位置信息,[0,1]和[1,1])
out:
tensor([[3, 1],
[4, 7]])
tensor(7)
torch.return_types.max(
values=tensor([3, 7]),
indices=tensor([0, 1]))
例子2:torch.cumsum()
a = torch.tensor([[3,1,3],[4,7,4],[4,5,2]])
print(a)
print(torch.cumsum(a, dim=1)) # 按照横轴计算每一列的累加,然后放在对应的位置上
例子3: torch.cumprod()
a = torch.tensor([[3,1,3],[4,7,4],[4,5,2]])
print(a)
print(torch.cumprod(a, dim=0)) # 按照列轴计算每一行的累乘,然后放在对应的位置上
例子4:a.mean(), a.std()等文章来源:https://www.toymoban.com/news/detail-770623.html
a = torch.tensor([[3,1,3],[4,7,4],[4,5,2]], dtype=torch.float)
print(a)
print("未指定轴,则计算全局的相关信息:")
print(a.max(), a.std(), a.median(), a.mean())
print("输出指定轴下的信息:")
print("Max_out:", a.max(dim=1),"\n ***") # 返回最大值 及 位置
print("Str_out:", a.std(dim=1),"\n ***") # 返回协方差信息
print("Median_out:", a.median(dim=1),"\n ***") # 返回中间值 及 位置
print("Mean_out:", a.mean(dim=1),"\n ***") # 返回均值
例子5:torch.unique()文章来源地址https://www.toymoban.com/news/detail-770623.html
x = torch.randint(0,15,(3,3))
print(x)
print(torch.unique(x)) # 得到x中出现的元素
out:
tensor([[14, 3, 4],
[ 2, 3, 7],
[12, 0, 6]])
tensor([ 0, 2, 3, 4, 6, 7, 12, 14])
到了这里,关于从 X 入门Pytorch——Tensor的索引,切片,拼接,拆分,Reduction操作的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!