前言:《神经网络与PyTorch实战》读书笔记之PyTorch中的张量操作
1. PyTorch中的张量
- torch.Tensor类的常用成员:
- size() 返回张量大小
- dim() 返回张量维度
- numel() 返回张量中元素个数
>>> import torch
>>> tmp = torch.tensor([[1,2,3],[4,5,6]])
>>> tmp
tensor([[1, 2, 3],
[4, 5, 6]])
>>> tmp.reshape(3,2)
tensor([[1, 2],
[3, 4],
[5, 6]])
>>> tmp
tensor([[1, 2, 3],
[4, 5, 6]])
>>> tmp.size()
torch.Size([2, 3])
>>> tmp.dim()
2
>>> tmp.numel()
6
>>> tmp.dtype
torch.int64
2. 构造Tensor实例方法
-
torch.zeros(), torch.zeros_like()
-
>>> torch.zeros(3,4) tensor([[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]) >>> a=torch.tensor([1,2,3]) >>> torch.zeros_like(a) tensor([0, 0, 0]) >>>
-
-
torch.ones(), torch.ones_like()
-
>>> torch.ones(4,5) tensor([[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]]) >>> torch.ones_like(torch.zeros(3,4)) tensor([[1., 1., 1., 1.], [1., 1., 1., 1.], [1., 1., 1., 1.]]) >>>
-
-
torch.full(), torch.full_like()
-
两个参数,张量的大小和要填充的值
>>> torch.full((3,3),3) tensor([[3., 3., 3.], [3., 3., 3.], [3., 3., 3.]]) >>> torch.full_like(torch.zeros(3,4),3) tensor([[3., 3., 3., 3.], [3., 3., 3., 3.], [3., 3., 3., 3.]]) >>>
-
-
torch.empty(), torch.empty_like()
-
不指定具体的值
>>> torch.empty(2,2) tensor([[ 0.0000e+00, 0.0000e+00], [-3.7177e-36, 4.5912e-41]]) >>> torch.empty_like(torch.zeros(3,3)) tensor([[1.0561e-38, 1.0286e-38, 1.0653e-38], [1.0469e-38, 9.5510e-39, 6.2449e-39], [6.9796e-39, 8.4490e-39, 1.0561e-38]]) >>>
-
-
torch.eye()
-
>>> torch.eye(5,5) tensor([[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.], [0., 0., 1., 0., 0.], [0., 0., 0., 1., 0.], [0., 0., 0., 0., 1.]]) >>>
-
-
torch.arange(), torch.range(), torch.linspace(), torch.logspace()
扫描二维码关注公众号,回复: 9779868 查看本文章-
>>> torch.arange(2,10) tensor([2, 3, 4, 5, 6, 7, 8, 9]) >>> torch.arange(2,10,2) tensor([2, 4, 6, 8]) >>> torch.range(2,10,2) __main__:1: UserWarning: torch.range is deprecated in favor of torch.arange and will be removed in 0.5. Note that arange generates values in [start; end), not [start; end]. tensor([ 2., 4., 6., 8., 10.]) >>> torch.linespace(2,10,2) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: module 'torch' has no attribute 'linespace' >>> torch.linspace(2,10,2) tensor([ 2., 10.]) >>> torch.linspace(2,10,6) tensor([ 2.0000, 3.6000, 5.2000, 6.8000, 8.4000, 10.0000]) >>> torch.logspace(2,10,6) tensor([1.0000e+02, 3.9811e+03, 1.5849e+05, 6.3096e+06, 2.5119e+08, 1.0000e+10]) >>>
-
arange() 中第三个参数代表每隔几个进行一次取样
-
linspace(), logspace()中第三个参数代表一共取多少个样本
-
-
torch.bernoulli(), torch.multinomial(), torch.randperm(), torch.randint(), torch.randint_like() 随机向量
-
>>> probs = torch.full((3,4), 0.5) # 概率张量,有一定的概率取1 >>> torch.bernoulli(probs) tensor([[0., 1., 1., 1.], [0., 0., 1., 1.], [1., 1., 0., 0.]]) >>> torch.bernoulli(probs) tensor([[0., 0., 0., 0.], [1., 1., 0., 0.], [1., 0., 1., 0.]]) >>>
-
>>> import torch >>> weights=torch.tensor([[1,100],[100,1],[1,1]], dtype=torch.float32) >>> weights tensor([[ 1., 100.], [100., 1.], [ 1., 1.]]) >>> torch.multinomial(weights,1) tensor([[1], [0], [1]]) ps: 不知道有啥用
-
>>> torch.randperm(5, dtype=torch.float32) tensor([2., 0., 3., 1., 4.]) >>> 功能就是随机生成一个排列,参数只有一个n, 得到{0,1,2,..., n-1}一个排列
-
>>> torch.randint(low=0,high=4,size=(3,4)) tensor([[0, 2, 0, 1], [3, 2, 3, 1], [0, 1, 0, 0]]) >>> torch.randint_like(torch.ones(3,4), low=0, high=4) tensor([[0., 0., 0., 0.], [3., 3., 1., 3.], [2., 3., 0., 2.]]) 功能:[low,high)范围的数,生成独立同分布的离散均匀分布的张量
-
>>> torch.rand(2,3) tensor([[0.0408, 0.8364, 0.2955], [0.5750, 0.9387, 0.0326]]) >>> torch.rand_like(torch.ones(3,3)) tensor([[0.1841, 0.9014, 0.6892], [0.6298, 0.9209, 0.4046], [0.1707, 0.2002, 0.3489]]) >>> mean=torch.tensor([0.,1.]) >>> std=torch.tensor([3.,2.]) >>> torch.normal(mean,std) tensor([-1.4714, -0.3917]) >>>
-
3. 组织张量元素(重点)
张量的组织在深度学习中tensor的处理中非常常见,所以也是重中之重。
3.1 重排张量
- reshape(), squeeze(), unsqueeze(),不会改变元素的实际位置
- permute(), transpose(), t(), 可能会改变元素的实际位置
-
reshape() 方法
张量元素个数相同的情况下,改变张量的维度
>>> import torch >>> ts = torch.arange(12) >>> ts.reshape(3,4) tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> ts.reshape(3,4).size() torch.Size([3, 4]) >>> ts.reshape(-1,4).size() torch.Size([3, 4]) >>> ts.reshape(-1,2).size() # -1 代表可以通过其他维度进行计算 torch.Size([6, 2]) >>>
-
squeeze()方法
>>> t = torch.arange(24).reshape(2,1,3,4,1) >>> t.size() torch.Size([2, 1, 3, 4, 1]) >>> t.squeeze() tensor([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]) >>> t.squeeze().size() # 将 1 维度的挤压掉 torch.Size([2, 3, 4]) >>>
-
unsqueeze()方法
>>> t = torch.arange(24).reshape(2,3,4) >>> t.unsqueeze(dim=1).size() # 在第1维度进行 torch.Size([2, 1, 3, 4]) ### 举个例子 两张图片 >>> img = torch.ones([512,512,3]) >>> img.size() torch.Size([512, 512, 3]) >>> img = img.unsqueeze(dim=0) >>> img.size() torch.Size([1, 512, 512, 3]) >>> img2 = torch.ones([512,512,3]) >>> img2 = img2.unsqueeze(dim=0) >>> img2.size() torch.Size([1, 512, 512, 3])
-
permuate()方法:英文意思是排列,重新排列,进行张量的交换
>>> t = torch.arange(24).reshape(1,2,3,4) >>> t.permute(dims=[0,2,1,3]) tensor([[[[ 0, 1, 2, 3], [12, 13, 14, 15]], [[ 4, 5, 6, 7], [16, 17, 18, 19]], [[ 8, 9, 10, 11], [20, 21, 22, 23]]]]) >>> t.permute(dims=[0,2,1,3]).size() # 根据dims进行重排 torch.Size([1, 3, 2, 4]) >>>
-
transpose(),张量的交换可以用转置实现
>>> t.size() torch.Size([1, 2, 3, 4]) >>> t.transpose(0,3).size() torch.Size([4, 2, 3, 1]) # 互换0和3维度 >>>
3.2 选取部分张量
选取一个张量中部分元素,涉及index_select(), masked_select(), take()三个方法。
-
index_select() 方法有两个参数,dim 表示对哪个维度进行处理, index表示选取该维度哪些指标
>>> t = torch.arange(24).reshape(2,3,4) >>> index = torch.tensor([1,2]) >>> t.index_select(dim=1, index=index) tensor([[[ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[16, 17, 18, 19], [20, 21, 22, 23]]]) >>> t.index_select(dim=1, index=index).size() torch.Size([2, 2, 4]) >>>
-
masked_select() 只接受一个张量参数mask, 这个mask大小必须要跟作用对象相同,且类型必须为torch.uint8,且其中元素必须是0或者1,对应为1的部分就会被选择。
>>> t = torch.arange(12).reshape(3,4) >>> mask = torch.tensor([[1,0,0,1],[0,1,0,0],[0,0,0,0]]) >>> mask = torch.tensor([[1,0,0,1],[0,1,0,0],[0,0,0,0]], dtype=torch.uint8) >>> t.masked_select(mask) tensor([0, 3, 5]) >>> t tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>>
-
take() 不考虑张量大小,只考虑总个数,相当于对tensor进行reshape(-1)以后进行索引的结果。
>>> t = torch.arange(12).reshape(3,4) >>> t tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> indices = torch.tensor([3,4,5]) >>> t.take(indices) tensor([3, 4, 5]) >>> indices = torch.tensor([1,4,2]) >>> t.take(indices) tensor([1, 4, 2]) >>> # ps: 用的不多
3.3 张量扩展和拼接
这部分也很重要,讲解了各个方法操作以后会介绍一个简单的但很实用的例子。
主要涉及到三个方法:repeat(), cat(), stack()
-
repeat() 方法可以对张量内容进行复制,复制方法具体看例子:
>>> import torch >>> img = torch.ones(224,224) # 假如读入了单通道图片想要将其处理成三通道,就会用到repeat >>> img.size() torch.Size([224, 224]) >>> img = img.unsqueeze(2) >>> img.size() torch.Size([224, 224, 1]) >>> img = img.repeat(1,1,3) >>> img.size() torch.Size([224, 224, 3]) >>>
-
cat() 方法可以对张量内容进行拼接,有两个参数,第一个参数是一个张量列表,第二个参数就是指定根据哪个维度进行拼接。依然延续上一个例子,拼接多张图片。
>>> img1 = torch.ones(224) >>> img1 = torch.ones(224,224) >>> img2 =torch.ones(224,224) >>> img_list = torch.cat([img1,img2],2) Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: Dimension out of range (expected to be in range of [-2, 1], but got 2) >>> img1 = img1.unsqueeze(2) >>> img2 = img2.unsqueeze(2) >>> img_list = torch.cat([img1,img2],2) >>> img_list.size() torch.Size([224, 224, 2]) >>>
-
stack()方法与cat()方法不同之处在于stack()要求输入张量大小完全相同, 也可以看出来有其他地方不太一样。
>>> img_list2 = torch.stack([img1,img2],2) >>> img_list2.size() torch.Size([224, 224, 2, 1]) >>> img1.size() torch.Size([224, 224, 1]) >>> img2.size() torch.Size([224, 224, 1]) >>> img_list2 = torch.stack([img1,img2, img1, img2],2) >>> img_list2.size() torch.Size([224, 224, 4, 1]) >>> tp = torch.arange(12).reshape(3,4) >>> tp.size() torch.Size([3, 4]) >>> tn=-tp >>> tn.size() torch.Size([3, 4]) >>> ts0 = torch.stack([tn,tp], 0) >>> ts0.size() torch.Size([2, 3, 4]) >>> ts1 = torch.stack([tn,tn, tp, tp],1) >>> ts1.size() torch.Size([3, 4, 4]) >>>
-
3.4 torch内置统计函数
主要有mean(), sum(), std(), var(), prod(), max(), min(), median(), kthvalue(), norm()
举例:
>>> t = torch.arange(5)
>>> t
tensor([0, 1, 2, 3, 4])
>>> t.mean() # 这里报错是因为不支持Long类型,使用dtype进行类型转化即可。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: Can only calculate the mean of floating types. Got Long instead.
>>> t = torch.arange(5, dtype=torch.float32)
>>> t.mean()# 平均值
tensor(2.)
>>> t.var()# 方差
tensor(2.5000)
>>> t.sum()# 求和
tensor(10.)
>>> t.std()# 标准差
tensor(1.5811)
>>> t.median()#中位数
tensor(2.)
>>> t.kthvalue(3)#第k大值
torch.return_types.kthvalue(
values=tensor(2.),
indices=tensor(2))
>>> t.max()# 最大值
tensor(4.)
>>> t.min()# 最小值
tensor(0.)
>>> t.norm()# 范数
tensor(5.4773)
针对某个维度进行处理:
>>> t = torch.arange(12, dtype=torch.float32).reshape(2,2,3)
>>> t.var(dim=1) # 求某维度的方差
tensor([[4.5000, 4.5000, 4.5000],
[4.5000, 4.5000, 4.5000]])
>>> t.prod(dim=1) # 求某一维度积
tensor([[ 0., 4., 10.],
[54., 70., 88.]])
>>> t.max(dim=1) # 求某一维度最大值
torch.return_types.max(
values=tensor([[ 3., 4., 5.],
[ 9., 10., 11.]]),
indices=tensor([[1, 1, 1],
[1, 1, 1]]))
>>> t.median(dim=1) # 求中位数
torch.return_types.median(
values=tensor([[0., 1., 2.],
[6., 7., 8.]]),
indices=tensor([[0, 0, 0],
[0, 0, 0]]))
>>> t.cumsum(dim=1) # 累计求和
tensor([[[ 0., 1., 2.],
[ 3., 5., 7.]],
[[ 6., 7., 8.],
[15., 17., 19.]]])
>>> t.cumprod(dim=1) #累乘
tensor([[[ 0., 1., 2.],
[ 0., 4., 10.]],
[[ 6., 7., 8.],
[54., 70., 88.]]])
>>>
后记:暂且先写这么多,主要的用法,都已经写上了,后期遇到更多内容也会添加进来,欢迎在评论区讨论。