使用張量處理數(shù)據(jù)
張量(Tensors)類似于numpy中的ndarrays炭序,Tensors可以在GPU中加速運(yùn)算跺株。
我們首先導(dǎo)入torch
from __future__ import print_function # python2中使用print()的輸出函數(shù)
import torch
然后我們創(chuàng)建一個(gè)3行和4列的2D數(shù)組(通常也叫矩陣),并且把每個(gè)元素初始化成0
x = torch.zeros(3, 4)
print(x)
0 0 0 0
0 0 0 0
0 0 0 0
[torch.FloatTensor of size 3x4]
類似的府喳,我們可以創(chuàng)建數(shù)組每個(gè)元素被初始化成1蒲肋。
x = torch.ones(3, 4)
print(x)
1 1 1 1
1 1 1 1
1 1 1 1
[torch.FloatTensor of size 3x4]
或者從數(shù)組直接構(gòu)造
x = torch.FloatTensor([[1,2],[3,4]])
print(x)
1 2
3 4
[torch.FloatTensor of size 2x2]
我們經(jīng)常需要?jiǎng)?chuàng)建隨機(jī)數(shù)組,就是說每個(gè)元素的值都是隨機(jī)采樣而來,這個(gè)經(jīng)常被用來初始化模型參數(shù)兜粘。下面創(chuàng)建數(shù)組申窘,它的元素服從均值0方差1的正態(tài)分布。
y = torch.randn(3, 4)
print(y)
1.8000 -1.2639 -0.5560 0.4861
-0.7101 -0.1594 -0.8752 -0.1776
-0.5662 -0.1355 -1.0900 -0.1244
[torch.FloatTensor of size 3x4]
每個(gè)數(shù)組的形狀可以通過.shape來獲取
print(x.size())
(3L, 4L)
它的總元素個(gè)數(shù)孔轴,是形狀的累乘剃法。
x_num = x.size(0) * x.size(1)
print(x_num)
12
操作符
PyTorch支持大量的數(shù)學(xué)操作符,例如按元素加法:
x = torch.FloatTensor([[1,2],[3,4]])
y = torch.FloatTensor([[5,6],[7,8]])
print(x + y) # 或者print(torch.add(x, y))
6 8
10 12
[torch.FloatTensor of size 2x2]
乘法:
print(x * y)
5 12
21 32
[torch.FloatTensor of size 2x2]
指數(shù)運(yùn)算:
print(torch.exp(x))
2.7183 7.3891
20.0855 54.5981
[torch.FloatTensor of size 2x2]
也可以轉(zhuǎn)置一個(gè)矩陣然后計(jì)算矩陣乘法:
x = torch.FloatTensor([[1,2,3],[4,5,6]])
y = torch.FloatTensor([[7,8,9],[10,11,12]])
print(torch.matmul(x, torch.t(y)))
50 68
122 167
[torch.FloatTensor of size 2x2]
可以索引數(shù)組:
x = torch.FloatTensor([[1,2],[3,4]])
print(x[:,1]) #提取第2列
2
4
[torch.FloatTensor of size 2]
形狀轉(zhuǎn)換(Broadcasting)
當(dāng)二元操作符左右兩邊Tensor形狀不一樣時(shí)距糖,系統(tǒng)會嘗試將其復(fù)制到一個(gè)共同的形狀玄窝。例如a的第0維是3, b的第0維是1,那么a+b時(shí)會將b沿著第0維復(fù)制3遍:
a = torch.arange(0, 3).resize_(3, 1)
b = torch.arange(0, 2).resize_(1, 2)
print(a)
print(b)
print(a + b)
0
1
2
[torch.FloatTensor of size 3x1]
0 1
[torch.FloatTensor of size 1x2]
0 1
1 2
2 3
[torch.FloatTensor of size 3x2]
跟NumPy的轉(zhuǎn)換
Tensor可以很方便同numpy進(jìn)行轉(zhuǎn)換
x = np.ones((2, 3)).astype(np.float32)
y = torch.from_numpy(x) # numpy -> tensor
z = y.numpy() # tensor -> numpy
print(x)
print(y)
print(z)
[[ 1. 1. 1.]
[ 1. 1. 1.]]
1 1 1
1 1 1
[torch.FloatTensor of size 2x3]
[[ 1. 1. 1.]
[ 1. 1. 1.]]
替換操作(In-place)
在前面的樣例中悍引,我們?yōu)槊總€(gè)操作新開內(nèi)存來存儲它的結(jié)果。例如帽氓,如果我們寫y = x + y, 我們會把y從現(xiàn)在指向的實(shí)例轉(zhuǎn)到新建的實(shí)例上去趣斤。我們可以用Python的id()函數(shù)來看這個(gè)是怎么執(zhí)行的:
x = torch.ones(3,4)
y = torch.ones(3,4)
before = id(y)
y = y + x
print(id(y) == before)
False
我們可以把結(jié)果通過[:]寫到一個(gè)之前開好的數(shù)組里:
x = torch.ones(3,4)
y = torch.ones(3,4)
z = torch.zeros(x.size())
before = id(z)
z[:] = x + y
print(id(z) == before)
True
但是這里我們還是為x+y創(chuàng)建了臨時(shí)空間,然后再復(fù)制到z黎休。需要避免這個(gè)開銷浓领,我們可以使用操作符的全名版本中的out參數(shù):
torch.add(x, y, out=z)
如果現(xiàn)有的數(shù)組不會復(fù)用,我們也可以用y.add_(x)
達(dá)到這個(gè)目的势腮,類似的操作還有x.copy_(y)
联贩,x.t_()
:
x = torch.ones(3,4)
y = torch.ones(3,4)
before = id(y)
y.add_(x)
print(id(y) == before)
True
截取(Slicing)
截取x的第2、3行:
x = torch.arange(0,9).resize_(3,3)
print(x)
print(x[1:3])
0 1 2
3 4 5
6 7 8
[torch.FloatTensor of size 3x3]
3 4 5
6 7 8
[torch.FloatTensor of size 2x3]
截取x的第2捎拯、3列:
x = torch.arange(0,9).resize_(3,3)
print(x)
print(x[:,1:3])
0 1 2
3 4 5
6 7 8
[torch.FloatTensor of size 3x3]
1 2
4 5
7 8
[torch.FloatTensor of size 3x2]
以及直接寫入指定位置:
x[1,2] = 9.0
print(x)
0 1 2
3 4 9
6 7 8
[torch.FloatTensor of size 3x3]
多維截壤峄稀:
print(x[1:2,1:3])
4 9
[torch.FloatTensor of size 1x2]
多維寫入:
x[1:2,1:3] = 9.0
print(x)
0 1 2
3 9 9
6 7 8
[torch.FloatTensor of size 3x3]
GPU計(jì)算
通過在張量后加上.cuda()
可以把Tensors移動(dòng)到GPU上
x = torch.arange(0,9).resize_(3,3)
y = torch.arange(1,10).resize_(3,3)
print(x)
print(y)
if torch.cuda.is_available():
x = x.cuda()
y = y.cuda()
print(x)
print(y)
print(x+y)
0 1 2
3 4 5
6 7 8
[torch.cuda.FloatTensor of size 3x3 (GPU 0)]
1 2 3
4 5 6
7 8 9
[torch.cuda.FloatTensor of size 3x3 (GPU 0)]
1 3 5
7 9 11
13 15 17
[torch.cuda.FloatTensor of size 3x3 (GPU 0)]