成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

超全總結!玩轉Pytorch張量(Tensor)!

開發
在深度學習領域,PyTorch是一個廣泛應用的開源庫,Tensor之于PyTorch就好比是array之于Numpy或者DataFrame之于Pandas,都是構建了整個框架中最為底層的核心數據結構。

一、什么是張量(Tensor)?

在深度學習領域,PyTorch是一個廣泛應用的開源庫,Tensor之于PyTorch就好比是array之于Numpy或者DataFrame之于Pandas,都是構建了整個框架中最為底層的核心數據結構。Pytorch中的所有操作都是在張量的基礎上進行的。

PyTorch官網對其的定義如下:

也就是說,一個Tensor是一個包含單一數據類型的多維矩陣。通常,其多維特性用三維及以上的矩陣來描述,例如下圖所示:單個元素為標量(scalar),一個序列為向量(vector),多個序列組成的平面為矩陣(matrix),多個平面組成的立方體為張量(tensor)。

當然,張量也無需嚴格限制在三維及以上才叫張量,就像矩陣也有一維、二維矩陣乃至多維矩陣之分一樣。

「在深度學習的范疇內,標量、向量和矩陣也可分為稱為零維張量、一維張量、二維張量?!?/p>

二、為什么深度學習要搞出Tensor?

熟悉機器學習的小伙伴們應該都知道,有監督機器學習模型的輸入X通常是多個特征列組成的二維矩陣,輸出y是單個特征列組成的標簽向量或多個特征列組成的二維矩陣。那么深度學習中,為何要定義多維矩陣Tensor呢?

深度學習當前最成熟的兩大應用方向莫過于CV和NLP,其中CV面向圖像和視頻,NLP面向語音和文本,二者分別以卷積神經網絡和循環神經網絡作為核心基礎模塊,且標準輸入數據集都是至少三維以上。其中,

  • 圖像數據集:至少包含三個維度(樣本數Nx圖像高度Hx圖像寬度W);如果是彩色圖像,則還需增加一個通道C,包含四個維度(NxHxWxC);如果是視頻幀,可能還需要增加一個維度T,表示將視頻劃分為T個等時長的片段。
  • 文本數據集:包含三個維度(樣本數N×序列長度L×特征數H)。

因此,輸入學習模型的輸入數據結構通常都要三維以上,這也就促使了Tensor的誕生。

三、Tensor創建

Pytorch可基于給定數據手動創建Tensor,并提供了多種方式:

1.使用torch.tensor()函數直接創建

在PyTorch中,torch.tensor()函數用于直接從Python的數據結構(如列表、元組或NumPy數組)中創建一個新的張量。

"""
data:數據,可以是list,numpy
dtype:數據類型,默認與data對應
device:張量所在的設備(cuda或cpu)
requires_grad:是否需要梯度
pin_memory:是否存于鎖存內存
"""
torch.tensor(data,dtype=None,device=None,requires_grad=False,pin_memory=False)

pin_memor用于實現鎖頁內存,創建DataLoader時,設置pin_memory=True,則意味著生成的Tensor數據最開始是屬于內存中的鎖頁內存,這樣將內存的Tensor轉義到GPU的顯存就會更快一些。

以下是使用torch.tensor()創建張量的基本示例:

import numpy as np
import torch
arr = np.ones((3, 3))
'''
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
'''
print(arr)
# ndarray的數據類型:float64
print("ndarray的數據類型:", arr.dtype)
t= torch.tensor(arr)
'''
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
'''
print(t)

如需創建一個放在GPU的數據,則可做如下修改,運行結果同上。

import numpy as np
import torch
device= torch.device("cuda" if torch.cuda.is_available() else 'cpu')
arr = np.ones((3, 3))
print("ndarray的數據類型:", arr.dtype)
t = torch.tensor(arr, device=device)
print(t)

2.從numpy創建Tensor

torch.from_numpy(ndarray)

利用該方法創建的tensor與原ndarray共享內存,當修改其中一個數據,另外一個也會被更新。

