1. 程式人生 > >pytorch系列------2 tensor基礎

pytorch系列------2 tensor基礎

pytorch Tensor的基本用法

  • Tensor的建立
  • 索引,合併,切片
  • 初始化
  • 數學操作

1. Tensor的建立

1) 隨機數字

torch.rand(*sizes, out=None) → Tensor
返回一個張量,包含了從區間[0, 1)的均勻分佈中抽取的一組隨機數。張量的形狀由引數sizes定義

# torch.rand(sizes) -> [0,1)之間的均勻分佈
x = torch.rand(2,3)
x

out:

0.9161 0.7135 0.8969
0.7552 0.8760 0.2236
[torch.FloatTensor of size 2x3]

torch.randn(*sizes, out=None) → Tensor
返回一個張量,包含了從標準正態分佈(均值為0,方差為1,即高斯白噪聲)中抽取的一組隨機數。張量的形狀由引數sizes定義

# torch.randn(sizes) -> Z(0,1)
x = torch.randn(2,3)
x

out:

-1.9352 0.9779 1.7401
2.0432 -0.1962 -0.1177
[torch.FloatTensor of size 2x3]

torch.randperm(n)
返回張量, 0~n之間的一個全排列


# torch.randperm(n) -> permutation of 0~n
x = torch.randperm(5) x

out:

3
1
4
0
2
[torch.LongTensor of size 5]

2) zeros, ones, eye, arrange

torch.zeros(*sizes, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor

返回張量,用0填充,size有引數sizes確定

# torch.zeros(2,3) -> [[0,0,0],[0,0,0]]
x = torch.zeros(2,3)
x

out:

0 0 0
0 0 0
[torch.FloatTensor of size 2x3]

torch.ones(*sizes, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor

返回張量,用1填充,size有引數sizes確定

# torch.ones(2,3) -> [[0,0,0],[0,0,0]]
x = torch.ones(2,3)
x

out:

1 1 1
1 1 1
[torch.FloatTensor of size 2x3]

torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor
返回一維張量,在[start, end)區間內,按step為間隔返回一個等差數列,
o u t i + 1 = o u t i + s t e p out_{i+1} = out_i + step

# torch.arange(start,end,step=1) -> [start,end) with step

y = torch.arange(1, 4)
x = torch.arange(0,3,step=0.5)
y
x

out:

tensor([ 1, 2, 3])
0.0000
0.5000
1.0000
1.5000
2.0000
2.5000
[torch.FloatTensor of size 6]

torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor
返回二維對角矩陣張量,對角線上為1,其餘為0

 torch.eye(3)

out:

tensor([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])

3) Tensor 資料型別

所有的資料型別都在這裡
https://pytorch.org/docs/stable/tensors.html#torch-tensor
建立size為[2,3]的浮點數張量

# torch.FloatTensor(size or list)
x = torch.FloatTensor(2,3)
x

out:

-7.4341e-17 4.5629e-41 -7.4341e-17
4.5629e-41 -7.4342e-17 2.9427e-44
[torch.FloatTensor of size 2x3]

建立資料為2,3的浮點數張量

# torch.FloatTensor(size or list)
x = torch.FloatTensor([2,3])
x

out:

2
3
[torch.FloatTensor of size 2]

轉換為整型張量


# tensor.type_as(tensor_type)
x = x.type_as(torch.IntTensor())
x

out:

2
3
[torch.IntTensor of size 2]

4) Tensor 和 numpy的相互轉換

從numpy轉換為Tensor

import numpy as np

# torch.from_numpy(ndarray) -> tensor

x1 = np.ndarray(shape=(2,3), dtype=int,buffer=np.array([1,2,3,4,5,6]))
x2 = torch.from_numpy(x1)

x2

out:

1 2 3
4 5 6
[torch.LongTensor of size 2x3]

從張量轉換為numpy陣列

# tensor.numpy() -> ndarray
x3 = x2.numpy()
x3

out:>
array([[1, 2, 3],
[4, 5, 6]])

5) GPU和CPU上的Tensor

建立Tensor

x = torch.FloatTensor([[1,2,3],[4,5,6]])
x

out:

1 2 3
4 5 6
[torch.FloatTensor of size 2x3]

轉換為GPU上:

x_gpu = x.cuda()
x_gpu

out:

1 2 3
4 5 6
[torch.cuda.FloatTensor of size 2x3 (GPU 0)]

從GPU格式轉換為CPU

x_cpu = x_gpu.cpu()
x_cpu

out:

1 2 3
4 5 6
[torch.FloatTensor of size 2x3]

6) tensor的size

也就是tensor的形狀
建立維度為[10, 12, 3,3]的浮點數張量

