import torch as t
t.__version__
'2.1.1'
從接口的角度來講,對(duì)tensor的操作可分為兩類:
-
torch.function
,如torch.save
等。 - 另一類是
tensor.function
,如tensor.view
等。
為方便使用,對(duì)tensor的大部分操作同時(shí)支持這兩類接口,如torch.sum (torch.sum(a, b))
與tensor.sum (a.sum(b))
功能等價(jià)。
而從存儲(chǔ)的角度來講,對(duì)tensor的操作又可分為兩類:
- 不會(huì)修改自身的數(shù)據(jù),如
a.add(b)
, 加法的結(jié)果會(huì)返回一個(gè)新的tensor。 - 會(huì)修改自身的數(shù)據(jù),如
a.add_(b)
, 加法的結(jié)果仍存儲(chǔ)在a中,a被修改了。
函數(shù)名以_
結(jié)尾的都是inplace方式, 即會(huì)修改調(diào)用者自己的數(shù)據(jù),在實(shí)際應(yīng)用中需加以區(qū)分。
1.1 創(chuàng)建Tensor
在PyTorch中新建tensor的方法有很多。
表1-1: 常見新建tensor的方法
函數(shù) | 功能 |
---|---|
Tensor(*sizes) | 基礎(chǔ)構(gòu)造函數(shù) |
tensor(data,) | 類似np.array的構(gòu)造函數(shù) |
ones(*sizes) | 全1Tensor |
zeros(*sizes) | 全0Tensor |
eye(*sizes) | 對(duì)角線為1,其他為0 |
arange(s,e,step) | 從s到e,步長為step |
linspace(s,e,steps) | 從s到e,均勻切分成steps份 |
rand/randn(*sizes) | 均勻/標(biāo)準(zhǔn)分布 |
normal(mean,std)/uniform(from,to) | 正態(tài)分布/均勻分布 |
randperm(m) | 隨機(jī)排列 |
這些創(chuàng)建方法都可以在創(chuàng)建的時(shí)候指定數(shù)據(jù)類型dtype和存放device(cpu/gpu).
其中使用Tensor
函數(shù)新建tensor是最復(fù)雜多變的方式,它既可以接收一個(gè)list,并根據(jù)list的數(shù)據(jù)新建tensor,也能根據(jù)指定的形狀新建tensor,還能傳入其他的tensor,下面舉幾個(gè)例子。
# 指定tensor的形狀
a = t.Tensor(2, 3)
a # 數(shù)值取決于內(nèi)存空間的狀態(tài),print時(shí)候可能overflow
tensor([[-1.0752245760e+09, 1.4601529998e-42, 1.4012984643e-45],
[ 0.0000000000e+00, 1.4012984643e-45, 0.0000000000e+00]])
# 用list的數(shù)據(jù)創(chuàng)建tensor
b = t.Tensor([[1,2,3],[4,5,6]])
b
tensor([[1., 2., 3.],
[4., 5., 6.]])
b.tolist() # 把tensor轉(zhuǎn)為list
[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
tensor.size()
返回torch.Size
對(duì)象,它是tuple的子類,但其使用方式與tuple略有區(qū)別
b_size = b.size()
b_size
torch.Size([2, 3])
b.numel() # b中元素總個(gè)數(shù),2*3,等價(jià)于b.nelement()
6
# 創(chuàng)建一個(gè)和b形狀一樣的tensor
c = t.Tensor(b_size)
# 創(chuàng)建一個(gè)元素為2和3的tensor
d = t.Tensor((2, 3))
c, d
(tensor([[1.4012984643e-45, 0.0000000000e+00, 1.4012984643e-45],
[0.0000000000e+00, 1.4012984643e-45, 0.0000000000e+00]]),
tensor([2., 3.]))
除了tensor.size()
,還可以利用tensor.shape
直接查看tensor的形狀,tensor.shape
等價(jià)于tensor.size()
c.shape
torch.Size([2, 3])
需要注意的是,t.Tensor(*sizes)
創(chuàng)建tensor時(shí),系統(tǒng)不會(huì)馬上分配空間,只是會(huì)計(jì)算剩余的內(nèi)存是否足夠使用,使用到tensor時(shí)才會(huì)分配,而其它操作都是在創(chuàng)建完tensor之后馬上進(jìn)行空間分配。其它常用的創(chuàng)建tensor的方法舉例如下。
t.ones(2, 3)
tensor([[1., 1., 1.],
[1., 1., 1.]])
t.zeros(2, 3)
tensor([[0., 0., 0.],
[0., 0., 0.]])
t.arange(1, 6, 2)
tensor([1, 3, 5])
t.linspace(1, 10, 3)
tensor([ 1.0000000000, 5.5000000000, 10.0000000000])
t.randn(2, 3, device=t.device('cpu'))
tensor([[-1.1603765488, -1.2580411434, -0.3872119784],
[-0.9962984324, -2.3714294434, -1.5460534096]])
t.randperm(5) # 長度為5的隨機(jī)排列
tensor([1, 4, 0, 2, 3])
t.eye(2, 3, dtype=t.int) # 對(duì)角線為1, 不要求行列數(shù)一致
tensor([[1, 0, 0],
[0, 1, 0]], dtype=torch.int32)
torch.tensor
是在0.4版本新增加的一個(gè)新版本的創(chuàng)建tensor方法,使用的方法,和參數(shù)幾乎和np.array
完全一致
scalar = t.tensor(3.14159)
print('scalar: %s, shape of sclar: %s' %(scalar, scalar.shape))
scalar: tensor(3.1415901184), shape of sclar: torch.Size([])
vector = t.tensor([1, 2])
print('vector: %s, shape of vector: %s' %(vector, vector.shape))
vector: tensor([1, 2]), shape of vector: torch.Size([2])
tensor = t.Tensor(1,2) # 注意和t.tensor([1, 2])的區(qū)別
tensor.shape
torch.Size([1, 2])
matrix = t.tensor([[0.1, 1.2], [2.2, 3.1], [4.9, 5.2]])
matrix,matrix.shape
(tensor([[0.1000000015, 1.2000000477],
[2.2000000477, 3.0999999046],
[4.9000000954, 5.1999998093]]),
torch.Size([3, 2]))
t.tensor([[0.11111, 0.222222, 0.3333333]],
dtype=t.float64,
device=t.device('cpu'))
tensor([[0.1111100000, 0.2222220000, 0.3333333000]], dtype=torch.float64)
empty_tensor = t.tensor([])
empty_tensor.shape
torch.Size([0])
1.2 常用Tensor操作
通過tensor.view
方法可以調(diào)整tensor的形狀,但必須保證調(diào)整前后元素總數(shù)一致。view
不會(huì)修改自身的數(shù)據(jù),返回的新tensor與源tensor共享內(nèi)存,也即更改其中的一個(gè),另外一個(gè)也會(huì)跟著改變。在實(shí)際應(yīng)用中可能經(jīng)常需要添加或減少某一維度,這時(shí)候squeeze
和unsqueeze
兩個(gè)函數(shù)就派上用場了。
a = t.arange(0, 6)
a.view(2, 3)
tensor([[0, 1, 2],
[3, 4, 5]])
b = a.view(-1, 3) # 當(dāng)某一維為-1的時(shí)候,會(huì)自動(dòng)計(jì)算它的大小
b.shape
torch.Size([2, 3])
b.unsqueeze(1) # 注意形狀,在第1維(下標(biāo)從0開始)上增加“1”
#等價(jià)于 b[:,None]
b[:, None].shape
torch.Size([2, 1, 3])
b.unsqueeze(-2) # -2表示倒數(shù)第二個(gè)維度
tensor([[[0, 1, 2]],
[[3, 4, 5]]])
c = b.view(1, 1, 1, 2, 3)
c.squeeze(0) # 壓縮第0維的“1”
tensor([[[[0, 1, 2],
[3, 4, 5]]]])
c.squeeze() # 把所有維度為“1”的壓縮
tensor([[0, 1, 2],
[3, 4, 5]])
a[1] = 100
b # a修改,b作為view之后的,也會(huì)跟著修改
tensor([[ 0, 100, 2],
[ 3, 4, 5]])
resize
是另一種可用來調(diào)整size
的方法,但與view
不同,它可以修改tensor的大小。如果新大小超過了原大小,會(huì)自動(dòng)分配新的內(nèi)存空間,而如果新大小小于原大小,則之前的數(shù)據(jù)依舊會(huì)被保存,看一個(gè)例子。
b.resize_(1, 3)
b
tensor([[ 0, 100, 2]])
b.resize_(3, 3) # 舊的數(shù)據(jù)依舊保存著,多出的大小會(huì)分配新空間
b
tensor([[ 0, 100, 2],
[ 3, 4, 5],
[ 0, 0, 0]])
1.3 索引操作
Tensor支持與numpy.ndarray類似的索引操作,語法上也類似,下面通過一些例子,講解常用的索引操作。如無特殊說明,索引出來的結(jié)果與原tensor共享內(nèi)存,也即修改一個(gè),另一個(gè)會(huì)跟著修改。
a = t.randn(3, 4)
a
tensor([[-0.2404960245, -0.1326600760, -0.0196023099, 1.7071028948],
[ 0.7344398499, 1.9282346964, 1.7709469795, 0.4925989807],
[-0.2727401257, -0.0743735656, -1.0019408464, -0.6791635156]])
a[0] # 第0行(下標(biāo)從0開始)
tensor([-0.2404960245, -0.1326600760, -0.0196023099, 1.7071028948])
a[:, 0] # 第0列
tensor([-0.2404960245, 0.7344398499, -0.2727401257])
a[0][2] # 第0行第2個(gè)元素,等價(jià)于a[0, 2]
tensor(-0.0196023099)
a[0, -1] # 第0行最后一個(gè)元素
tensor(1.7071028948)
a[:2] # 前兩行
tensor([[-0.2404960245, -0.1326600760, -0.0196023099, 1.7071028948],
[ 0.7344398499, 1.9282346964, 1.7709469795, 0.4925989807]])
a[:2, 0:2] # 前兩行,第0,1列
tensor([[-0.2404960245, -0.1326600760],
[ 0.7344398499, 1.9282346964]])
print(a[0:1, :2]) # 第0行,前兩列
print(a[0, :2]) # 注意兩者的區(qū)別:形狀不同
tensor([[-0.2404960245, -0.1326600760]])
tensor([-0.2404960245, -0.1326600760])
# None類似于np.newaxis, 為a新增了一個(gè)軸
# 等價(jià)于a.view(1, a.shape[0], a.shape[1])
a[None].shape
torch.Size([1, 3, 4])
a[None].shape # 等價(jià)于a[None,:,:]
torch.Size([1, 3, 4])
a[:,None,:].shape
torch.Size([3, 1, 4])
a[:,None,:,None,None].shape
torch.Size([3, 1, 4, 1, 1])
a > 1 # 返回一個(gè)ByteTensor
tensor([[False, False, False, True],
[False, True, True, False],
[False, False, False, False]])
a[a>1] # 等價(jià)于a.masked_select(a>1)
# 選擇結(jié)果與原tensor不共享內(nèi)存空間
tensor([1.7071028948, 1.9282346964, 1.7709469795])
a[t.LongTensor([0,1])] # 第0行和第1行
tensor([[-0.2404960245, -0.1326600760, -0.0196023099, 1.7071028948],
[ 0.7344398499, 1.9282346964, 1.7709469795, 0.4925989807]])
其它常用的選擇函數(shù)如表3-2所示。
表3-2常用的選擇函數(shù)
函數(shù) | 功能 |
---|---|
index_select(input, dim, index) | 在指定維度dim上選取,比如選取某些行、某些列 |
masked_select(input, mask) | 例子如上,a[a>0],使用ByteTensor進(jìn)行選取 |
non_zero(input) | 非0元素的下標(biāo) |
gather(input, dim, index) | 根據(jù)index,在dim維度上選取數(shù)據(jù),輸出的size與index一樣 |
gather
是一個(gè)比較復(fù)雜的操作,對(duì)一個(gè)2維tensor,輸出的每個(gè)元素如下:
out[i][j] = input[index[i][j]][j] # dim=0
out[i][j] = input[i][index[i][j]] # dim=1
三維tensor的gather
操作同理,下面舉幾個(gè)例子。
a = t.arange(0, 16).view(4, 4)
a
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
# 選取對(duì)角線的元素
index = t.LongTensor([[0,1,2,3]])
a.gather(0, index)
tensor([[ 0, 5, 10, 15]])
# 選取反對(duì)角線上的元素
index = t.LongTensor([[3,2,1,0]]).t()
a.gather(1, index)
tensor([[ 3],
[ 6],
[ 9],
[12]])
# 選取反對(duì)角線上的元素,注意與上面的不同
index = t.LongTensor([[3,2,1,0]])
a.gather(0, index)
tensor([[12, 9, 6, 3]])
# 選取兩個(gè)對(duì)角線上的元素
index = t.LongTensor([[0,1,2,3],[3,2,1,0]]).t()
b = a.gather(1, index)
b
tensor([[ 0, 3],
[ 5, 6],
[10, 9],
[15, 12]])
與gather
相對(duì)應(yīng)的逆操作是scatter_
,gather
把數(shù)據(jù)從input中按index取出,而scatter_
是把取出的數(shù)據(jù)再放回去。注意scatter_
函數(shù)是inplace操作。
out = input.gather(dim, index)
-->近似逆操作
out = Tensor()
out.scatter_(dim, index)
# 把兩個(gè)對(duì)角線元素放回去到指定位置
c = t.zeros(4,4)
c.scatter_(1, index, b.float())
tensor([[ 0., 0., 0., 3.],
[ 0., 5., 6., 0.],
[ 0., 9., 10., 0.],
[12., 0., 0., 15.]])
對(duì)tensor的任何索引操作仍是一個(gè)tensor,想要獲取標(biāo)準(zhǔn)的python對(duì)象數(shù)值,需要調(diào)用tensor.item()
, 這個(gè)方法只對(duì)包含一個(gè)元素的tensor適用
a[0,0] #依舊是tensor)
tensor(0)
a[0,0].item() # python float
0
d = a[0:1, 0:1, None]
print(d.shape)
d.item() # 只包含一個(gè)元素的tensor即可調(diào)用tensor.item,與形狀無關(guān)
torch.Size([1, 1, 1])
0
# a[0].item() ->
# raise ValueError: only one element tensors can be converted to Python scalars
1.4 高級(jí)索引
PyTorch在0.2版本中完善了索引操作,目前已經(jīng)支持絕大多數(shù)numpy的高級(jí)索引1。高級(jí)索引可以看成是普通索引操作的擴(kuò)展,但是高級(jí)索引操作的結(jié)果一般不和原始的Tensor共享內(nèi)存。
x = t.arange(0,27).view(3,3,3)
x
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],
[24, 25, 26]]])
x[[1, 2], [1, 2], [2, 0]] # x[1,1,2]和x[2,2,0]
tensor([14, 24])
x[[2, 1, 0], [0], [1]] # x[2,0,1],x[1,0,1],x[0,0,1]
tensor([19, 10, 1])
x[[0, 2], ...] # x[0] 和 x[2]
tensor([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[18, 19, 20],
[21, 22, 23],
[24, 25, 26]]])
1.5 Tensor類型
Tensor有不同的數(shù)據(jù)類型,如表1-3所示,每種類型分別對(duì)應(yīng)有CPU和GPU版本(HalfTensor除外)。默認(rèn)的tensor是FloatTensor,可通過t.set_default_tensor_type
來修改默認(rèn)tensor類型(如果默認(rèn)類型為GPU tensor,則所有操作都將在GPU上進(jìn)行)。Tensor的類型對(duì)分析內(nèi)存占用很有幫助。例如對(duì)于一個(gè)size為(1000, 1000, 1000)的FloatTensor,它有1000*1000*1000=10^9
個(gè)元素,每個(gè)元素占32bit/8 = 4Byte內(nèi)存,所以共占大約4GB內(nèi)存/顯存。HalfTensor是專門為GPU版本設(shè)計(jì)的,同樣的元素個(gè)數(shù),顯存占用只有FloatTensor的一半,所以可以極大緩解GPU顯存不足的問題,但由于HalfTensor所能表示的數(shù)值大小和精度有限2,所以可能出現(xiàn)溢出等問題。
表1-3: tensor數(shù)據(jù)類型
Data type | dtype | CPU tensor | GPU tensor |
---|---|---|---|
32-bit floating point |
torch.float32 or torch.float
|
torch.FloatTensor |
torch.cuda.FloatTensor |
64-bit floating point |
torch.float64 or torch.double
|
torch.DoubleTensor |
torch.cuda.DoubleTensor |
16-bit floating point |
torch.float16 or torch.half
|
torch.HalfTensor |
torch.cuda.HalfTensor |
8-bit integer (unsigned) | torch.uint8 |
torch.ByteTensor |
torch.cuda.ByteTensor |
8-bit integer (signed) | torch.int8 |
torch.CharTensor |
torch.cuda.CharTensor |
16-bit integer (signed) |
torch.int16 or torch.short
|
torch.ShortTensor |
torch.cuda.ShortTensor |
32-bit integer (signed) |
torch.int32 or torch.int
|
torch.IntTensor |
torch.cuda.IntTensor |
64-bit integer (signed) |
torch.int64 or torch.long
|
torch.LongTensor |
torch.cuda.LongTensor |
各數(shù)據(jù)類型之間可以互相轉(zhuǎn)換,type(new_type)
是通用的做法,同時(shí)還有float
、long
、half
等快捷方法。CPU tensor與GPU tensor之間的互相轉(zhuǎn)換通過tensor.cuda
和tensor.cpu
方法實(shí)現(xiàn),此外還可以使用tensor.to(device)
。Tensor還有一個(gè)new
方法,用法與t.Tensor
一樣,會(huì)調(diào)用該tensor對(duì)應(yīng)類型的構(gòu)造函數(shù),生成與當(dāng)前tensor類型一致的tensor。torch.*_like(tensora)
可以生成和tensora
擁有同樣屬性(類型,形狀,cpu/gpu)的新tensor。 tensor.new_*(new_shape)
新建一個(gè)不同形狀的tensor。
# 設(shè)置默認(rèn)tensor,注意參數(shù)是字符串
t.set_default_tensor_type('torch.DoubleTensor')
a = t.Tensor(2,3)
a.dtype # 現(xiàn)在a是DoubleTensor,dtype是float64
torch.float64
# 恢復(fù)之前的默認(rèn)設(shè)置
t.set_default_tensor_type('torch.FloatTensor')
# 把a(bǔ)轉(zhuǎn)成FloatTensor,等價(jià)于b=a.type(t.FloatTensor)
b = a.float()
b.dtype
torch.float32
c = a.type_as(b)
c
tensor([[0.0000000000e+00, 8.8863861561e-01, 4.0106318193e-04],
[1.0096810608e-14, 3.7590373540e-04, 2.0494908676e-04]])
a.new(2,3) # 等價(jià)于torch.DoubleTensor(2,3),建議使用a.new_tensor
tensor([[0.1000000015, 1.2000000477, 2.2000000477],
[3.0999999046, 4.9000000954, 5.1999998093]], dtype=torch.float64)
t.zeros_like(a) #等價(jià)于t.zeros(a.shape,dtype=a.dtype,device=a.device)
tensor([[0., 0., 0.],
[0., 0., 0.]], dtype=torch.float64)
t.zeros_like(a, dtype=t.int16) #可以修改某些屬性
tensor([[0, 0, 0],
[0, 0, 0]], dtype=torch.int16)
t.rand_like(a)
tensor([[0.4587583271, 0.0597746880, 0.3043038499],
[0.8112906815, 0.1569333205, 0.7714216456]], dtype=torch.float64)
a.new_ones(4,5, dtype=t.int)
tensor([[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]], dtype=torch.int32)
a.new_tensor([3,4]) #
tensor([3., 4.], dtype=torch.float64)
1.6 逐元素操作
這部分操作會(huì)對(duì)tensor的每一個(gè)元素(point-wise,又名element-wise)進(jìn)行操作,此類操作的輸入與輸出形狀一致。常用的操作如表1-4所示。
表1-4: 常見的逐元素操作
函數(shù) | 功能 |
---|---|
abs/sqrt/div/exp/fmod/log/pow… | 絕對(duì)值/平方根/除法/指數(shù)/求余/求冪… |
cos/sin/asin/atan2/cosh… | 相關(guān)三角函數(shù) |
ceil/round/floor/trunc | 上取整/四舍五入/下取整/只保留整數(shù)部分 |
clamp(input, min, max) | 超過min和max部分截?cái)?/td> |
sigmod/tanh… | 激活函數(shù) |
對(duì)于很多操作,例如div、mul、pow、fmod等,PyTorch都實(shí)現(xiàn)了運(yùn)算符重載,所以可以直接使用運(yùn)算符。如a ** 2
等價(jià)于torch.pow(a,2)
, a * 2
等價(jià)于torch.mul(a,2)
。
其中clamp(x, min, max)
的輸出滿足以下公式:
y
i
=
{
m
i
n
,
if?
x
i
<
m
i
n
x
i
,
if?
m
i
n
≤
x
i
≤
m
a
x
m
a
x
,
if?
x
i
>
m
a
x
y_i = \begin{cases} min, & \text{if } x_i \lt min \\ x_i, & \text{if } min \le x_i \le max \\ max, & \text{if } x_i \gt max\\ \end{cases}
yi?=?
?
??min,xi?,max,?if?xi?<minif?min≤xi?≤maxif?xi?>max?clamp
常用在某些需要比較大小的地方,如取一個(gè)tensor的每個(gè)元素與另一個(gè)數(shù)的較大值。
a = t.arange(0, 6).view(2, 3).float()
t.cos(a)
tensor([[ 1.0000000000, 0.5403023362, -0.4161468446],
[-0.9899924994, -0.6536436081, 0.2836622000]])
a % 3 # 等價(jià)于t.fmod(a, 3)
tensor([[0., 1., 2.],
[0., 1., 2.]])
a ** 2 # 等價(jià)于t.pow(a, 2)
tensor([[ 0., 1., 4.],
[ 9., 16., 25.]])
# 取a中的每一個(gè)元素與3相比較大的一個(gè) (小于3的截?cái)喑?)
print(a)
t.clamp(a, min=3)
tensor([[0., 1., 2.],
[3., 4., 5.]])
tensor([[3., 3., 3.],
[3., 4., 5.]])
b = a.sin_() # 效果同 a = a.sin();b=a ,但是更高效節(jié)省顯存
a
tensor([[ 0.0000000000, 0.8414709568, 0.9092974067],
[ 0.1411200017, -0.7568024993, -0.9589242935]])
1.7 歸并操作
此類操作會(huì)使輸出形狀小于輸入形狀,并可以沿著某一維度進(jìn)行指定操作。如加法sum
,既可以計(jì)算整個(gè)tensor的和,也可以計(jì)算tensor中每一行或每一列的和。常用的歸并操作如表1-5所示。
表1-5: 常用歸并操作
函數(shù) | 功能 |
---|---|
mean/sum/median/mode | 均值/和/中位數(shù)/眾數(shù) |
norm/dist | 范數(shù)/距離 |
std/var | 標(biāo)準(zhǔn)差/方差 |
cumsum/cumprod | 累加/累乘 |
以上大多數(shù)函數(shù)都有一個(gè)參數(shù)**dim
**,用來指定這些操作是在哪個(gè)維度上執(zhí)行的。關(guān)于dim(對(duì)應(yīng)于Numpy中的axis)的解釋眾說紛紜,這里提供一個(gè)簡單的記憶方式:
假設(shè)輸入的形狀是(m, n, k)
- 如果指定dim=0,輸出的形狀就是(1, n, k)或者(n, k)
- 如果指定dim=1,輸出的形狀就是(m, 1, k)或者(m, k)
- 如果指定dim=2,輸出的形狀就是(m, n, 1)或者(m, n)
size中是否有"1",取決于參數(shù)keepdim
,keepdim=True
會(huì)保留維度1
。注意,以上只是經(jīng)驗(yàn)總結(jié),并非所有函數(shù)都符合這種形狀變化方式,如cumsum
。
b = t.ones(2, 3)
b.sum(dim = 0, keepdim=True)
tensor([[2., 2., 2.]])
# keepdim=False,不保留維度"1",注意形狀
b.sum(dim=0, keepdim=False)
tensor([2., 2., 2.])
b.sum(dim=1)
tensor([3., 3.])
a = t.arange(0, 6).view(2, 3)
print(a)
a.cumsum(dim=1) # 沿著行累加
tensor([[0, 1, 2],
[3, 4, 5]])
tensor([[ 0, 1, 3],
[ 3, 7, 12]])
1.8 比較
比較函數(shù)中有一些是逐元素比較,操作類似于逐元素操作,還有一些則類似于歸并操作。常用比較函數(shù)如表1-6所示。
表1-6: 常用比較函數(shù)
函數(shù) | 功能 |
---|---|
gt/lt/ge/le/eq/ne | 大于/小于/大于等于/小于等于/等于/不等 |
topk | 最大的k個(gè)數(shù) |
sort | 排序 |
max/min | 比較兩個(gè)tensor最大最小值 |
表中第一行的比較操作已經(jīng)實(shí)現(xiàn)了運(yùn)算符重載,因此可以使用a>=b
、a>b
、a!=b
、a==b
,其返回結(jié)果是一個(gè)ByteTensor
,可用來選取元素。max/min這兩個(gè)操作比較特殊,以max來說,它有以下三種使用情況:
- t.max(tensor):返回tensor中最大的一個(gè)數(shù)
- t.max(tensor,dim):指定維上最大的數(shù),返回tensor和下標(biāo)
- t.max(tensor1, tensor2): 比較兩個(gè)tensor相比較大的元素
至于比較一個(gè)tensor和一個(gè)數(shù),可以使用clamp函數(shù)。下面舉例說明。
a = t.linspace(0, 15, 6).view(2, 3)
a
tensor([[ 0., 3., 6.],
[ 9., 12., 15.]])
b = t.linspace(15, 0, 6).view(2, 3)
b
tensor([[15., 12., 9.],
[ 6., 3., 0.]])
a>b
tensor([[False, False, False],
[ True, True, True]])
a[a>b] # a中大于b的元素
tensor([ 9., 12., 15.])
t.max(a)
tensor(15.)
t.max(b, dim=1)
# 第一個(gè)返回值的15和6分別表示第0行和第1行最大的元素
# 第二個(gè)返回值的0和0表示上述最大的數(shù)是該行第0個(gè)元素
torch.return_types.max(
values=tensor([15., 6.]),
indices=tensor([0, 0]))
t.max(a,b)
tensor([[15., 12., 9.],
[ 9., 12., 15.]])
# 比較a和10較大的元素
t.clamp(a, min=10)
tensor([[10., 10., 10.],
[10., 12., 15.]])
1.9 線性代數(shù)
PyTorch的線性函數(shù)主要封裝了Blas和Lapack,其用法和接口都與之類似。常用的線性代數(shù)函數(shù)如表1-7所示。
表1-7: 常用的線性代數(shù)函數(shù)
函數(shù) | 功能 |
---|---|
trace | 對(duì)角線元素之和(矩陣的跡) |
diag | 對(duì)角線元素 |
triu/tril | 矩陣的上三角/下三角,可指定偏移量 |
mm/bmm | 矩陣乘法,batch的矩陣乘法 |
addmm/addbmm/addmv/addr/badbmm… | 矩陣運(yùn)算 |
t | 轉(zhuǎn)置 |
dot/cross | 內(nèi)積/外積 |
inverse | 求逆矩陣 |
svd | 奇異值分解 |
具體使用說明請(qǐng)參見官方文檔3,需要注意的是,矩陣的轉(zhuǎn)置會(huì)導(dǎo)致存儲(chǔ)空間不連續(xù),需調(diào)用它的.contiguous
方法將其轉(zhuǎn)為連續(xù)。
b = a.t()
b.is_contiguous()
False
b.contiguous()
tensor([[ 0., 9.],
[ 3., 12.],
[ 6., 15.]])
-
https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#advanced-indexing ??
-
https://stackoverflow.com/questions/872544/what-range-of-numbers-can-be-represented-in-a-16-32-and-64-bit-ieee-754-syste ??文章來源:http://www.zghlxwxcb.cn/news/detail-759930.html
-
http://pytorch.org/docs/torch.html#blas-and-lapack-operations ??文章來源地址http://www.zghlxwxcb.cn/news/detail-759930.html
到了這里,關(guān)于1.PyTorch數(shù)據(jù)結(jié)構(gòu)Tensor常用操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!