PyTorch 張量的基本操作
PyTorch 張量詳解
基本概念
PyTorch 張量(Tensor)是 PyTorch 中的核心數(shù)據(jù)結(jié)構(gòu),類似于 NumPy 的 ndarray,但具有 GPU 加速能力。張量是一個(gè)多維數(shù)組,可以包含標(biāo)量(0維)、向量(1維)、矩陣(2維)以及更高維度的數(shù)據(jù)。在深度學(xué)習(xí)應(yīng)用中,張量通常用于表示神經(jīng)網(wǎng)絡(luò)的輸入數(shù)據(jù)、權(quán)重參數(shù)和梯度信息。
張量的維度與詳細(xì)示例
0維張量(標(biāo)量)
0維張量是最基本的張量形式,僅包含一個(gè)數(shù)值,不包含任何維度信息。在PyTorch中創(chuàng)建時(shí)不需要使用方括號(hào)包裹。
- 示例1:
torch.tensor(3.14)表示一個(gè)簡(jiǎn)單的浮點(diǎn)數(shù)值 - 示例2:
torch.tensor(True)表示一個(gè)布爾值 - 應(yīng)用場(chǎng)景:神經(jīng)網(wǎng)絡(luò)中的損失值、準(zhǔn)確率等單一指標(biāo)的表示
1維張量(向量)
1維張量包含一個(gè)軸(維度),可以看作是一組有序的數(shù)值集合。通常用于表示特征向量、時(shí)間序列等。
- 示例1:
torch.tensor([1, 2, 3])表示一個(gè)包含3個(gè)元素的行向量 - 示例2:
torch.tensor([0.1, 0.5, 0.9])表示神經(jīng)網(wǎng)絡(luò)的輸出概率 - 形狀表示:
(n,)其中n是向量長(zhǎng)度 - 應(yīng)用場(chǎng)景:全連接層的輸入/輸出、詞嵌入表示等
2維張量(矩陣)
2維張量包含兩個(gè)軸,通常表示為行和列的結(jié)構(gòu)。在深度學(xué)習(xí)中廣泛用于權(quán)重矩陣、特征矩陣等。
- 示例1:
torch.tensor([[1, 2], [3, 4]])表示一個(gè)2×2的矩陣 - 示例2:
torch.zeros((3, 4))創(chuàng)建3行4列的全零矩陣 - 形狀表示:
(m, n)其中m是行數(shù),n是列數(shù) - 應(yīng)用場(chǎng)景:全連接層的權(quán)重參數(shù)、批量處理時(shí)的特征矩陣等
3維張量
3維張量在計(jì)算機(jī)視覺中特別常見,通常用于表示批量的圖像數(shù)據(jù)或序列數(shù)據(jù)。
典型形狀:
(batch_size, channels, height, width)batch_size:一次處理的樣本數(shù)量channels:顏色通道數(shù)(RGB圖像為3,灰度圖為1)height:圖像高度(像素?cái)?shù))width:圖像寬度(像素?cái)?shù))
示例1:
torch.randn(16, 3, 224, 224)表示16張224×224像素的RGB圖像示例2:
torch.zeros(32, 1, 28, 28)表示32張28×28像素的灰度圖應(yīng)用場(chǎng)景:卷積神經(jīng)網(wǎng)絡(luò)的輸入、視頻數(shù)據(jù)處理、自然語言處理中的詞序列等
與 NumPy 數(shù)組的比較
與 NumPy 數(shù)組相比,PyTorch 張量具有以下獨(dú)特優(yōu)勢(shì):
GPU 加速支持
- 可以輕松將張量轉(zhuǎn)移到 GPU 上進(jìn)行高效計(jì)算
- 使用方法:tensor.cuda() 或 tensor.to('cuda')
- 示例:在圖像分類任務(wù)中,可以將批量圖像張量轉(zhuǎn)移到 GPU 加速卷積運(yùn)算
自動(dòng)微分能力
- 內(nèi)置支持自動(dòng)微分,便于神經(jīng)網(wǎng)絡(luò)訓(xùn)練
- 通過設(shè)置 requires_grad=True 啟用自動(dòng)求導(dǎo)
- 示例:在訓(xùn)練 CNN 時(shí),PyTorch 會(huì)自動(dòng)計(jì)算損失函數(shù)對(duì)網(wǎng)絡(luò)參數(shù)的梯度
動(dòng)態(tài)計(jì)算圖
- 支持動(dòng)態(tài)構(gòu)建計(jì)算圖,靈活性更高
- 計(jì)算圖在每次前向傳播時(shí)動(dòng)態(tài)構(gòu)建
- 應(yīng)用場(chǎng)景:在RNN處理變長(zhǎng)序列時(shí)特別有用
實(shí)際應(yīng)用場(chǎng)景
- 計(jì)算機(jī)視覺:4D張量表示圖像批次 (batch, channel, height, width)
- 自然語言處理:3D張量表示文本序列 (batch, sequence_length, embedding_dim)
- 強(qiáng)化學(xué)習(xí):2D張量表示狀態(tài)空間 (batch, state_dimension)
性能優(yōu)化建議
- 盡量使用矢量化操作代替循環(huán)
- 合理使用 inplace 操作節(jié)省內(nèi)存
- 注意 CPU 和 GPU 之間的數(shù)據(jù)傳輸開銷
張量創(chuàng)建方式
從 Python 列表創(chuàng)建
import torch # 創(chuàng)建一維張量(向量) tensor1d = torch.tensor([1.0, 2.0, 3.0]) # 浮點(diǎn)型向量 tensor1d_int = torch.tensor([1, 2, 3]) # 整型向量 # 創(chuàng)建二維張量(矩陣) tensor2d = torch.tensor([[1, 2, 3], [4, 5, 6]]) # 2x3矩陣 tensor2d_float = torch.tensor([[1., 2.], [3., 4.]]) # 2x2浮點(diǎn)矩陣 # 創(chuàng)建三維張量 tensor3d = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) # 2x2x2張量
特殊張量創(chuàng)建
# 創(chuàng)建全零張量(常用于初始化) zeros = torch.zeros(3, 4) # 3行4列的全零矩陣 zeros_3d = torch.zeros(2, 3, 4) # 2x3x4的三維零張量 # 創(chuàng)建全一張量 ones = torch.ones(2, 3) # 2行3列的全一矩陣 ones_like = torch.ones_like(zeros) # 創(chuàng)建與zeros形狀相同的全一張量 # 創(chuàng)建隨機(jī)張量(常用于權(quán)重初始化) rand_tensor = torch.rand(5, 5) # 5x5的隨機(jī)矩陣,值在[0,1)之間均勻分布 randn_tensor = torch.randn(3, 3) # 3x3的正態(tài)分布隨機(jī)矩陣,均值0,方差1 # 創(chuàng)建單位矩陣(常用于線性變換初始化) eye_matrix = torch.eye(4) # 4x4的單位矩陣 eye_with_offset = torch.eye(3, 4, k=1) # 3x4的矩陣,對(duì)角線偏移1位 # 創(chuàng)建等差數(shù)列張量 arange_tensor = torch.arange(0, 10, 2) # [0, 2, 4, 6, 8] linspace_tensor = torch.linspace(0, 1, 5) # [0.0, 0.25, 0.5, 0.75, 1.0]
張量屬性
每個(gè)張量都有以下重要屬性,這些屬性決定了張量的行為和計(jì)算方式:
tensor = torch.rand(3, 4) # 數(shù)據(jù)類型 - 決定張量存儲(chǔ)的數(shù)值類型 print(tensor.dtype) # 如torch.float32、torch.int64等 # 常用類型:torch.float32, torch.float64, torch.int32, torch.int64 # 存儲(chǔ)設(shè)備 - 決定張量存儲(chǔ)在CPU還是GPU上 print(tensor.device) # 如'cpu'或'cuda:0' # 可以通過.to(device)方法在設(shè)備間移動(dòng)張量 # 形狀 - 描述張量的維度信息 print(tensor.shape) # 如torch.Size([3, 4]) print(tensor.size()) # 同shape的另一種訪問方式 print(tensor.ndim) # 張量的維度數(shù),這里是2 # 梯度計(jì)算標(biāo)志 - 決定張量是否需要計(jì)算梯度 print(tensor.requires_grad) # 默認(rèn)為False # 當(dāng)設(shè)置為True時(shí),PyTorch會(huì)跟蹤對(duì)此張量的所有操作以計(jì)算梯度 # 其他屬性 print(tensor.is_leaf) # 是否為葉節(jié)點(diǎn)(用戶直接創(chuàng)建的張量) print(tensor.is_cuda) # 是否存儲(chǔ)在GPU上 print(tensor.grad) # 存儲(chǔ)的梯度值(如果有)
張量操作
算術(shù)運(yùn)算
a = torch.tensor([1, 2, 3], dtype=torch.float32) b = torch.tensor([4, 5, 6], dtype=torch.float32) # 加法(逐元素相加) c = a + b # 直接運(yùn)算符 c = torch.add(a, b) # 函數(shù)形式 c = a.add(b) # 方法形式 # 原地加法(不創(chuàng)建新張量) a.add_(b) # 等價(jià)于 a += b # 乘法(逐元素相乘) d = a * b # [1*4, 2*5, 3*6] = [4, 10, 18] d = torch.mul(a, b) d = a.mul(b) # 除法(逐元素相除) e = a / b # [1/4, 2/5, 3/6] e = torch.div(a, b) # 矩陣乘法 mat_a = torch.rand(3, 4) # 3x4矩陣 mat_b = torch.rand(4, 5) # 4x5矩陣 mat_prod = torch.matmul(mat_a, mat_b) # 3x5結(jié)果矩陣 mat_prod = mat_a @ mat_b # Python 3.5+支持的運(yùn)算符 # 廣播機(jī)制示例 a = torch.rand(5, 1, 4) b = torch.rand( 1, 3) c = a + b # 廣播后形狀為(5,3,4)
索引和切片
PyTorch 張量的索引與 NumPy 類似,支持豐富的索引操作:
tensor = torch.arange(12).reshape(3, 4)
"""
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
"""
# 基本索引
print(tensor[0]) # 第一行: tensor([0, 1, 2, 3])
print(tensor[-1]) # 最后一行: tensor([ 8, 9, 10, 11])
print(tensor[:, 1]) # 第二列: tensor([1, 5, 9])
print(tensor[1:3, 2]) # 第二三行的第三列元素: tensor([6, 10])
# 高級(jí)索引
print(tensor[[0, 2], [1, 3]]) # 第0行第1列和第2行第3列: tensor([1, 11])
print(tensor[tensor > 5]) # 所有大于5的元素: tensor([6, 7, 8, 9, 10, 11])
# 修改子張量
tensor[1:, 2:] = 0 # 將第二行開始的右下2x2子矩陣置零
形狀操作
# 改變形狀(不改變數(shù)據(jù)) tensor = torch.rand(4, 6) reshaped = tensor.reshape(3, 8) # 總元素?cái)?shù)必須保持不變 viewed = tensor.view(2, 12) # 與reshape類似,但對(duì)內(nèi)存連續(xù)性有要求 # 轉(zhuǎn)置 transposed = tensor.t() # 僅適用于2D張量 permuted = tensor.permute(1, 0) # 通用轉(zhuǎn)置方法 # 增加/減少維度 tensor = torch.rand(3, 4) unsqueezed = tensor.unsqueeze(0) # 在0維增加1維,變?yōu)?x3x4 squeezed = unsqueezed.squeeze() # 去除所有長(zhǎng)度為1的維度 # 連接張量 a = torch.rand(2, 3) b = torch.rand(2, 3) cat_0 = torch.cat([a, b], dim=0) # 沿0維連接,結(jié)果為4x3 cat_1 = torch.cat([a, b], dim=1) # 沿1維連接,結(jié)果為2x6 # 分割張量 chunks = torch.chunk(tensor, 3, dim=0) # 沿0維分成3塊 splits = torch.split(tensor, 2, dim=1) # 沿1維每2列分一塊
張量與 NumPy 互轉(zhuǎn)
PyTorch 張量和 NumPy 數(shù)組可以高效互轉(zhuǎn),因?yàn)樗鼈児蚕淼讓觾?nèi)存(當(dāng)張量在CPU上時(shí)):
import numpy as np # 張量轉(zhuǎn) NumPy tensor = torch.ones(5) numpy_array = tensor.numpy() # 共享內(nèi)存,修改一個(gè)會(huì)影響另一個(gè) # 注意:GPU上的張量需要先移動(dòng)到CPU gpu_tensor = torch.rand(5, device='cuda') cpu_tensor = gpu_tensor.cpu() numpy_array = cpu_tensor.numpy() # NumPy 轉(zhuǎn)張量 np_array = np.array([1, 2, 3]) torch_tensor = torch.from_numpy(np_array) # 同樣共享內(nèi)存 # 不共享內(nèi)存的創(chuàng)建方式 torch_tensor_copy = torch.tensor(np_array) # 創(chuàng)建新副本
GPU 加速
PyTorch 張量的 GPU 加速功能可以顯著提升深度學(xué)習(xí)模型的訓(xùn)練速度:
# 檢查GPU是否可用
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f"Using device: {device}")
# 創(chuàng)建張量并移動(dòng)到GPU
tensor = torch.rand(10, 10).to(device)
# 直接在目標(biāo)設(shè)備上創(chuàng)建張量
gpu_tensor = torch.rand(5, 5, device='cuda')
# 在GPU上執(zhí)行運(yùn)算
result = tensor * 2 # 如果tensor在GPU上,result也會(huì)在GPU上
# 將結(jié)果移回CPU
cpu_result = result.cpu()
# 多GPU示例(需要多GPU環(huán)境)
if torch.cuda.device_count() > 1:
tensor = tensor.to('cuda:1') # 顯式指定第二個(gè)GPU
自動(dòng)微分
PyTorch 的自動(dòng)微分功能(autograd)是其核心特性之一,使得神經(jīng)網(wǎng)絡(luò)訓(xùn)練變得簡(jiǎn)單:
# 創(chuàng)建需要計(jì)算梯度的張量
x = torch.tensor(2.0, requires_grad=True)
w = torch.tensor(1.0, requires_grad=True)
b = torch.tensor(0.5, requires_grad=True)
# 構(gòu)建計(jì)算圖
y = w * x + b # 線性函數(shù)
z = y**2 # 非線性變換
# 反向傳播計(jì)算梯度
z.backward() # 計(jì)算dz/dx, dz/dw, dz/db
# 查看梯度
print(x.grad) # dz/dx = 2*(w*x+b)*w = 2*(1*2+0.5)*1 = 5.0
print(w.grad) # dz/dw = 2*(w*x+b)*x = 2*(1*2+0.5)*2 = 10.0
print(b.grad) # dz/db = 2*(w*x+b)*1 = 2*(1*2+0.5)*1 = 5.0
# 梯度清零(重要!在訓(xùn)練循環(huán)中需要)
x.grad.zero_()
w.grad.zero_()
b.grad.zero_()
# 禁用梯度跟蹤(用于推理階段)
with torch.no_grad():
y = w * x + b # 不會(huì)在計(jì)算圖中記錄
高級(jí)特性
內(nèi)存共享
# 視圖操作共享內(nèi)存 a = torch.rand(4, 5) b = a.view(20) # b與a共享內(nèi)存 c = a[1:3, 2:4] # c與a共享內(nèi)存 # clone()創(chuàng)建獨(dú)立副本 d = a.clone() # d與a不共享內(nèi)存
稀疏張量
# 創(chuàng)建稀疏張量 indices = torch.tensor([[0, 1, 2], [2, 0, 1]]) # 非零元素的坐標(biāo) values = torch.tensor([3, 4, 5], dtype=torch.float32) # 非零元素的值 shape = torch.Size([3, 3]) # 稀疏張量的形狀 sparse_tensor = torch.sparse_coo_tensor(indices, values, shape) print(sparse_tensor.to_dense()) # 轉(zhuǎn)換為稠密張量
分布式張量
# 分布式訓(xùn)練中的張量分片
import torch.distributed as dist
if dist.is_initialized():
# 將張量分片到不同進(jìn)程
tensor = torch.rand(10, 10)
shard = tensor.chunk(dist.get_world_size(), dim=0)[dist.get_rank()]