# tensor.size() -> indexing also possible

x = torch.FloatTensor(10,12,3,3)

x.size()[:]

out:

torch.Size([10, 12, 3, 3])

2. 索引(indexing),切片(slicing), 合併(joining), 更改形狀(reshaping)

1) indexing

torch.index_select(input, dim, index)
在dim的維度上,按index索引

比如下列就是在行上,索引第0和3行

# torch.index_select(input, dim, index)

x = torch.rand(4,3)
out = torch.index_select(x,0,torch.LongTensor([0,3]))

x,out

out:

(
0.9495 0.8593 0.2616
0.2279 0.0857 0.7603
0.4439 0.2024 0.8021
0.3477 0.6363 0.5002
[torch.FloatTensor of size 4x3],
0.9495 0.8593 0.2616
0.3477 0.6363 0.5002
[torch.FloatTensor of size 2x3])

也支援python和numpy的索引方式

x[:,0],x[0,:],x[0:2,0:2]

out:

(
0.9495
0.2279
0.4439
0.3477
[torch.FloatTensor of size 4],
0.9495
0.8593
0.2616
[torch.FloatTensor of size 3],
0.9495 0.8593
0.2279 0.0857
[torch.FloatTensor of size 2x2])

torch.masked_select(input, mask, out=None) → Tensor
返回一維張量,mask為一個ByteTensor,返回mask值為1的位置對應input的值,

mask和input的size不一定相同,但要滿足廣播機制

# torch.masked_select(input, mask)

x = torch.randn(2,3)
mask = torch.ByteTensor([[0,0,1],[0,1,0]])
out = torch.masked_select(x,mask)

x, mask, out

out:

(
-2.0702 -0.3064 -0.8124
0.2870 0.2648 0.4418
[torch.FloatTensor of size 2x3],
0 0 1
0 1 0
[torch.ByteTensor of size 2x3],
-0.8124
0.2648
[torch.FloatTensor of size 2])

來看一個更有意義的場景,
返回x中大於0.5的值:

x = torch.randn(3, 4)
x
'''
tensor([[ 0.3552, -2.3825, -0.8297,  0.3477],
        [-1.2035,  1.2252,  0.5002,  0.6248],
        [ 0.1307, -2.0608,  0.1244,  2.0139]])
 '''
 # 值大於0.5為1,否則為0
mask = x.ge(0.5)
mask
'''
tensor([[ 0,  0,  0,  0],
        [ 0,  1,  1,  1],
        [ 0,  0,  0,  1]], dtype=torch.uint8)
 '''
 torch.masked_select(x, mask)

'''
tensor([ 1.2252,  0.5002,  0.6248,  2.0139])
'''

2) joining

torch.cat(seq, dim=0) -> concatenate tensor along dim
最常見的是二維資料, dim為0是按行排列,dim為1是按列排列。
而對於二維陣列而言dim=-1和dim=1完全等價,因為dim=-1表示size的最後一個維度。

# torch.cat(seq, dim=0) -> concatenate tensor along dim

x = torch.FloatTensor([[1,2,3],[4,5,6]])
y = torch.FloatTensor([[-1,-2,-3],[-4,-5,-6]])
z1 = torch.cat([x,y],dim=0)
z2 = torch.cat([x,y],dim=1)

x,y,z1,z2

out:

(
1 2 3
4 5 6
[torch.FloatTensor of size 2x3],
-1 -2 -3
-4 -5 -6
[torch.FloatTensor of size 2x3],
1 2 3
4 5 6
-1 -2 -3
-4 -5 -6
[torch.FloatTensor of size 4x3],
1 2 3 -1 -2 -3
4 5 6 -4 -5 -6
[torch.FloatTensor of size 2x6])

3) slicing 切片

torch.chunk(tensor, chunks, dim=0) → List of Tensors
將tensor在維度dim上分割為特定數量的塊(chunks)

例如下列程式碼第一行將z1在行上分割為兩部分,第二行將z1在列上分為3部分

# torch.chunk(tensor, chunks, dim=0) -> tensor into num chunks

x_1, x_2 = torch.chunk(z1,2,dim=0)
y_1, y_2, y_3 = torch.chunk(z1,3,dim=1)

z1,x_1,x_2,z1,y_1,y_2,y_3

out:

(
1 2 3
4 5 6
-1 -2 -3
-4 -5 -6
[torch.FloatTensor of size 4x3],
1 2 3
4 5 6
[torch.FloatTensor of size 2x3],
-1 -2 -3
-4 -5 -6
[torch.FloatTensor of size 2x3],
1 2 3
4 5 6
-1 -2 -3
-4 -5 -6
[torch.FloatTensor of size 4x3],
1
4
-1
-4
[torch.FloatTensor of size 4x1],
2
5
-2
-5
[torch.FloatTensor of size 4x1],
3
6
-3
-6
[torch.FloatTensor of size 4x1])

