Tensor數據操作


* torch.Tensor 存儲和變換數據的工具

* Tensor與Ndarray多維數組類似,可提供GPU計算和自動求梯度

* 標量:0緯張量,一個數字

* 向量:1緯張量,[ ]

* 矩陣:2緯張量,[ [ ] ]

 

首先導入torch,查看版本號

import torch

#打印torch版本
print(torch.__version__)

#查看是否支持GPU
torch.cuda.is_avaliable()
代碼運行后的結果是:
1.4.0
True

1.創建Tensor

1.11 直接創建

* torch.tensor(value)
* value:可以是任何維度的張量

print("創建一個標量5")
x = torch.tensor(5)
print("創建一個向量[]")
y = torch.tensor([2,3])
print("創建一個矩陣[ [ ] ]")
z = torch.tensor([[1,2],
                 [2,3]])
print(x)
print(y)
print(z)
輸出結果是:
創建一個標量5
創建一個向量[]
創建一個矩陣[ [ ] ]
tensor(5)
tensor([2, 3])
tensor([[1, 2],
        [2, 3]])

1.2使用方法創建

* torch.empty(shape,dtype = type):創建未初始化的Tensor,可指定數據類型,dtype參數可省略
* torch.rand(shape) :創建隨機矩陣
* torch.zeros(shape):創建0矩陣
* 創建維度均為2緯矩陣

print("創建二維未初始化矩陣")
A = torch.empty((2,2))
print(A)
print("創建隨機矩陣")
B = torch.rand((2,2))
print(B)
print("創建0矩陣")
C = torch.zeros((2,2))
print(C)
輸出結果是:
創建二維未初始化矩陣
tensor([[ 0.0000e+00,  1.4279e+00],
        [-9.3980e-11,  4.5908e-41]])
創建隨機矩陣
tensor([[0.3857, 0.0058],
        [0.1388, 0.9339]])
創建0矩陣
tensor([[0., 0.],
        [0., 0.]])

1.3通過現有的Tensor創建

* matrix.new_ones(shape,dtype) 可以改變維度
* torch.randn_like(matirx,dtype)

print("將原本2*2未初始化矩陣進行重新創建")
B = B.new_ones(5,3)
print(B)
print("將原本2*2未初始化矩陣進行重新創建")
A = torch.randn_like(A, dtype = torch.float)
print(A)
輸出結果是:
將原本2*2未初始化矩陣進行重新創建
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
將原本2*2未初始化矩陣進行重新創建
tensor([[ 0.1454, -0.1173],
        [-0.7503,  0.5255]])

1.4Tensor的基本方法

* matrix.shape: 獲取Tensor形狀
* matirx.size():獲取Tensor形狀 返回一個tuple,支持tuple的所有操作

print("獲取B矩陣形狀")
print(B.shape)
print(B.size())
輸出結果是:
獲取B矩陣形狀
torch.Size([5, 3])
torch.Size([5, 3])

2 Tensor操作

2.1 算法操作

2.11 加法操作

* matrix1 + matirx2
* torch.add(matrix1, matrix2, out = A) out指定輸出參數,可省略
* inplace matrix1.add_(matrix2) == (matirx1 += matrix2)

print("使用 + 完成加法操作")
print(A + C)
print("使用torch.add完成加法操作")
print(torch.add(A,C))
print("使用inplace完成加法操作")
print(C.add_(A))
輸出結果是:
使用 + 完成加法操作
tensor([[ 0.1454, -0.1173],
        [-0.7503,  0.5255]])
使用torch.add完成加法操作
tensor([[ 0.1454, -0.1173],
        [-0.7503,  0.5255]])
使用inplace完成加法操作
tensor([[ 0.1454, -0.1173],
        [-0.7503,  0.5255]])

2.1.2 索引

* 類似於Numpy
* 索引結果與原數據共享內存

A = torch.rand(5,5)
print('查看創建Tensor')
print(A[1][1])
A[1][1] = 5
print("查看A矩陣第一行第一列是否為5")
print(A[1][1])
輸出結果是:
查看創建Tensor
tensor(0.6124)
查看A矩陣第一行第一列是否為5
tensor(5.)

2.1.3 改變形狀

* marix.clone() 克隆新副本,解決共享內存帶來的問題
* matrix.view(shape) view() 前后共享data
* matrix.reshape(shape)

#查看clone與變量賦值的區別
print("查看A變量地址")
print(id(A))
A_cl = A.clone()
print('查看克隆新副本地址')
print(id(A_cl))
A_an = A
print('查看變量重新賦值后的地址')
print(id(A_an))
輸出結果是:
查看A變量地址
2337547400576
查看克隆新副本地址
2337538344512
查看變量重新賦值后的地址
2337547400576

