torch Tensor學習:切片操作
一直使用的是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
- 選取M的第2,3列
N1=M:narrow(2,2,2)
-- [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
- 針對於上邊提到的注意點C,如果想選取第dim維上的某幾個不連續的“行”
例如 選取M的第2,5,3,1列構成新的矩陣
N1=M:index(2,torch.LongTensor({2,5,3,1}))
-- [Tensor] index(dim,indices) 在矩陣M中選取dim維上索引indices中對應的"行",indices的類型要求為LongTensor
-- 返回Tensor的number of dimensions 和原始Tensor相同,返回的是新分配的內存
注: [] 操作是一系列narrow,select,sub的組合,其並不涉及新內存,而index則涉及到新內存的分配
index的相關函數
a. indexCopy
-- [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]
b. indexAdd
-- [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]
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!!!尤其要注意
- tensor中元素的自由選取和賦值
a. gather
[Tensor] gather (dim,indices) -- 首先這個函數需要重新分配內存
。-- 該函數的功能主要是沿着dim維度,在每一個row上按照indices選取數值,indices為LongTensor類型
看下面官方文檔的圖示更好理解
左圖是: 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
- 總結
A: mask都是ByteTensor類型,indices都是LongTensor類型
B: view操作的有 narrow, sub,select 和 [ ]
C: 重新分配內存的有 index,gatter,maskedSelect
D: 不牽涉到內存的重新分配能夠大大提升程序的效率