和chunk的作用一樣

# torch.split(tensor,split_size,dim=0) -> split into specific size

x1,x2 = torch.split(z1,2,dim=0)
y1 = torch.split(z1,2,dim=1) 

z1,x1,x2,y1

out:

(
1 2 3
4 5 6
-1 -2 -3
-4 -5 -6
[torch.FloatTensor of size 4x3],
1 2 3
4 5 6
[torch.FloatTensor of size 2x3],
-1 -2 -3
-4 -5 -6
[torch.FloatTensor of size 2x3], (
1 2
4 5
-1 -2
-4 -5
[torch.FloatTensor of size 4x2],
3
6
-3
-6
[torch.FloatTensor of size 4x1]))

4) squeezing

torch.squeeze(input,dim=None) -> reduce dim by 1
去掉張量中維度大小為1的dim
建立size為[10, 1,3,1,4]的張量,通過squeeze函式,去掉1的dim,變為[10,3,4]

# torch.squeeze(input,dim=None) -> reduce dim by 1

x1 = torch.FloatTensor(10,1,3,1,4)
x2 = torch.squeeze(x1)

x1.size(),x2.size()

out:

(torch.Size([10, 1, 3, 1, 4]), torch.Size([10, 3, 4]))

torch.unsqueeze(input,dim=None) -> add dim by 1
在指定的dim上新增大小為1維度
比如下列程式碼,在dim=0的維度上增加緯度值為1 的維度,所以張量size變為[1, 10, 3, 4]

# torch.unsqueeze(input,dim=None) -> add dim by 1

x1 = torch.FloatTensor(10,3,4)
x2 = torch.unsqueeze(x1,dim=0)

x1.size(),x2.size()

out:

(torch.Size([10, 3, 4]), torch.Size([1, 10, 3, 4]))

5) reshaping

tensor.view(size):改變張量的形狀size
經常在最後一層卷積層,第一層全連線層之前使用,展開為[batch, -1]的形狀

# tensor.view(size)

x1 = torch.FloatTensor(10,3,4)
# 展開為1維
x2 = x1.view(-1)
x3 = x1.view(5,-1)
x4 = x1.view(3,10,-1)

x1.size(), x2.size(), x3.size(), x4.size()

out:>
(torch.Size([10, 3, 4]),
torch.Size([120]),
torch.Size([5, 24]),
torch.Size([3, 10, 4]))

3. 初始化

import torch.nn.init as init
# 均勻分佈
x1 = init.uniform(torch.FloatTensor(3,4),a=0,b=9) 
# 正太分佈
x2 = init.normal(torch.FloatTensor(3,4),std=0.2)
# 初始化為常數
x3 = init.constant(torch.FloatTensor(3,4),3.1415)

x1,x2,x3

out:

(
7.8079 3.7811 4.0829 8.0698
8.4885 5.2119 2.5769 1.4455
3.0500 3.9946 5.6066 4.9679
[torch.FloatTensor of size 3x4],
-0.4025 -0.2582 -0.0780 -0.2003
0.1577 -0.0933 -0.2640 -0.3402
0.1431 -0.1946 -0.1485 0.0026
[torch.FloatTensor of size 3x4],
3.1415 3.1415 3.1415 3.1415
3.1415 3.1415 3.1415 3.1415
3.1415 3.1415 3.1415 3.1415
[torch.FloatTensor of size 3x4])

4. 數學操作

1) 算數操作 Arithmetic operations
# torch.add()

x1 = torch.FloatTensor([[1,2,3],[4,5,6]])
x2 = torch.FloatTensor([[1,2,3],[4,5,6]])
add = torch.add(x1,x2)

x1,x2,add,x1+x2,x1-x2

out:

(
1 2 3
4 5 6
[torch.FloatTensor of size 2x3],
1 2 3
4 5 6
[torch.FloatTensor of size 2x3],
2 4 6
8 10 12
[torch.FloatTensor of size 2x3],
2 4 6
8 10 12
[torch.FloatTensor of size 2x3],
0 0 0
0 0 0
[torch.FloatTensor of size 2x3])

支援廣播機制

# torch.add() broadcasting

x1 = torch.FloatTensor([[1,2,3],[4,5,6]])
x2 = torch.add(x1,10)

x1,x2,x1+10,x2-10

