torch Tensor學習:切片操作


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

  1. 選取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

  1. 針對於上邊提到的注意點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!!!尤其要注意

  1. tensor中元素的自由選取和賦值
    a. gather
    [Tensor] gather (dim,indices) -- 首先這個函數需要重新分配內存
    。-- 該函數的功能主要是沿着dim維度,在每一個row上按照indices選取數值,indices為LongTensor類型
    看下面官方文檔的圖示更好理解

enter description here

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

  1. 總結
    A: mask都是ByteTensor類型,indices都是LongTensor類型
    B: view操作的有 narrow, sub,select 和 [ ]
    C: 重新分配內存的有 index,gatter,maskedSelect
    D: 不牽涉到內存的重新分配能夠大大提升程序的效率


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM