目錄
- 1、Troch
1、Troch
函數 | 說明 | 舉例 |
---|---|---|
torch.tensor() torch.arange() | 創建張量 | 創建一個標量:torch.tensor(42) 創建一個一維張量:torch.tensor([1, 2, 3]) 創建一個二維張量:torch.tensor([[1, 2], [3, 4]]) 生成一維等差張量:語法:torch.arange(start=0, end, step=1, *, dtype=None, device=None, requires_grad=False) torch.arange(3)就是tensor([0, 1, 2]) |
torch.view() | 改變張量的形狀 | 1行8列改2行4列:torch.arange(1, 9).view(2, 4) |
torch.cat() | 指定維度拼接張量 | torch.cat((torch.tensor([[1, 2], [3, 4]]), torch.tensor([[5, 6]])), dim=0) # tensor([[1, 2], [3, 4], [5, 6]]) |
索引與切片 | 和numpy數組用法一致 | |
tensor.t() | 張量轉置 | torch.tensor([[1, 2, 3], [4, 5, 6]]).t() tensor([[1, 4], [2, 5], [3, 6]]) |
torch.mm() | 矩陣乘法 | torch.mm(torch.tensor([[1, 2], [3, 4]]), torch.tensor([[5, 6], [7, 8]])) # tensor([[19, 22], [43, 50]]) |
torch.mul() | 元素級乘法 | torch.mul(torch.tensor([[1, 2], [3, 4]]), torch.tensor([[5, 6], [7, 8]])) # tensor([[ 5, 12], [21, 32]]) |
torch.sum() | 求和 | torch.sum(torch.tensor([[1, 2], [3, 4]])) # tensor(10) |
torch.mean() | 求均值 | torch.mean(torch.tensor([[1.0, 2.0], [3.0, 4.0]]))) # tensor(2.5000) |
torch.std() | 求標準差 | torch.std(torch.tensor([[1.0, 2.0], [3.0, 4.0]]))) # tensor(2.2910) 即:((1-2)**2 + (2-2)**2 + (3-2)**2 + (4-2)**2)**0.5 |
torch.max() torch.min() | 求最大值、最小值及其索引 | 見下面代碼(后面都見下面代碼,不寫了) |
torch.abs() | 絕對值 | |
torch.exp() | 指數運算,torch.exp(x)就是e^x | |
torch.log() | 對數運算,toch.log(2)就是ln2≈0.6931 | |
torch.floor() torch.ceil() | 向下取整floor 向上取整ceil | |
nn.Linear(x, y) | 定義一個線性層,x行y列,總共x*y個weight神經元,y個bias神經元 | |
optimizer.zero_grad() | 梯度清零,清空優化器跟蹤的參數的梯度(即 model.parameters() 中注冊的參數) | |
layer.weight.grad layer.bias.grad | 保存該層的 權重weight梯度信息 和 偏置bias梯度信息 | |
model.named_parameters() | 通過迭代器 獲取模型的所有參數(而不是某一層)及其梯度 [(n, p.grad) for n, p in model.named_parameters()] | |
torch.nn.utils.clip_grad_norm_() | 梯度裁剪,用于防止梯度爆炸的技術,通過對模型的梯度進行裁剪。 |
import torch, math
import torch.nn as nn
import torch.optim as optim# torch.tensor()
print(torch.tensor(42)) # 創建一個標量(零維張量),tensor(42)
print(torch.tensor([1,2,3])) # 創建一個一維張量,tensor([1, 2, 3])
print(torch.tensor([[1,2],[3,4]])) # 創建一個二維張量,tensor([[1, 2], [3, 4]])# torch.arange(),一維等差張量
print(torch.arange(1,5)) # tensor([2, 3, 4])
print(torch.arange(3)) # tensor([0, 1, 2])# tensor1.view() 改變形狀
tensor1 = torch.arange(1, 9) # tensor1 = tensor([1, 2, 3, 4, 5, 6, 7, 8])
print(tensor1.view(2, 4)) # 或者 tensor1.view(-1, 4)、tensor1.view(2, -1):tensor([[1, 2, 3, 4], [5, 6, 7, 8]])# torch.cat() 拼接
print(torch.cat((torch.tensor([[1, 2], [3, 4]]), torch.tensor([[5, 6]])), dim=0))
# 上面就是按照第0個維度拼接(就是第1維度不變,例如[1,2]拼接前后一致)tensor([[1, 2], [3, 4], [5, 6]])# 索引和切片
tensor1 = torch.tensor([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]])
print(tensor1[0, :]) # 獲取第一行:tensor([1, 2, 3, 4, 5, 6])
print(tensor1[0, 0:3]) # 獲取第一行從索引0開始,到索引3(不包括3)的元素:tensor([1, 2, 3])
print(tensor1[0, 0:3:2]) # 獲取第一行,且從索引0開始,到索引3(不包括3),步長為2的元素:tensor([1, 3])
print(tensor1[:, 0]) # 獲取第一列:tensor([1, 7])
print(tensor1[1:, 1:]) # 獲取子集:tensor([[ 8, 9, 10, 11, 12]])# torch.t() 轉置
print(torch.tensor([[1, 2, 3], [4, 5, 6]]).t()) # tensor([[1, 4], [2, 5], [3, 6]])# torch.mm() 矩陣乘法
print(torch.mm(torch.tensor([[1, 2], [3, 4]]), torch.tensor([[5, 6], [7, 8]]))) # tensor([[19, 22], [43, 50]])# torch.mul() 元素級乘法
print(torch.mul(torch.tensor([[1, 2], [3, 4]]), torch.tensor([[5, 6], [7, 8]]))) # tensor([[ 5, 12], [21, 32]])# torch.sum() 求和
print(torch.sum(torch.tensor([[1, 2], [3, 4]]))) # tensor(10)# torch.mean() 求均值
print(torch.mean(torch.tensor([[1.0, 2.0], [3.0, 4.0]]))) # tensor(2.5000)# torch.std() 求標準差
print(torch.std(torch.tensor([[1.0, 2.0], [3.0, 4.0]]))) # tensor(2.2910) 即:((1-2)**2 + (2-2)**2 + (3-2)**2 + (4-2)**2)**0.5# torch.max()、torch.min() 求最大值、最小值及其索引
print(torch.max(torch.tensor([[1.0, 2.0], [3.0, 4.0]]))) # tensor(4.)
print(torch.max(torch.tensor([[1.0, 2.0], [3.0, 4.0]]), dim=1)) # torch.return_types.max( values=tensor([2., 4.]), indices=tensor([1, 1]))
print(torch.min(torch.tensor([[1.0, 2.0], [3.0, 4.0]]))) # tensor(1.)# torch.abs() 絕對值
print(torch.abs(torch.tensor([[-1, 2], [-3, 4]]))) # tensor([[1, 2], [3, 4]])# torch.exp() 指數運算,torch.exp(x)就是e^x
print(torch.exp(torch.tensor([[1.0, 2.0], [3.0, 4.0]]))) # tensor([[ 2.7183, 7.3891], [20.0855, 54.5981]])# torch.log() 對數運算,就是 ln2≈0.6931
print(torch.log(torch.tensor([[1.0, 2.0], [3.0, 4.0]]))) # tensor([[0.0000, 0.6931], [1.0986, 1.3863]])# torch.floor()、torch.ceil() 向下取整floor、向上取整ceil
print(torch.floor(torch.tensor([[1.2, 2.8], [3.5, 4.1]]))) # tensor([[1., 2.], [3., 4.]])
print(torch.ceil(torch.tensor([[1.2, 2.8], [3.5, 4.1]]))) # tensor([[2., 3.], [4., 5.]])# nn.Linear(x, y) 定義一個線性層,x行y列,總共x*y個weight神經元,y個bias神經元
layer1 = nn.Linear(3, 1) # 定義一個線性層
print(f"layer1\t權重 W:{layer1.weight.shape}\t偏置 b:{layer1.bias.shape}") # 查看權重和偏置:layer1 權重 W:torch.Size([1, 3]) 偏置 b:torch.Size([1])
layer2 = nn.Linear(3, 2) # 定義一個線性層
print(f"layer2\t權重 W:{layer2.weight.shape}\t偏置 b:{layer2.bias.shape}") # 查看權重和偏置:layer2 權重 W:torch.Size([2, 3]) 偏置 b:torch.Size([2])# 損失函數 可以調用類形式的損失函數(torch.nn)和函數形式的損失函數(torch.nn.functional)
# torch.nn:需要實例化對象,可以初始化時固定參數
# torch.nn.funcional:直接調用函數,每次調用顯式傳遞所有參數
criterion = nn.CrossEntropyLoss(reduction="mean") # 初始化時固定參數
outputs = torch.randn(3, 5) # 模型輸出(3個樣本,5個類別)
labels = torch.tensor([2, 0, 4]) # 真實標簽
loss1 = criterion(outputs, labels) # 直接調用
import torch.nn.functional as F
loss2 = F.cross_entropy(outputs,labels,reduction="mean" # 每次調用需顯式傳遞參數
)# 優化器 torch.optim模塊提供多種優化函數,例如隨機梯度下降(SGD)、Adam
# optimizer.zero_grad() 梯度清零,清空優化器跟蹤的參數的梯度(即 model.parameters() 中注冊的參數)
# layer.weight.grad、layer.bias.grad 保存該層的 權重weight梯度信息 和 偏置bias梯度信息
# model.named_parameters() 通過迭代器 獲取模型的所有參數(而不是某一層)及其梯度 [(n, p.grad) for n, p in model.named_parameters()]
torch.manual_seed(77) # 設置隨機種子,77可以改為其他數字
model = nn.Linear(3, 1) # 定義模型:簡單線性層,就是3行1列 個神經元
optimizer = optim.SGD(model.parameters(), lr=0.01) # 定義優化器:隨機梯度下降優化器
inputs = torch.randn(10, 3) # 模擬輸入數據和標簽:batch_size批量大小10,特征維度3(就是3行10列的張量,10個樣品,每個樣品)
labels = torch.randn(10, 1) # 對應標簽
for epoch in range(2): # 訓練循環optimizer.zero_grad() # 1. 梯度清零outputs = model(inputs) # 2. 前向傳播計算損失loss = nn.MSELoss()(outputs, labels)print(f"計算epoch={epoch}的loss前:weight:{model.weight.grad}\tbias:{model.bias.grad}")loss.backward() # 3. 反向傳播計算梯度print(f"計算epoch={epoch}的loss后:weight:{model.weight.grad}\tbias:{model.bias.grad}")optimizer.step() # 4. 優化器更新參數
# 計算epoch=0的loss前:weight:None bias:None
# 計算epoch=0的loss后:weight:tensor([[-1.2573, -0.0045, -0.6926]]) bias:tensor([0.2520])
# 計算epoch=1的loss前:weight:tensor([[0., 0., 0.]]) bias:tensor([0.])
# 計算epoch=1的loss后:weight:tensor([[-1.2206, -0.0055, -0.6704]]) bias:tensor([0.2330])
# 如果注釋掉optimizer.zero_grad(),可以對比bias變化,下面的 0.4849≈0.2520+0.2330
# 計算epoch=0的loss前:weight:None bias:None
# 計算epoch=0的loss后:weight:tensor([[-1.2573, -0.0045, -0.6926]]) bias:tensor([0.2520])
# 計算epoch=1的loss前:weight:tensor([[-1.2573, -0.0045, -0.6926]]) bias:tensor([0.2520])
# 計算epoch=1的loss后:weight:tensor([[-2.4779, -0.0100, -1.3630]]) bias:tensor([0.4849])# torch.nn.utils.clip_grad_norm_() 梯度裁剪
torch.manual_seed(77) # 設置隨機種子,77可以改為其他數字
model = nn.Linear(3, 1)
optimizer = optim.SGD(model.parameters(), lr=0.01)
input_data = torch.randn(10, 3)
output = model(input_data) # 前向傳播
loss = torch.nn.functional.mse_loss(output, torch.randn(10, 1))
loss.backward() # 反向傳播
print(f"裁剪前梯度:weight.grad={model.weight.grad}\tbias.grad={model.bias.grad}")
grads = torch.cat([p.grad.flatten() for p in model.parameters()]) # grads = tensor([-1.2573, -0.0045, -0.6926, 0.2520])
weightGrad, biasGrad = model.weight.grad*1/torch.norm(grads), model.bias.grad*1/torch.norm(grads)
print(f"手動計算裁剪后梯度:weight.grad={weightGrad}\tbias.grad={biasGrad}")
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) # 梯度裁剪
print(f"裁剪后梯度:{model.weight.grad}\tbias.grad={model.bias.grad}")
optimizer.step()
# 打印:
# 裁剪前梯度:weight.grad=tensor([[-1.2573, -0.0045, -0.6926]]) bias.grad=tensor([0.2520])
# 手動計算裁剪后梯度:weight.grad=tensor([[-0.8627, -0.0031, -0.4752]]) bias.grad=tensor([0.1729])
# 裁剪后梯度:tensor([[-0.8627, -0.0031, -0.4752]]) bias.grad=tensor([0.1729])
# 可見:-0.8627 = -1.2573 * 1 / math.sqrt((1.2573*1.2573 + 0.0045*0.0045 + 0.6926*0.6926 + 0.2520*0.2520))# DataLoader\Dataset torch.utils.data提供了用于加載和處理數據的工具
# 例如:DataLoader(my_dataset, batch_size=2, shuffle=True):
# 創建一個數據加載器,my_dataset 必須繼承自torch.utils.data.Dataset的自定義數據集對象
# 需要實現__len__()(返回數據集大小)和__getitem__()(根據索引返回樣本和標簽)方法。
# batch_size=2:每個批次包含2個樣本。例如,若數據集有1000個樣本,則會生成500個批次(每個批次2個樣本)。
# shuffle=True:在每個epoch開始時打亂數據順序(默認shuffle=False)。提升泛化能力
from torch.utils.data import DataLoader, Dataset
class CustomDataset(Dataset): # 自定義數據集類def __init__(self, data):self.data = datadef __len__(self):return len(self.data)def __getitem__(self, index):return self.data[index]
my_dataset = CustomDataset([1, 2, 3, 4, 5]) # 創建自定義數據集實例
data_loader = DataLoader(my_dataset, batch_size=2, shuffle=True) # 創建數據加載器
for batch in data_loader: # 迭代數據加載器print("Batch:", batch)
# 打印
# Batch: tensor([2, 3])
# Batch: tensor([4, 5])
# Batch: tensor([1])# 學習率調度 .optim.lr_scheduler 模塊提供了多種學習率調度器,例如學習率衰減等
from torch.optim.lr_scheduler import StepLR
torch.manual_seed(77) # 設置隨機種子,77可以改為其他數字
model = nn.Linear(3, 1) # 定義模型:簡單線性層,就是3行1列 個神經元
optimizer = optim.SGD(model.parameters(), lr=0.01) # 定義優化器:隨機梯度下降優化器
scheduler = StepLR(optimizer, step_size=5, gamma=0.1) # 按照固定周期調整優化器的學習率:每隔 5 個epoch調整一次學習率,每次將學習率縮小10倍(乘0.1)
inputs = torch.randn(10, 3) # 模擬輸入數據和標簽:batch_size批量大小10,特征維度3(就是3行10列的張量,10個樣品,每個樣品)
labels = torch.randn(10, 1) # 對應標簽
for epoch in range(20): # 訓練循環optimizer.zero_grad() # 1. 梯度清零outputs = model(inputs) # 2. 前向傳播計算損失loss = nn.MSELoss()(outputs, labels)print(f"計算epoch={epoch}的loss前:weight:{model.weight.grad}\tbias:{model.bias.grad}")loss.backward() # 3. 反向傳播計算梯度print(f"計算epoch={epoch}的loss后:weight:{model.weight.grad}\tbias:{model.bias.grad}")optimizer.step() # 4. 優化器更新參數scheduler.step() # 5、更新學習率