深度學習之PyTorch學習_2.2 數據結構

2.2 數據結構

  • torch.Tensor 是存儲和變換數據的主要工具

2.2.1 創建TENSOR

首先導入PyTorch

import torch

創建一個5x3的未初始化的Tensor

x = torch.empty(5,3)
print(x)
tensor([[9.2755e-39, 1.0561e-38, 1.0929e-38],
        [1.0102e-38, 9.7347e-39, 4.2246e-39],
        [1.0286e-38, 1.0653e-38, 1.0194e-38],
        [8.4490e-39, 1.0469e-38, 9.3674e-39],
        [9.9184e-39, 8.7245e-39, 9.2755e-39]])

創建一個5x3的隨機初始化Tencor

x  = torch.rand(5,3)
print(x)
tensor([[0.8809, 0.5242, 0.8139],
        [0.1677, 0.4035, 0.3680],
        [0.4707, 0.9393, 0.5377],
        [0.7676, 0.7518, 0.4257],
        [0.7233, 0.4705, 0.3036]])

創建一個全0的long型Tensor

x = torch.zeros(5,3,dtype = torch.long)
print(x)
print(x[1][1])
print(type(x[1][1]))
tensor([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])
tensor(0)
<class 'torch.Tensor'>

還可以根據數據直接創建Tensor

x = torch.tensor([6.6,8])
print(x)
tensor([6.6000, 8.0000])

通過現有的Tensor 來創建新的數據

y =x.new_ones(5,3,dtype = torch.float64)
print(y)
z = torch.randn_like(y,dtype = torch.float)
print(z)
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
tensor([[ 0.3913,  1.5179,  1.6415],
        [ 1.2150, -0.1650, -0.7815],
        [-0.2489,  0.5252, -1.2605],
        [ 0.5305,  0.1410, -0.6449],
        [-1.4771,  0.1270,  0.6471]])

可以通過shape 或者 size() 來獲取Tensor 的數據形狀

print(y.size())
print(y.shape)
# torch.size 的類型是 tuple
torch.Size([5, 3])
torch.Size([5, 3])
函數 功能
Tensor(*sizes) 基礎構造函數
tensor(data,) 類似np.array的構造函數
ones(*sizes) 全1Tensor
zeros(*sizes) 全0Tensor
eye(*sizes) 對⻆線爲1,其他爲0
arange(s,e,step) 從s到e,步⻓爲step
linspace(s,e,steps) 從s到e,均勻切分成steps份
rand/randn(*sizes) 均勻/標準分佈
normal(mean,std)/uniform(from,to) 正態分佈/均勻分佈
randperm(m) 隨機排列

2.2.2 操作

算數操作

  • 加法 直接利用加號
x  = torch.rand(5,3)
y = torch.rand(5,3)
print(x + y)
tensor([[1.4692, 0.7374, 0.7234],
        [0.8925, 0.7805, 1.3061],
        [0.8631, 1.8786, 1.5237],
        [0.9812, 0.9703, 1.0981],
        [1.1590, 0.7849, 1.1890]])
print(torch.add(x,y))
tensor([[1.4692, 0.7374, 0.7234],
        [0.8925, 0.7805, 1.3061],
        [0.8631, 1.8786, 1.5237],
        [0.9812, 0.9703, 1.0981],
        [1.1590, 0.7849, 1.1890]])
  • 還可以指定輸出
result = torch.empty(5,3)
torch.add(x,y,out = result)
print(result)
# 可以直接指定
result = torch.add(x,y)
print(result)
tensor([[1.4692, 0.7374, 0.7234],
        [0.8925, 0.7805, 1.3061],
        [0.8631, 1.8786, 1.5237],
        [0.9812, 0.9703, 1.0981],
        [1.1590, 0.7849, 1.1890]])
tensor([[1.4692, 0.7374, 0.7234],
        [0.8925, 0.7805, 1.3061],
        [0.8631, 1.8786, 1.5237],
        [0.9812, 0.9703, 1.0981],
        [1.1590, 0.7849, 1.1890]])
  • 另一種加法
y.add(x)
print(y)
tensor([[0.5895, 0.4489, 0.3473],
        [0.0495, 0.6829, 0.5846],
        [0.2628, 0.9495, 0.9024],
        [0.3175, 0.9222, 0.5868],
        [0.1993, 0.7389, 0.7718]])

索引

可以利用類似NumPy的索引方式訪問Tensor的一部分。索引的結果和原數據共享一個內存

y = x[0,:]
y += 1
print(y)
print(x[0,:])
# 索引的數據修改後也改變了原數據
tensor([1.8798, 1.2886, 1.3761])
tensor([1.8798, 1.2886, 1.3761])

其他一些函數

函數 功能
index_select(input,dim,index) 指定維度dim上選取,某行或某列
masked_select(input, mask) 例⼦如上, a[a>0],使⽤ByteTensor進⾏選取
non_zero(input) ⾮0元素的下標
gather(input, dim, index) 根據index,在dim維度上選取數據,輸出的size與index⼀樣