import numpy as np
import torch
# 創建一個numpy數組
numpy_array = np.array([[1, 2, 3], [4, 5, 6]])

# 從numpy數組創建一個Tensor,并保持數據共享(更改Tensor內容會同時改變numpy數組)
tensor_from_numpy = torch.from_numpy(numpy_array)
print(tensor_from_numpy)

# 輸出:
# tensor([[1, 2, 3],
#         [4, 5, 6]], dtype=torch.int32)

# 修改tensor,array也會被修改
print("# -----------修改tensor--------------*")
t[0, 0] = -1
print("numpy array: ", arr)
# 輸出:
# numpy array:  [[-1  2  3]
#               [ 4  5  6]]
print("tensor : ", t)
# 輸出:
# tensor([[-1, 2, 3],
#         [4, 5, 6]], dtype=torch.int32)

3.根據數值創建張量

(1) torch.zeros():根據size創建全0張量

'''
size:張量的形狀
out:輸出的張量,如果指定了out,torch.zeros()返回的張量則會和out共享同一個內存地址
layout:內存中的布局方式,有strided,sparse_coo等。如果是稀疏矩陣,則可以設置為sparse_coo以減少內存占用
device:張量所在的設備(cuda或cpu)
requires_grad:是否需要梯度
'''
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
import torch
out_t = torch.tensor([1])
print(f"out_t初始值:{out_t}")
#指定out
t = torch.zeros((3, 3), out=out_t)
print(f"t:\n{t}")
print(f"out_t更新值:\n{out_t}")
# id是取內存地址,t和out_t是同一個內存地址
print(id(t), id(out_t), id(t) == id(out_t))

運行結果如下,由此可見,和out_t最終共享同一個內存地址。

out_t初始值:tensor([1])
t:
tensor([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])
out_t更新值:
tensor([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])
2083081770704 2083081770704 True

(2) torch.zeros_like:根據input形狀創建全0張量

torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)

同理還有全1張量的創建:torch.ones(),torch.ones_like()

(3) torch.full() & torch.full_like():創建自定義某一數值的張量。

'''
size:張量的形狀,例如(3,3)
fill_value:張量中每一個元素的值。
'''

torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

例如:

import torch
t = torch.full((4, 4), 10)
print(t)
'''
tensor([[10, 10, 10, 10],
        [10, 10, 10, 10],
        [10, 10, 10, 10],
        [10, 10, 10, 10]])
'''

(4) 創建等差的一維張量。

?注意區間為:[start,end)。

'''
start:數列起始值,默認為0
end:數列結束值,開區間,取不到結束值
step:數列公差,默認為1
'''
torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

例如:

import torch
t = torch.arange(2, 10, 2)
print(t) # tensor([2, 4, 6, 8])

(5) torch.linspace():創建均分的一維張量

?注意區間為:[start,end]。

'''
step:數列長度(元素個數)
'''
torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
import torch
t = torch.linspace(2, 10, 3)
print(t) # tensor([ 2.,  6., 10.])

(6) torch.logspace():創建對數均分的一維張量

?注意區間為:[start,end]。

'''
step:數列長度(元素個數)
base:對數函數的底,默認為 10
'''
torch.logspace(start, end, steps, base=10, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
import torch
t = torch.logspace(2, 4, 3)
print(t) # tensor([100.,  1000., 10000.])

(7) torch.eye():創建單位對角矩陣(2維張量)

?默認輸出方陣。

'''
n: 矩陣行數。因為是方陣,通常只設置n
m: 矩陣列數
'''
torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
import torch
t = torch.eye(3)
h = torch.eye(3,4)
print(f"t:{t}")
print(f"h:{h}")

運行結果如下:

t:tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])
h:tensor([[1., 0., 0., 0.],
        [0., 1., 0., 0.],
        [0., 0., 1., 0.]])

4.根據概率創建張量

(1) torch.normal():生成正態分布(高斯分布)