note:這里主要是解釋共享data的問題。直接view()的話維度改變,操作的是同一內存的數據。不會生成新的維度的數據。

* 變量賦值相當於引用,地址不變,只想同一塊內存
* clone()操作會重新申請內存空間
* matrix.item() 將標量Tensor轉化為number

* https://pytorch.org/docs/stable/tensors.html     Tensor操作鏈接

2.1.4 Tensor的廣播機制

* 自動使得運算的Tensor相同的操作
* 首先會比較最靠右的維度,如果最靠右的維度相等或其中一個為 1,則認為此維度相等;
* 再繼續向左比較,如果一直滿足,則認為兩者兼容;
* 最后,分別在對應維度上發生廣播,以此補齊直到維度一致;

x = torch.rand(4 , 6)
y = torch.rand(4,  1)
print(torch.add(x , y))
輸出結果是:
tensor([[0.6108, 0.1842, 0.9873, 0.9042, 0.2456, 0.4298],
        [1.0251, 0.6726, 1.2724, 1.2861, 1.1256, 0.5654],
        [1.0223, 0.3473, 0.5952, 0.3701, 0.4500, 0.4993],
        [0.0542, 0.9524, 0.1668, 0.5762, 0.0671, 0.4689]])

2.1.5 Tensor與Numpy的相互轉換

* tensor.numpy() 可將Tensor轉為ndarray數據

a = torch.rand(3,2)
print(id(a))
b = a.numpy()
print(id(b))
print(a)
print(b)
輸出結果為:
2337547166400
2337547429088
tensor([[0.3145, 0.9862],
        [0.7604, 0.9342],
        [0.3104, 0.7312]])
[[0.31446308 0.9861587 ]
 [0.7603721  0.9341993 ]
 [0.31042498 0.73123205]]

Numpy轉為Tensor

* torch.from_numpy(array)
* torch.Tensor()

import numpy as np
c = torch.from_numpy(b)
d = torch.Tensor(b)
print(type(c))
print(type(d))
<class 'torch.Tensor'>
<class 'torch.Tensor'>

2.1.6 Tensor on GPU

* .to("cuda") 將Tensor在GPU上運算
    x.to("cuda")
* .to(device) 將Tensor在GPU運算
    torch.device("cuda")
    x.to(device)
* .to("cpu") 將Tensor在CPU上運算

驗證GPU的運算速度

%%time #jupyter notebook中的魔法語句,可以輸出當前代碼塊的運行速度
print("使用device")
device = torch.device("cuda")
x = torch.rand(200,100).to(device)
y = torch.rand(200,100).to(device)
print(x + y)
輸出結果是:
使用device
tensor([[1.3311, 1.7433, 1.1089,  ..., 0.8775, 1.1430, 0.4877],
        [1.1953, 0.3628, 0.6479,  ..., 0.4781, 0.9154, 1.3447],
        [1.2134, 0.5482, 1.7713,  ..., 0.9025, 1.1786, 0.2083],
        ...,
        [0.9276, 0.8605, 0.9905,  ..., 0.9992, 1.1613, 0.8636],
        [1.2191, 0.6350, 0.9921,  ..., 1.7540, 1.0139, 1.2921],
        [1.2137, 0.9510, 0.9126,  ..., 0.8433, 0.5871, 1.0881]],
       device='cuda:0')
Wall time: 6.45 s

驗證CPU運算速度

%%time
print("使用CPU")
x = torch.rand(200,100).to("cpu")
y = torch.rand(200,100).to("cpu")
print(x + y)
輸出結果是:
使用CPU
tensor([[1.4920, 1.1891, 0.0936,  ..., 0.5056, 1.6395, 1.0162],
        [1.4211, 0.9837, 1.1501,  ..., 1.2990, 0.7121, 0.3505],
        [1.1503, 1.0263, 1.4055,  ..., 0.6856, 0.3320, 0.7620],
        ...,
        [0.4615, 1.0520, 1.3409,  ..., 1.1014, 1.0806, 0.9630],
        [0.9770, 1.4159, 1.6652,  ..., 0.9515, 1.2479, 1.2459],
        [0.7622, 0.9159, 0.9734,  ..., 0.5249, 0.1216, 0.6906]])
Wall time: 112 ms

查看同樣維度矩陣計算GPU與CPU的速度差異

print("GPU 比 CPU 的運算速度塊: %.2f 倍" %(112 / 6.45))
輸出結果是:
GPU 比 CPU 的運算速度塊: 17.36 倍

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM