torchTensor学习:切⽚操作
torch Tensor学习:切⽚操作
to rch Tenso r Slice
⼀直使⽤的是matlab处理矩阵,想从matlab转到lua+torch上,然⽽在matrix处理上遇到了好多类型不匹配问题。所以这⾥主要总结⼀下torch/Tensor中切⽚操作⽅法以及其参数类型,以备查询。
已知有矩阵M
M=torch.range(1,20):resize(4,5)
th> M
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
[torch.DoubleTensor of size 4x5]
这⾥需要注意的是 resize() 和reshape()的区别, M:reshape(5,4)并不改变M,但是M:resize(5,4)改变M的size
1. 选取M的第2,3列
N1=M:narrow(2,2,2)resize函数c++
-- [self] narrow (dim,index,size) --> dim表⽰待选取的维度,index 是待选取连续列的起始数值, size是选取的列数,那么总体就是在第⼆维上从第2列选取连续的2列
N2=M:sub(1,-1,2,3)
-- [Tensor] sub(dim1s,dim1e ...[,dim4s [,dim4e]])
--dim1s,dim1e 分别对应第⼀维上的起始index和终⽌index,-1表⽰该维度倒数第⼀个...以此类推
N3=M[{{},{2,3}}]
另外
[Tensor] select(dim,index) :在第dim维选取第index"⾏",这只能取⼀个切⽚
需要注意的⼏点:
A. sub, narrow, select, [] 函数都是在原始的数据上进⾏操作的,也就是说获得的Tensor都仅仅是⼀个视图⽽已,改变其中⼀个另⼀个也会变化
B. 因为A的原因,这⼏个函数执⾏的速度⾮常快(对于这点深有体会,torch中Tensor操作速度蛮快的,但是涉及到内存分配,速度有点慢)
C. sub,narrow,select 都是选取Tensor⼀块数据,⽽不能选取特定的值,⽐如⼀次性选取上述矩阵M的第1⾏第2列,第2⾏第4列 和第4⾏第1列的值
C. [Tensor][{dim1,dim2}] or [{{dim1s,dim1e},{dim2s,dim2e}}] 的输⼊量还可以是ByteTensor类型,由0,1元素组成的掩码矩阵,⽐如
M[torch.lt(M,8)] =0--令M中⼩于8的元素为0
th> M
0 0 0 0 0
0 0 8 9 10
11 12 13 14 15
16 17 18 19 20
[torch.DoubleTensor of size 4x5]
注: 逻辑操作:lt, gt, le, eq, ge,ne返回的都是ByteTensor类型的掩码Tensor
2. 针对于上边提到的注意点C,如果想选取第dim维上的某⼏个不连续的“⾏”
例如 选取M的第2,5,3,1列构成新的矩阵
注: [] 操作是⼀系列narrow,select,sub的组合,其并不涉及新内存,⽽index则涉及到新内存的分配
index的相关函数
a. indexCopy
b. indexAdd
c. indexFill
[Tensor] indexFill(dim, indices,var) -- 和indexCopy相同,只是使⽤var去填充indices对应的元素,在原Tensor内存上改变
总结:
A. index相关的函数中只有index是重新开辟的内存,⽽indexCopy,indexFill,indexAdd均是在原内存上操作
B. index相关函数仅仅能在某⼀个特定维度dim上,相对⾃由的选取indices,⽽不能同时操作多个维度
C. index相关函数中 indices参数的类型为LongTensor尤其要注意
3. tensor中元素的⾃由选取和赋值
a. gather
[Tensor] gather (dim,indices) -- ⾸先这个函数需要重新分配内存
。-- 该函数的功能主要是沿着dim维度,在每⼀个row上按照indices选取数值,indices为LongTensor类
型看下⾯官⽅⽂档的图⽰更好理解
N1=M:index(2,torch.LongTensor({2,5,3,1}))
-- [Tensor] index(dim,indices) 在矩阵M 中选取dim 维上索引indices 中对应的"⾏",indices 的类型要求为LongTensor
-- 返回Tensor 的number of dimensions 和原始Tensor 相同,返回的是新分配的内存
-- [Tensor] indexCopy(dim,indices,tensor) -- 将tensor 中的元素拷贝到原tensor 对应indices 上去,tensor 和带存储的⼤⼩应该严格⼀致
N=torch.Tensor(4,2):fill(-1)
M:indexCopy(2,torch.LongTensor{4,1},N) -- 这个返回的是N ,但M 变化了
th> M
-1 2 3 -1 5
-1 7 8 -1 10
-1 12 13 -1 15
-1 17 18 -1 20
[torch.DoubleTensor of size 4x5]
-- [Tensor] indexAdd(dim,indices,tensor) 和indexCopy 类似,只是在原tensor 的indices 对应的位置加上tensor
M:indexAdd(2,torch.LongTensor{1,3},-N) --返回的是-N
th> M
0 2 4 -1 5
0 7 9 -1 10
0 12 14 -1 15
0 17 19 -1 20
[torch.DoubleTensor of size 4x5
]
1486728865883.jpg
左图是: result=src:gatter(1,index), index=torch.LongTensor({{1,2,3},{2,3,1}})
其输出result的⼤⼩和index相同,result[{1,{}}]为src每⼀列上的index[{{1},{}}]对应的元素,为什么是列呢,因为dim=1,决定了沿着row数,也就是列了。 后⾯的类似
注意:因为dim=1,所以index的第⼆维长度应该和src的dim=2长度相同
b. scatter
[Tensor] scatter(dim,indices,src|var)
这个函数和gatter是⼀组的,gather是取元素,scatter是元素赋值,其indices查⽅式相同。待赋值可以使Tensor src 也可以是标量var
同样有新的内存分配发⽣
c. maskedSelect
[Tensor] maskedSelect(mask)
。-- mask 是ByteTensor类型的掩码矩阵或者向量,元素为0或1. mask并不要求size和src相同,但元素个数必须相同。。--返回的是mask中元素1对应的src中元素,长度和mask中1的个数相同,元素类型和src类型相同,ndim=1
d. maskedCopy
[Tensor] maskedCopy(mask,tensor)
。--和maskedSelect的关系,就和index与indexCopy的关系,对掩码确定的元素进⾏赋值
e. maskedFill
[Tensor] maskedFill(mask,val)
。 --类⽐index和indexFill
3. 总结
A: mask都是ByteTensor类型,indices都是LongTensor类型
B: view操作的有 narrow, sub,select 和 [ ]
C: 重新分配内存的有 index,gatter,maskedSelect
D: 不牵涉到内存的重新分配能够⼤⼤提升程序的效率
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论