?返回一個張量,包含從給定參數means、std的離散正態分布中抽取的隨機數。

'''
mean:均值
std:標準差
'''
torch.normal(mean, std, *, generator=None, out=None)

包含4種模式:

  • mean為標量,std為標量,此時需要設置size。
import torch
t_normal = torch.normal(0., 1., size=(4,))
# t_normal:tensor([ 0.7098,  1.5432, -0.1568, -0.6350])
print(f"t_normal:{t_normal}")

mean為張量,std為標量。

import torch
mean = torch.arange(1, 5, dtype=torch.float)
std = 1
t_normal = torch.normal(mean, std)
'''
mean:tensor([1., 2., 3., 4.])
std:1
'''
print("mean:{}\nstd:{}".format(mean, std))
#tensor([2.2450, 1.0230, 2.0299, 4.5855])
print(t_normal)

這4個數采樣分布的均值不同,但是方差都是 1。

  • mean為標量,std為張量。
import torch
std = torch.arange(1, 5, dtype=torch.float)
mean = 2
t_normal = torch.normal(mean, std)
'''
mean:2
std:tensor([1., 2., 3., 4.])
'''
print("mean:{}\nstd:{}".format(mean, std))
# tensor([ 1.8482,  4.8143, -3.5074,  4.2010])
print(t_normal)
  • mean為張量,std為張量。
import torch
mean = torch.arange(1, 5, dtype=torch.float)
std = torch.arange(1, 5, dtype=torch.float)
t_normal = torch.normal(mean, std)
'''
mean:tensor([1., 2., 3., 4.])
std:tensor([1., 2., 3., 4.])
'''
print("mean:{}\nstd:{}".format(mean, std))
# tensor([ 0.8195, -3.9112,  4.8498,  2.3934])
print(t_normal)

其中0.8195是從正態分布N(1,1)中采樣得到的,-3.9112是從正態分布N(2,2)中采樣得到的,其他數字以此類推。

四、Tensor屬性

1.Tensor形狀

張量具有如下形狀屬性:

  • Tensor.ndim:張量的維度,例如向量的維度為1,矩陣的維度為2。
  • Tensor.shape:張量每個維度上元素的數量。
  • Tensor.shape[n]:張量第n維的大小。第n維也稱為軸(axis)。
  • Tensor.numel:張量中全部元素的個數。

如下是創建一個四維Tensor,并通過圖形直觀表達以上幾個概念的關系。

import torch
Tensor=torch.ones([2,3,4,5])
print("Number of dimensions:", Tensor.ndim)
print("Shape of Tensor:", Tensor.shape)
print("Elements number along axis 0 of Tensor:", Tensor.shape[0])
print("Elements number along the last axis of Tensor:", Tensor.shape[-1])
print('Number of elements in Tensor: ', Tensor.numel())  #用.numel表示元素個數

Tensor的axis、shape、dimension、ndim之間的關系如下圖所示。

2.Tensor數據類型

torch.dtype屬性標識了torch.Tensor的數據類型。PyTorch有八種不同的數據類型:

例如:

import torch
Tensor=torch.ones([2,3,4,5])
# Data Type of every element: torch.float32
print("Data Type of every element:", Tensor.dtype)

3.Tensor所在設備

如圖所示,我們可以看到每種類型的數據都有一個CPU和一個GPU版本,因此我們對張量進行處理的時候需要指定一個設備,它要么是CPU要么是GPU,這是數據被分配的位置,這決定了給定張量的張量計算位置。

Pytorch支持多種設備的使用,我們可以用torch.device來創建一個設備,并指定索引,例如:

device=torch.device('cuda:0')

輸出結果為:device(type='cuda',index=0),可看到類型為'cuda',即GPU,索引0表示為第一個GPU。

五、Tensor操作

1.形狀重置

Tensor的shape可通過torch.reshape接口來改變。例如:

import torch
Tensor =torch.tensor([[[1, 2, 3, 4, 5],
                        [6, 7, 8, 9, 10]],
                      [[11, 12, 13, 14, 15],
                        [16, 17, 18, 19, 20]],
                      [[21, 22, 23, 24, 25],
                        [26, 27, 28, 29, 30]]])
print("the shape of Tensor:", Tensor.shape)
#利用reshape改變形狀
reshape_Tensor = torch.reshape(Tensor, [2, 5, 3])
print("After reshape:\n", reshape_Tensor)

從輸出結果看,將張量從[3, 2, 5]的形狀reshape為[2, 5, 3]的形狀時,張量內的數據不會發生改變,元素順序也沒有發生改變,只有數據形狀發生了改變。

在指定新的shape時存在一些技巧:

  • -1 表示這個維度的值是從Tensor的元素總數和剩余維度自動推斷出來的。因此,有且只有一個維度可以被設置為-1。
  • 0 表示該維度的元素數量與原值相同,因此shape中0的索引值必須小于Tensor的維度(索引值從 0 開始計,如第 1 維的索引值是 0,第二維的索引值是 1)。

例如:

# 直接指定目標 shape
origin:[3, 2, 5] reshape:[3, 10] actual: [3, 10]
# 轉換為 1 維,維度根據元素總數推斷出來是 3*2*5=30
origin:[3, 2, 5] reshape:[-1] actual: [30]
# 轉換為 2 維,固定一個維度 5,另一個維度根據元素總數推斷出來是 30÷5=6
origin:[3, 2, 5] reshape:[-1, 5]      actual: [6, 5]
# reshape:[0, -1]中 0 的索引值為 0,按照規則
# 轉換后第 0 維的元素數量與原始 Tensor 第 0 維的元素數量相同,為3
# 第 1 維的元素數量根據元素總值計算得出為 30÷3=10。
origin:[3, 2, 5] reshape:[0, -1]      actual: [3, 10]
# reshape:[3, 1, 0]中 0 的索引值為 2
# 但原 Tensor 只有 2 維,無法找到與第 3 維對應的元素數量,因此出錯。
origin:[3, 2] reshape:[3, 1, 0]       error:

另外還可以通過如下方式改變shape:

  • torch.squeeze:可實現Tensor的降維操作,即把Tensor中尺寸為1的維度刪除。
  • torch.unsqueeze:可實現Tensor的升維操作,即向Tensor中某個位置插入尺寸為1的維度。
  • torch.flatten,將Tensor的數據在指定的連續維度上展平。
  • torch.transpose,對Tensor的數據進行重排。

2.索引和切片

通過索引或切片方式可訪問或修改Tensor。

(1) 「訪問Tensor」

import torch
ndim_2_Tensor = torch.tensor([[0, 1, 2, 3],
                               [4, 5, 6, 7],
                               [8, 9, 10, 11]])
print("Origin Tensor:\n", ndim_2_Tensor.numpy())
#索引或切片的第一個值對應第 0 維,第二個值對應第 1 維,
#依次類推,如果某個維度上未指定索引,則默認為 :
#所以下面兩種操作結果一樣
print("First row:", ndim_2_Tensor[0].numpy())
print("First row:", ndim_2_Tensor[0, :].numpy())
print("First column:", ndim_2_Tensor[:, 0].numpy())
print("Last column:", ndim_2_Tensor[:, -1].numpy())
print("All element:\n", ndim_2_Tensor[:].numpy())
print("First row and second column:", ndim_2_Tensor[0, 1].numpy())

(2) 「修改Tensor」

與訪問張量類似,可以在單個或多個軸上通過索引或切片操作來修改張量。

import torch
ndim_2_Tensor = torch.ones([2, 3])
ndim_2_Tensor = ndim_2_Tensor.to(torch.float32)
print('Origin Tensor:\n ', ndim_2_Tensor)
# 修改第1維為0
ndim_2_Tensor[0] = 0
print('change Tensor:\n ', ndim_2_Tensor)
# 修改第1維為2.1
ndim_2_Tensor[0:1] = 2.1
print('change Tensor:\n ', ndim_2_Tensor)
# 修改全部Tensor
ndim_2_Tensor[...] = 3
print('change Tensor:\n ', ndim_2_Tensor)