(
1 2 3
4 5 6
[torch.FloatTensor of size 2x3],
11 12 13
14 15 16
[torch.FloatTensor of size 2x3],
11 12 13
14 15 16
[torch.FloatTensor of size 2x3],
1 2 3
4 5 6
[torch.FloatTensor of size 2x3])

元素級乘法:

# torch.mul() -> size better match

x1 = torch.FloatTensor([[1,2,3],[4,5,6]])
x2 = torch.FloatTensor([[1,2,3],[4,5,6]])
x3 = torch.mul(x1,x2)

x3

out:

1 4 9
16 25 36
[torch.FloatTensor of size 2x3]

也支援廣播:

# torch.mul() -> broadcasting

x1 = torch.FloatTensor([[1,2,3],[4,5,6]])
x2 = x1*10

x2

out:

10 20 30
40 50 60
[torch.FloatTensor of size 2x3]

元素級除法

# torch.div() -> size better match

x1 = torch.FloatTensor([[1,2,3],[4,5,6]])
x2 = torch.FloatTensor([[1,2,3],[4,5,6]])
x3 = torch.div(x1,x2)

x3

out:

1 1 1
1 1 1
[torch.FloatTensor of size 2x3]

# torch.div() -> broadcasting

x1 = torch.FloatTensor([[1,2,3],[4,5,6]])

x1/5

out:

0.2000 0.4000 0.6000
0.8000 1.0000 1.2000
[torch.FloatTensor of size 2x3]

2)其他的數學操作

pow 冪操作
求每一個元素的平方

# torch.pow(input,exponent)

x1 = torch.FloatTensor(3,4)
torch.pow(x1,2),x1**2

out:

(
1.00000e-33 *
5.5267 0.0000 5.5267 0.0000
0.0000 0.0000 5.5267 0.0000
0.0000 0.0000 0.0000 0.0000
[torch.FloatTensor of size 3x4],
1.00000e-33 *
5.5267 0.0000 5.5267 0.0000
0.0000 0.0000 5.5267 0.0000
0.0000 0.0000 0.0000 0.0000
[torch.FloatTensor of size 3x4])

指數操作

# torch.exp(tensor,out=None) 

x1 = torch.FloatTensor(3,4)
torch.exp(x1)

out:

1 1 1 1
inf 1 inf 1
1 1 1 1
[torch.FloatTensor of size 3x4]

對數操作

# torch.log(input, out=None) -> natural logarithm

x1 = torch.FloatTensor(3,4)
torch.log(x1)

out:

nan -92.8880 -86.5151 -inf
-inf -inf -inf -inf
-inf -inf -inf -inf
[torch.FloatTensor of size 3x4]

3) 矩陣操作

矩陣乘法

# torch.mm(mat1, mat2) -> matrix multiplication

x1 = torch.FloatTensor(3,4)
x2 = torch.FloatTensor(4,5)

torch.mm(x1,x2)

out:

-9.6088e-12 5.8988e-36 5.5267e-33 0.0000e+00 -9.6628e-12
2.4562e-18 6.9592e+27 2.4562e-18 -2.4818e+01 8.6738e-02
1.2129e-32 5.8988e-36 5.5267e-33 0.0000e+00 -9.6628e-12
[torch.FloatTensor of size 3x5]

批矩陣乘法

# torch.bmm(batch1, batch2) -> batch matrix multiplication

x1 = torch.FloatTensor(10,3,4)
x2 = torch.FloatTensor(10,4,5)

torch.bmm(x1,x2).size()

out:

torch.Size([10, 3, 5])

點乘:

# torch.dot(tensor1,tensor2) -> dot product of two tensor

x1 = torch.FloatTensor(3,4)
x2 = torch.FloatTensor(3,4)

torch.dot(x1,x2)

out:

5.5267435454184226e-33

轉置

# torch.t(matrix) -> transposed matrix

x1 = torch.FloatTensor(3,4)

x1,x1.t()

out:

(
1.00000e-17 *
-7.4341 0.0000 -7.4341 0.0000
0.0000 0.0000 0.0000 0.0000
-7.4342 0.0000 -7.4342 0.0000
[torch.FloatTensor of size 3x4],
1.00000e-17 *
-7.4341 0.0000 -7.4342
0.0000 0.0000 0.0000
-7.4341 0.0000 -7.4342
0.0000 0.0000 0.0000
[torch.FloatTensor of size 4x3])

按兩個指定的維度調換位置

# torch.transpose(input,dim0,dim1) -> transposed matrix

x1 = torch.FloatTensor(10,3,4)

x1.size(), torch.transpose(x1,1,2).size(), x1.transpose(1,2).size()

out:

(torch.Size([10, 3, 4]), torch.Size([10, 4, 3]), torch.Size([10, 4, 3]))