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 的創建於使用