3.Tensor運算

張量支持包括基礎數學運算、邏輯運算、矩陣運算等100余種運算操作。

數學運算:

x.abs()                       # 逐元素取絕對值
x.ceil()                      # 逐元素向上取整
x.floor()                     # 逐元素向下取整
x.round()                     # 逐元素四舍五入
x.exp()                       # 逐元素計算自然常數為底的指數
x.log()                       # 逐元素計算x的自然對數
x.reciprocal()                # 逐元素求倒數
x.square()                    # 逐元素計算平方
x.sqrt()                      # 逐元素計算平方根
x.sin()                       # 逐元素計算正弦
x.cos()                       # 逐元素計算余弦
x.add(y)                      # 逐元素加
x.subtract(y)                 # 逐元素減
x.multiply(y)                 # 逐元素乘(積)
x.divide(y)                   # 逐元素除
x.mod(y)                      # 逐元素除并取余
x.pow(y)                      # 逐元素冪
x.max()                       # 指定維度上元素最大值,默認為全部維度
x.min()                       # 指定維度上元素最小值,默認為全部維度
x.prod()                      # 指定維度上元素累乘,默認為全部維度
x.sum()                       # 指定維度上元素的和,默認為全部維度

邏輯運算:

x.isfinite()                  # 判斷Tensor中元素是否是有限的數字,即不包括inf與nan
x.equal_all(y)                # 判斷兩個Tensor的全部元素是否相等,并返回形狀為[1]的布爾類Tensor
x.equal(y)                    # 判斷兩個Tensor的每個元素是否相等,并返回形狀相同的布爾類Tensor
x.not_equal(y)                # 判斷兩個Tensor的每個元素是否不相等
x.less_than(y)                # 判斷Tensor x的元素是否小于Tensor y的對應元素
x.less_equal(y)               # 判斷Tensor x的元素是否小于或等于Tensor y的對應元素
x.greater_than(y)             # 判斷Tensor x的元素是否大于Tensor y的對應元素
x.greater_equal(y)            # 判斷Tensor x的元素是否大于或等于Tensor y的對應元素
x.allclose(y)                 # 判斷兩個Tensor的全部元素是否接近

矩陣運算:

x.t()                         # 矩陣轉置
x.transpose([1, 0])           # 交換第 0 維與第 1 維的順序
x.norm('fro')                 # 矩陣的弗羅貝尼烏斯范數
x.dist(y, p=2)                # 矩陣(x-y)的2范數
x.matmul(y)                   # 矩陣乘法

4.Tensor廣播機制

深度學習任務中,通常不可避免會遇到需要使用較小形狀的Tensor與較大形狀的Tensor執行計算的情況。此時,則需要將較小形狀的Tensor擴展到與較大形狀的Tensor一樣的形狀,以便于匹配計算,但是又「不會」對較小形狀Tensor進行「數據拷貝」操作,從而「提升算法實現的運算效率」。這即是廣播機制。

Tensor廣播機制通常遵循如下規則:

  • 每個 Tensor 至少為一維 Tensor。
  • 從最后一個維度向前開始比較兩個Tensor的形狀,需要滿足如下條件才能進行廣播:
  • 兩個Tensor的維度大小相等;或者其中一個Tensor的維度為1;或者其中一個Tensor的維度不存在。

例如:

兩個Tensor的形狀一致,可以廣播。

import torch

x = torch.ones((2, 3, 4))
y = torch.ones((2, 3, 4))
z = x + y
print(z)
# tensor([[[2., 2., 2., 2.],
         [2., 2., 2., 2.],
         [2., 2., 2., 2.]],

         [[2., 2., 2., 2.],
         [2., 2., 2., 2.],
         [2., 2., 2., 2.]]])
print(z.shape)
# torch.Size([2, 3, 4])