PyTorch 張量(Tensor)是深度學(xué)習(xí)模型構(gòu)建的核心數(shù)據(jù)結(jié)構(gòu),它本質(zhì)上是一個(gè)多維數(shù)組,類似于 NumPy 的 ndarray,但具有 GPU 加速計(jì)算和自動(dòng)微分等額外功能。理解張量的特性和操作對(duì)于高效使用 PyTorch 至關(guān)重要。
張量的基本特性
- 數(shù)據(jù)類型(dtype):PyTorch 張量支持多種數(shù)據(jù)類型,如 torch.float32、torch.int64 等
- 形狀(shape):表示張量的維度結(jié)構(gòu),例如 (3, 224, 224) 表示一個(gè) 3 通道的 224x224 圖像
- 設(shè)備(device):可以存儲(chǔ)在 CPU 或 GPU 上,通過
.to('cuda')方法可以輕松切換
張量的創(chuàng)建方法
PyTorch 提供了多種創(chuàng)建張量的方式:
- 從 Python 列表創(chuàng)建:
torch.tensor([[1, 2], [3, 4]]) - 特殊張量創(chuàng)建:
- 零張量:
torch.zeros(2, 3) - 單位矩陣:
torch.eye(3) - 隨機(jī)張量:
torch.randn(2, 2)
- 零張量:
- 從 NumPy 數(shù)組轉(zhuǎn)換:
torch.from_numpy(np_array)
張量的操作
PyTorch 支持豐富的張量操作:
- 數(shù)學(xué)運(yùn)算:加減乘除、矩陣乘法(
@或torch.matmul()) - 形狀操作:
- 改變形狀:
view()或reshape() - 轉(zhuǎn)置:
t()或transpose()
- 改變形狀:
- 索引和切片:與 NumPy 類似的索引方式
- 歸約操作:
sum(),mean(),max()等
設(shè)備管理
PyTorch 允許張量在 CPU 和 GPU 之間輕松切換:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
x = x.to(device) # 將張量移動(dòng)到指定設(shè)備
自動(dòng)微分
PyTorch 的核心特性之一是自動(dòng)微分(autograd):
x = torch.tensor(2.0, requires_grad=True) y = x**2 y.backward() # 自動(dòng)計(jì)算梯度 print(x.grad) # 輸出梯度值 4.0
實(shí)際應(yīng)用場(chǎng)景
- 圖像處理領(lǐng)域
- 格式轉(zhuǎn)換:將BGR/RGB格式的原始圖像(H, W, C)轉(zhuǎn)換為PyTorch標(biāo)準(zhǔn)格式(C, H, W)張量
- 示例:處理224x224的RGB圖像時(shí),轉(zhuǎn)換后得到(3, 224, 224)形狀的張量
- 預(yù)處理流水線:可結(jié)合torchvision.transforms模塊實(shí)現(xiàn)
- 標(biāo)準(zhǔn)化操作:使用Normalize將像素值從[0,255]轉(zhuǎn)換到[0,1]范圍
- 數(shù)據(jù)增強(qiáng):隨機(jī)裁剪、水平翻轉(zhuǎn)等操作都通過張量運(yùn)算實(shí)現(xiàn)
- 自然語言處理領(lǐng)域
- 文本向量化:通過詞嵌入層將單詞轉(zhuǎn)換為固定維度的詞向量
- 典型流程:文本分詞→構(gòu)建詞匯表→創(chuàng)建詞向量矩陣
- 示例:使用300維GloVe詞向量時(shí),每個(gè)單詞表示為(300,)的張量
- 序列處理:使用pack_padded_sequence處理變長(zhǎng)文本序列
- 有效處理批量中不同長(zhǎng)度的文本序列
- 模型訓(xùn)練過程
- 批量處理:將數(shù)據(jù)組織為(N, C, H, W)或(N, L, D)形式的批量張量
- N為批量大小,L為序列長(zhǎng)度,D為特征維度
- 自動(dòng)微分:通過backward()自動(dòng)計(jì)算梯度
- 示例:損失函數(shù)的梯度自動(dòng)傳播到各層參數(shù)
- GPU加速:使用.to('cuda')將張量轉(zhuǎn)移到GPU
- 典型加速比:相比CPU可實(shí)現(xiàn)5-50倍的訓(xùn)練速度提升
- 優(yōu)化技巧
- 內(nèi)存優(yōu)化:使用torch.no_grad()減少驗(yàn)證時(shí)的內(nèi)存占用
- 計(jì)算優(yōu)化:利用torch.jit對(duì)模型進(jìn)行編譯優(yōu)化
- 并行計(jì)算:通過DataParallel實(shí)現(xiàn)多GPU訓(xùn)練
通過這些張量操作和優(yōu)化技術(shù),開發(fā)者可以:
- 構(gòu)建端到端的深度學(xué)習(xí)流水線
- 實(shí)現(xiàn)高效的模型訓(xùn)練和推理
- 充分利用現(xiàn)代GPU的計(jì)算能力
- 快速迭代模型結(jié)構(gòu)和超參數(shù)
- 部署高性能的深度學(xué)習(xí)應(yīng)用
到此這篇關(guān)于PyTorch 張量的基本操作的文章就介紹到這了,更多相關(guān)PyTorch 張量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入理解NumPy 的 np.column_stack的實(shí)現(xiàn)
本文主要介紹了NumPy 的 np.column_stack的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2026-01-01
在Python中使用M2Crypto模塊實(shí)現(xiàn)AES加密的教程
這篇文章主要介紹了在Python中使用M2Crypto模塊實(shí)現(xiàn)AES加密的教程,例子中的方法使用aes_128_ecb算法,需要的朋友可以參考下2015-04-04
django項(xiàng)目中使用云片網(wǎng)發(fā)送短信驗(yàn)證碼的實(shí)現(xiàn)
這篇文章主要介紹了django項(xiàng)目中使用云片網(wǎng)發(fā)送短信驗(yàn)證碼的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Pandas數(shù)據(jù)合并的始終高效技巧與常見問題
在數(shù)據(jù)分析工作中,我們經(jīng)常需要處理來自多個(gè)來源的數(shù)據(jù)集,當(dāng)合并來自20個(gè)不同地區(qū)的銷售數(shù)據(jù)時(shí),可能會(huì)發(fā)現(xiàn)部分列意外丟失,如果您曾經(jīng)因數(shù)據(jù)合并問題而感到困擾,本文將為您提供系統(tǒng)的解決方案,需要的朋友可以參考下2025-05-05
Python區(qū)塊鏈范圍結(jié)論及Genesis Block的添加教程
這篇文章主要為大家介紹了Python區(qū)塊鏈范圍結(jié)論及Genesis Block的添加,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
使用python實(shí)現(xiàn)簡(jiǎn)單去水印功能
這篇文章主要為大家詳細(xì)介紹了使用python實(shí)現(xiàn)簡(jiǎn)單去水印功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Python語法糖for?else循環(huán)語句里的break使用詳解
這篇文章主要介紹了Python語法糖之for?else循環(huán)語句里的break使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05