改變Tensor的形狀

可以用view()來改變Tensor的形狀,就是改變矩陣的行列

y = x.view(15) # 將5行3列的矩陣改變爲一維行向量
z = x.view(-1,5) # -1 表示該位置自動識別,後面是5列 所以-1位置應該爲3
print(x.size(),y.size(),z.size())
torch.Size([5, 3]) torch.Size([15]) torch.Size([3, 5])

這裏的新tensor與原tensor共享內存,一改則都改

如果需要複製可以使用clone再使用view

x_cp = x.clone().view(15)
x -= 1
print(x)
print(x_cp)
tensor([[ 0.8798,  0.2886,  0.3761],
        [-0.1569, -0.9025, -0.2784],
        [-0.3997, -0.0710, -0.3788],
        [-0.3363, -0.9519, -0.4887],
        [-0.0403, -0.9539, -0.5827]])
tensor([1.8798, 1.2886, 1.3761, 0.8431, 0.0975, 0.7216, 0.6003, 0.9290, 0.6212,
        0.6637, 0.0481, 0.5113, 0.9597, 0.0461, 0.4173])

item() 可以將標量的Tensor轉換成Python number

x = torch.randn(1)
print(x)
print(x.item())
tensor([-0.5851])
-0.585087776184082
  • torch.rand() 與 torch.randn()

torch.rand() 是均勻分佈([0,1]之間隨機抽取)
torch.randn() 是標準正態分佈(均值爲0 方差爲1)

線性代數

函數 功能
trace 對⻆線元素之和(矩陣的跡)
diag 對⻆線元素
triu/tril 矩陣的上三⻆/下三⻆,可指定偏移量
mm/bmm 矩陣乘法, batch的矩陣乘法
addmm/addbmm/addmv/addr/badbmm… 矩陣運算
t 轉置
dot/cross 內積/外積
inverse 求逆矩陣
svd 奇異值分解
x = torch.rand(3,3)
print(x)
print('x的對角元素之和爲:{}'.format(x.trace()))
print('x的對角元素爲:{}'.format(x.diag()))
print('x的上三角:{}'.format(x.triu()))
print('x的轉置:{}'.format(x.t()))

tensor([[0.8447, 0.7846, 0.1641],
        [0.5459, 0.4649, 0.9806],
        [0.1267, 0.0251, 0.9043]])
x的對角元素之和爲:2.2139716148376465
x的對角元素爲:tensor([0.8447, 0.4649, 0.9043])
x的上三角:tensor([[0.8447, 0.7846, 0.1641],
        [0.0000, 0.4649, 0.9806],
        [0.0000, 0.0000, 0.9043]])
x的轉置:tensor([[0.8447, 0.5459, 0.1267],
        [0.7846, 0.4649, 0.0251],
        [0.1641, 0.9806, 0.9043]])

2.2.3 廣播機制

所謂廣播機制,就是在處理數據維度不相等的數據時,會自動將數據補全成相同大小

例如:

x = torch.arange(1,3).view(1,2)
print(x)
y = torch.arange(1,4).view(3,1)
print(y)
print(x + y)

tensor([[1, 2]])
tensor([[1],
        [2],
        [3]])
tensor([[2, 3],
        [3, 4],
        [4, 5]])

2.2.4 運算的內存開銷

利用Python中自帶的id函數 驗證前面的內存地址差異

x = torch.tensor([1,2])
y = torch.tensor([3,4])
print(id(y))
y = y + x  # 賦值運算 所以開闢新內存
print(id(y))
y += x  # 不開闢新內存  也可以使用.add()
print(id(y))
print(y)
torch.add(x,y,out = y)
# y.add_(x)
print(id(y))
print(y)

1714379452136
1714379449544
1714379449544
tensor([5, 8])
1714379449544
tensor([ 6, 10])

區分一下add(x,y,out = y) 和 .add()
前者在torch下

2.2.5 Tensor和Numpy 互相轉換

利用 numpy() 和 from_numpy() 可以實現Tensor 和 Numpy的數組互相轉換

轉換後數據共享內存

  • Tensor轉爲Numpy
a = torch.ones(5)
b = a.numpy()
print(a,b)

a += 1
print(a,b)
b += 1
print(a,b)

tensor([1., 1., 1., 1., 1.]) [1. 1. 1. 1. 1.]
tensor([2., 2., 2., 2., 2.]) [2. 2. 2. 2. 2.]
tensor([3., 3., 3., 3., 3.]) [3. 3. 3. 3. 3.]
  • Numpy 轉爲 Tensor
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
print(a,b)

a += 1
print(a,b)
b += 1
print(a,b)

[1. 1. 1. 1. 1.] tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
[2. 2. 2. 2. 2.] tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
[3. 3. 3. 3. 3.] tensor([3., 3., 3., 3., 3.], dtype=torch.float64)

【總結】
主要介紹了Tensor 的創建於使用


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章