從最后一個維度向前依次比較:第一次y的維度大小為1,第二次x的維度大小為1,第三次x和y的維度大小相等,第四次y的維度不存在,所以x和y可以廣播。

import torch

x = torch.ones((2, 3, 1, 5))
y = torch.ones((3, 4, 1))

z = x + y
print(z.shape)
# torch.Size([2, 3, 4, 5])

從最后一個維度向前依次比較:第一次比較:4不等于6,不可廣播。

x = torch.ones((2, 3, 4))
y = torch.ones((2, 3, 6))
# z = x + y
# ValueError: (InvalidArgument) Broadcast dimension mismatch.

兩個Tensor進行廣播后的結果Tensor的形狀計算規則如下:

  • 如果兩個 Tensor 的形狀的長度不一致,會在較小長度的形狀矩陣前部添加 1,直到兩個 Tensor 的形狀長度相等。
  • 保證兩個 Tensor 形狀相等之后,每個維度上的結果維度就是當前維度上的較大值。

例如,y的形狀長度為2,小于x的形狀長度3,因此會在 y 的形狀前部添加 1,結果就是 y 的形狀變為[1, 3, 1]。廣播之后z的形狀為[2,3,4],且z的每一維度上的尺寸,將取x和y對應維度上尺寸的較大值,如第0維x的尺寸為2,y的尺寸為1,則z的第0維尺寸為2。

import torch

x = torch.ones((2, 1, 4))
y = torch.ones((3, 1))
z = x + y
print(z.shape)
# torch.Size([2, 3, 4])

廣播機制運行過程如下圖:

圖片圖片

責任編輯:趙寧寧 來源: 數據科學與AI
相關推薦

2021-11-05 12:59:51

深度學習PytorchTenso

2024-05-10 12:59:58

PyTorch人工智能

2024-12-31 07:00:00

2021-12-29 09:00:36

Go文件syscall

2020-09-15 15:50:33

Python編程語言代碼

2024-06-11 07:34:58

C#字符串性能

2024-01-05 17:15:21

pytorchtensor深度學習

2017-09-05 10:20:30

PyTorchTensorPython

2024-03-22 15:32:21

機器學習算法

2011-09-02 14:59:15

2025-01-20 08:00:00

圖像增強深度學習AI

2019-09-17 14:16:57

工具代碼開發

2024-10-22 15:51:42

PyTorch張量

2010-03-15 15:45:50

2009-10-21 17:02:51

綜合布線施工經驗

2024-10-16 10:03:13

2023-01-03 17:31:52

2015-05-27 14:55:45

2022-01-03 16:08:36

深度學習PyTorchNumPy

2017-12-29 21:49:36

信息安全網絡攻擊漏洞
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产高清一区二区三区 | 欧美精选一区二区 | 激情av网站| 五月婷婷在线播放 | h视频在线观看免费 | 久久av一区二区 | 91天堂网| 精品视频一区二区三区在线观看 | 国产精品毛片在线 | 久久精品成人热国产成 | 亚洲欧美激情网 | 亚洲午夜精品一区二区三区 | 韩国久久| 中文字幕第三页 | 精品视频在线播放 | 久久香焦| 亚洲激情综合网 | 超碰av在线 | 日韩国产精品一区二区三区 | 国产黄色麻豆视频 | 性色视频 | 国产视频一区二区三区四区五区 | 91精品国产91久久久久久吃药 | 亚洲区一区二 | 亚洲毛片一区二区 | 欧美精品一区三区 | 久久综合888 | 欧美视频一区二区三区 | 日本不卡一区二区三区在线观看 | 成人亚洲精品久久久久软件 | 国产精品美女视频 | 国产最新网址 | 喷潮网站| 亚洲区一区二 | 亚洲视频欧美视频 | 亚洲精品一 | 亚洲综合色网站 | 精产国产伦理一二三区 | 女人牲交视频一级毛片 | 国产区在线视频 | 一区二区国产在线观看 |