Pytorch 核心操作全總結(jié)!零基礎(chǔ)必備!
在深度學(xué)習(xí)與人工智能領(lǐng)域,PyTorch已成為研究者與開發(fā)者手中的利劍,以其靈活高效的特性,不斷推動著新技術(shù)的邊界。對于每一位致力于掌握PyTorch精髓的學(xué)習(xí)者來說,深入了解其核心操作不僅是提升技能的關(guān)鍵,也是邁向高級應(yīng)用與創(chuàng)新研究的必經(jīng)之路。本文精心梳理了PyTorch的核心操作,這不僅是一份全面的技術(shù)指南,更是每一個PyTorch實踐者的智慧錦囊,建議收藏!
一、張量創(chuàng)建和基本操作
1. 張量創(chuàng)建
(1) 從Python列表或Numpy數(shù)組創(chuàng)建張量
使用torch.tensor()函數(shù)可以直接從Python列表創(chuàng)建張量。并且,PyTorch設(shè)計時考慮了與NumPy的互操作性,也可以使用torch.tensor()函數(shù)從NumPy數(shù)組創(chuàng)建張量。
import numpy as np
import torch
# 從列表創(chuàng)建張量
list_data = [1, 2, 3, 4]
tensor_from_list = torch.tensor(list_data)
print(tensor_from_list) # tensor([1, 2, 3, 4])
# 從NumPy數(shù)組創(chuàng)建張量
np_array = np.array([1, 2, 3])
tensor_from_np_tensor = torch.tensor(np_array)
print(tensor_from_np_tensor) # tensor([1, 2, 3], dtype=torch.int32)
(2) 使用固定數(shù)值創(chuàng)建張量
torch.zeros(shape)和torch.ones(shape):創(chuàng)建指定形狀的全零或全一張量。
'''
tensor([[0., 0., 0.],
[0., 0., 0.]])
'''
zeros_tensor = torch.zeros(2, 3)
'''
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
'''
ones_tensor = torch.ones(3, 4)
torch.rand(shape):創(chuàng)建指定形狀的隨機(jī)浮點數(shù)張量(0到1之間)或標(biāo)準(zhǔn)正態(tài)分布的張量。
'''
tensor([[0.7632, 0.9953, 0.8954],
[0.8681, 0.7707, 0.8806]])
'''
random_tensor = torch.rand(2, 3)
'''
tensor([[ 0.1873, -1.6907, 0.4717, 1.0271],
[-1.0680, 0.7490, -0.5693, 0.6490],
[ 0.0429, -1.5796, -2.3312, -0.2733]])
'''
normal_tensor = torch.randn(3, 4)
torch.arange(start, end=None, step=1, dtype=None, layout=torch.strided, device=None, requires_grad=False):創(chuàng)建一個等差序列張量,默認(rèn)step為1。
arange_tensor = torch.arange(1, 10) #tensor([1, 2, 3, 4, 5, 6, 7, 8, 9])
2. 張量的基本操作
(1) 張量索引和切片
張量的索引和切片類似于Python列表,可以訪問和修改張量的特定元素或子集。
# 創(chuàng)建一個張量
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
# 索引單個元素
element = tensor[0, 0] # 1
# 切片
slice_1 = tensor[0, :] # [1, 2, 3]
slice_2 = tensor[:, 1] # [2, 5]
# 修改元素
tensor[0, 0] = 7
print(tensor) # [[7, 2, 3], [4, 5, 6]]
(2) 形狀操作
- shape屬性獲取張量的形狀:
shape = tensor.shape # torch.Size([2, 3])
- unsqueeze(dim)在指定維度添加一個大小為1的新維度:
expanded_tensor = tensor.unsqueeze(0) # 添加一個新維度,形狀變?yōu)閇1, 2, 3]
- reshape(shape)或view(shape)改變張量的形狀:
reshaped_tensor = tensor.reshape(6) # 變?yōu)樾螤顬閇6]的一維張量
- transpose(dim0, dim1)交換指定的兩個維度:
transposed_tensor = tensor.transpose(0, 1) # 交換第一和第二維度
(3) 數(shù)學(xué)運算
PyTorch張量支持廣泛的數(shù)學(xué)運算,包括基本的算術(shù)運算、元素級運算、矩陣運算等。以tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])為例。
- 基本運算(適用于標(biāo)量、一維或多維張量):
addition = tensor + tensor # [[2, 4, 6], [8, 10, 12]]。
subtraction = tensor - tensor #[[0, 0, 0], [0, 0, 0]]
multiplication = tensor * tensor #[[1, 4, 9], [16, 25, 36]]
division = tensor / tensor #[[1, 1, 1], [1, 1, 1]]
- 元素級運算(*運算符在這種情況下表示逐元素乘法,而不是矩陣乘法):
elementwise_product = tensor * tensor # [[1, 4, 9], [16, 25, 36]]
- 矩陣運算(使用@運算符或torch.matmul()):
matrix_product = tensor @ tensor.t() # 或者 torch.matmul(tensor, tensor.t())
# tensor @ tensor.t() 結(jié)果是一個標(biāo)量,因為張量是方陣,且張量與其轉(zhuǎn)置的點積等于1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
- 廣播機(jī)制(使得不同形狀的張量能夠進(jìn)行運算):
'''
結(jié)果是一個2x3的張量,其中每個元素都是tensor對應(yīng)位置的元素加上1
broadcasted_addition = [[2, 3, 4], [5, 6, 7]]
'''
broadcasted_addition = tensor + torch.tensor([1, 1, 1])
- 比較運算(返回布爾張量):
# 返回一個2x3的布爾張量,所有元素都為False,因為每個元素都不大于自身。
greater_than = tensor > tensor
- 聚合運算(如求和、平均、最大值、最小值等):
sum = torch.sum(tensor) # 返回張量所有元素的總和,即1+2+3+4+5+6=21。
mean = torch.mean(tensor) #返回張量的平均值,即21/6=3.5。
# 返回最大值張量[4, 5, 6]和最大值的索引[1, 1, 1],因為第二行的所有元素都是最大值。
max_value, max_index = torch.max(tensor, dim=0) # 按列求最大值和對應(yīng)索引
二、自動求導(dǎo)
在深度學(xué)習(xí)中,自動求導(dǎo)(automatic differentiation)是關(guān)鍵步驟,用于計算損失函數(shù)對模型參數(shù)的梯度。PyTorch提供了自動求導(dǎo)機(jī)制,可以輕松地定義和計算復(fù)雜的神經(jīng)網(wǎng)絡(luò)。
1. 張量的requires_grad屬性
在PyTorch中,requires_grad屬性用于決定張量是否應(yīng)該在計算過程中跟蹤其操作,以便進(jìn)行自動求導(dǎo)。如果計算張量的梯度,就需要設(shè)置requires_grad=True。
import torch
# 創(chuàng)建一個張量并設(shè)置requires_grad=True
x = torch.tensor([1.0, 2.0], requires_grad=True)
# Original tensor: tensor([1., 2.], requires_grad=True)
print("Original tensor:", x)
2. 張量操作與計算圖
在PyTorch中,張量操作與計算圖緊密相關(guān),因為計算圖是實現(xiàn)自動求導(dǎo)(autograd)的關(guān)鍵。當(dāng)一個張量的requires_grad屬性被設(shè)置為True時,PyTorch會記錄對該張量的所有操作,形成一個計算圖。這個圖描述了從輸入張量到輸出張量的計算路徑,每個節(jié)點代表一個張量,邊代表操作。
import torch
# 創(chuàng)建一個需要梯度的張量
x = torch.tensor([1.0, 2.0], requires_grad=True)
# 張量操作
y = x + 2 # 加法操作
z = y * y * 3 # 乘法操作
out = z.mean() # 平均值操作
此時,計算圖已經(jīng)隱含地構(gòu)建完成,記錄了從x到out的所有操作。其中,x是計算圖的起點,out是終點。
3. 計算梯度
要計算梯度,只需對計算圖的最終輸出調(diào)用.backward()方法。
# 計算梯度
out.backward()
# 現(xiàn)在,x的梯度已經(jīng)計算出來了,可以通過x.grad屬性獲取
print("Gradient of x with respect to the output:", x.grad)
out.backward()會沿著計算圖反向傳播,計算所有涉及張量的梯度。在本例中,x.grad將會給出x相對于out的梯度,即out關(guān)于x的偏導(dǎo)數(shù)。這在訓(xùn)練神經(jīng)網(wǎng)絡(luò)時非常有用,因為可以用來更新網(wǎng)絡(luò)的權(quán)重。
4. 阻止梯度追蹤
在某些場景下,比如驗證模型或計算某些不需要更新參數(shù)的中間結(jié)果時,阻止梯度追蹤可以減少內(nèi)存消耗和提高效率。使用.detach()或torch.no_grad()是實現(xiàn)這一目的的有效手段。
- 使用.detach()方法: 返回一個與原始張量數(shù)值相同的新張量,但不跟蹤梯度。
new_tensor = original_tensor.detach()
- 使用torch.no_grad()上下文管理器。
with torch.no_grad():
# 在此區(qū)域內(nèi)進(jìn)行的操作不會追蹤梯度
intermediate_result = some_operation(original_tensor)
5. 控制梯度計算的上下文管理器
torch.autograd.set_grad_enabled(True|False) 是另一個強(qiáng)大的工具,用于全局控制是否在代碼的特定部分進(jìn)行梯度計算。相比.detach()和torch.no_grad(),它提供了更多的靈活性,因為它允許在代碼的不同部分動態(tài)開啟或關(guān)閉梯度追蹤,這對于復(fù)雜的模型調(diào)試、性能優(yōu)化或混合精度訓(xùn)練等場景特別有用。
import torch
# 默認(rèn)情況下,梯度追蹤是開啟的
print(f"當(dāng)前梯度追蹤狀態(tài): {torch.is_grad_enabled()}") # 輸出: True
# 使用set_grad_enabled(False)關(guān)閉梯度追蹤
with torch.autograd.set_grad_enabled(False):
x = torch.tensor([1.0, 2.0], requires_grad=True)
y = x * 2
print(f"在上下文中,梯度追蹤狀態(tài): {torch.is_grad_enabled()}") # 輸出: False
print(f"y的requires_grad屬性: {y.requires_grad}") # 輸出: False
# 離開上下文后,梯度追蹤狀態(tài)恢復(fù)到之前的狀態(tài)
print(f"離開上下文后,梯度追蹤狀態(tài): {torch.is_grad_enabled()}") # 輸出: True
# 這里x的梯度追蹤仍然是開啟的,除非在其他地方被改變
6. 優(yōu)化器與自動求導(dǎo)結(jié)合
在訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型時,通常會使用優(yōu)化器(optimizer)來更新模型的參數(shù)。優(yōu)化器利用自動求導(dǎo)計算出的梯度來調(diào)整參數(shù),以最小化損失函數(shù)。以下是一個使用隨機(jī)梯度下降(SGD)優(yōu)化器的簡單示例:
import torch
from torch import nn, optim
# 定義一個簡單的線性模型
model = nn.Linear(2, 1) # 輸入2個特征,輸出1個值
# 假設(shè)有一些輸入數(shù)據(jù)和標(biāo)簽
inputs = torch.randn(10, 2) # 10個樣本,每個樣本2個特征
labels = torch.randn(10, 1) # 10個樣本,每個樣本1個標(biāo)簽
# 創(chuàng)建優(yōu)化器,指定要更新的模型參數(shù)
optimizer = optim.SGD(model.parameters(), lr=0.01) # 學(xué)習(xí)率為0.01
# 前向傳播
outputs = model(inputs)
# 損失函數(shù)
loss = nn.MSELoss()(outputs, labels)
# 反向傳播并計算梯度
loss.backward()
# 使用優(yōu)化器更新參數(shù)
optimizer.step()
# 清除梯度(防止梯度累積)
optimizer.zero_grad()
三、神經(jīng)網(wǎng)絡(luò)層
在PyTorch中,nn.Module是構(gòu)建神經(jīng)網(wǎng)絡(luò)模型的核心類,它提供了一個模塊化的框架,可以方便地組合各種層和操作。
1. 創(chuàng)建自定義神經(jīng)網(wǎng)絡(luò)層
創(chuàng)建自定義神經(jīng)網(wǎng)絡(luò)層是PyTorch中常見的做法。以下是如何創(chuàng)建一個名為CustomLayer的自定義層,它包含一個線性層和一個激活函數(shù)(例如ReLU):
import torch
import torch.nn as nn
class CustomLayer(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(CustomLayer, self).__init__()
# 創(chuàng)建線性層
self.linear = nn.Linear(input_size, hidden_size)
# 創(chuàng)建ReLU激活函數(shù)
self.relu = nn.ReLU()
# 創(chuàng)建輸出線性層(如果需要的話,例如對于分類任務(wù))
self.output_linear = nn.Linear(hidden_size, output_size)
def forward(self, x):
# 應(yīng)用線性變換
x = self.linear(x)
# 應(yīng)用ReLU激活函數(shù)
x = self.relu(x)
# 如果需要,可以添加更多的操作,例如另一個線性層
x = self.output_linear(x)
return x
其中,CustomLayer類繼承自nn.Module,并在__init__方法中定義了兩個線性層(一個輸入層和一個輸出層)以及一個ReLU激活函數(shù)。forward方法描述了輸入到輸出的計算流程:首先,輸入通過線性層,然后通過ReLU激活,最后通過輸出線性層。如果只需要一個線性變換和激活,可以去掉output_linear。
使用這個自定義層,可以像使用內(nèi)置層一樣在模型中實例化和使用它:
input_size = 10
hidden_size = 20
output_size = 5
model = CustomLayer(input_size, hidden_size, output_size)
2. 構(gòu)建復(fù)雜的神經(jīng)網(wǎng)絡(luò)模型
構(gòu)建復(fù)雜的神經(jīng)網(wǎng)絡(luò)模型通常涉及到將多個基本層或者自定義層按照特定順序組合起來。以下是一個使用自定義SimpleLayer類來構(gòu)建多層感知機(jī)(MLP)的示例:
import torch
import torch.nn as nn
class SimpleLayer(nn.Module):
def __init__(self, input_size, output_size):
super(SimpleLayer, self).__init__()
self.linear = nn.Linear(input_size, output_size)
self.relu = nn.ReLU()
def forward(self, x):
x = self.linear(x)
x = self.relu(x)
return x
class MLP(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(MLP, self).__init__()
# 第一層:輸入層到隱藏層
self.layer1 = SimpleLayer(input_dim, hidden_dim)
# 第二層:隱藏層到輸出層
self.layer2 = SimpleLayer(hidden_dim, output_dim)
def forward(self, x):
x = self.layer1(x) # 第一層前向傳播
x = self.layer2(x) # 第二層前向傳播
return x
# 實例化一個MLP模型
input_dim = 784 # 假設(shè)輸入維度為784(例如,MNIST數(shù)據(jù)集)
hidden_dim = 128 # 隱藏層維度
output_dim = 10 # 輸出維度(例如,10類分類問題)
model = MLP(input_dim, hidden_dim, output_dim)
# 打印模型結(jié)構(gòu)
print(model)
在以上代碼中,MLP類定義了一個包含兩個SimpleLayer實例的多層感知機(jī)。第一個SimpleLayer接收輸入數(shù)據(jù)并轉(zhuǎn)換到隱藏層空間,第二個SimpleLayer則負(fù)責(zé)從隱藏層空間映射到輸出層。通過這種方式,可以靈活地堆疊多個層來構(gòu)造復(fù)雜的神經(jīng)網(wǎng)絡(luò)模型,每增加一層,模型的表達(dá)能力就可能增強(qiáng),從而能學(xué)習(xí)到更復(fù)雜的輸入-輸出映射關(guān)系。
3. 模塊的嵌套和子模塊
在PyTorch中,nn.Module的嵌套和子模塊是構(gòu)建復(fù)雜神經(jīng)網(wǎng)絡(luò)架構(gòu)的關(guān)鍵。下面是一個名為ComplexModel的示例,它包含了兩個子模塊:一個CustomLayer和一個MLP:
import torch
import torch.nn as nn
class ComplexModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(ComplexModel, self).__init__()
# 創(chuàng)建一個CustomLayer實例
self.custom_layer = CustomLayer(input_size, hidden_size, output_size)
# 創(chuàng)建一個MLP實例
self.mlp = MLP(hidden_size, hidden_size, output_size)
def forward(self, x):
x = self.custom_layer(x)
x = self.mlp(x)
return x
# 實例化一個ComplexModel
input_size = 784 # 假設(shè)輸入維度為784
hidden_size = 128 # 隱藏層維度
output_size = 10 # 輸出維度
model = ComplexModel(input_size, hidden_size, output_size)
# 打印模型結(jié)構(gòu)
print(model)
其中,ComplexModel類包含兩個子模塊:custom_layer和mlp。custom_layer是一個自定義層,而mlp是一個多層感知機(jī)。當(dāng)在ComplexModel的forward方法中調(diào)用這些子模塊時,它們的計算將按順序進(jìn)行,并且所有子模塊的參數(shù)和梯度都會被自動跟蹤。這種模塊化的方法使得代碼易于理解和維護(hù),同時可以方便地重用和組合現(xiàn)有的層和模型。
4. 訪問模塊的參數(shù)
在PyTorch中,nn.Module類提供了兩種方法來訪問模型的參數(shù):parameters()和named_parameters()。這兩個方法都可以用來遍歷模型的所有參數(shù),但它們的區(qū)別在于返回的內(nèi)容。
- parameters()方法: 返回一個可迭代的生成器,其中每個元素是一個張量,代表模型的一個參數(shù)。
model = ComplexModel()
for param in model.parameters():
print(param)
- named_parameters()方法: 返回一個可迭代的生成器,其中每個元素是一個元組,包含參數(shù)的名稱和對應(yīng)的張量。
model = ComplexModel()
for name, param in model.named_parameters():
print(f"Name: {name}, Parameter: {param}")
在實際應(yīng)用中,通常使用named_parameters()方法,因為這樣可以同時獲取參數(shù)的名稱,這對于調(diào)試和可視化模型參數(shù)很有用。
5. 模型的保存與加載
要保存模型的狀態(tài)字典,可以使用state_dict()方法,然后使用torch.save()將其寫入磁盤。加載模型時,首先創(chuàng)建一個模型實例,然后使用load_state_dict()方法加載保存的參數(shù)。
- 保存模型:
torch.save(model.state_dict(), 'model.pth')
- 加載模型:
model = ComplexModel(input_size, hidden_size, output_size)
model.load_state_dict(torch.load('model.pth'))
6. 模型的設(shè)備移動
使用to()方法可以將模型及其所有參數(shù)移到GPU或CPU上。如果設(shè)備可用,它會嘗試將模型移動到GPU上,否則保留在CPU上。將模型移動到GPU(如果可用):
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
7. 自定義層和操作
要創(chuàng)建自定義的神經(jīng)網(wǎng)絡(luò)層或操作,可以繼承nn.Module,再實現(xiàn)新的前向傳播邏輯,包括新的數(shù)學(xué)函數(shù)、正則化、注意力機(jī)制等。例如,假設(shè)要創(chuàng)建一個自定義的歸一化層:
class CustomNormalization(nn.Module):
def __init__(self, dim):
super(CustomNormalization, self).__init__()
self.dim = dim
def forward(self, x):
mean = x.mean(dim=self.dim, keepdim=True)
std = x.std(dim=self.dim, keepdim=True)
return (x - mean) / (std + 1e-8)
model.add_module('custom_normalization', CustomNormalization(1))
首先定義了一個新的層CustomNormalization,它計算輸入張量在指定維度上的平均值和標(biāo)準(zhǔn)差,然后對輸入進(jìn)行歸一化。這個新層可以像其他任何nn.Module實例一樣添加到模型中,并在forward方法中使用。
四、優(yōu)化器
在 PyTorch 中,優(yōu)化器(Optimizer)是用于更新神經(jīng)網(wǎng)絡(luò)模型參數(shù)的工具。優(yōu)化器基于模型參數(shù)的梯度信息來調(diào)整參數(shù),從而最小化或最大化某個損失函數(shù)。PyTorch 提供了多種優(yōu)化器,包括隨機(jī)梯度下降(SGD)、Adam、RMSprop 等。
1. SGD
SGD是最基礎(chǔ)的優(yōu)化算法,它根據(jù)梯度的方向逐步調(diào)整模型參數(shù),以減少損失函數(shù)的值。在PyTorch中,可以通過以下方式創(chuàng)建一個SGD優(yōu)化器:
import torch.optim as optim
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
其中,model.parameters()用于獲取模型的所有可學(xué)習(xí)參數(shù)。lr是學(xué)習(xí)率,決定了參數(shù)更新的步長。momentum是動量項,默認(rèn)為0,可以加速學(xué)習(xí)過程并有助于跳出局部最小值。
2. Adam
Adam(Adaptive Moment Estimation)是另一種廣泛使用的優(yōu)化器,它結(jié)合了動量和自適應(yīng)學(xué)習(xí)率的優(yōu)點,可自動調(diào)整每個參數(shù)的學(xué)習(xí)率,通常不需要手動調(diào)整學(xué)習(xí)率衰減。
optimizer = optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.999))
其中,betas是兩個超參數(shù),分別控制了一階矩和二階矩估計的衰減率。
3. RMSprop
RMSprop(Root Mean Square Propagation)也是自適應(yīng)學(xué)習(xí)率的一種方法,它主要根據(jù)歷史梯度的平方根來調(diào)整學(xué)習(xí)率。
optimizer = optim.RMSprop(model.parameters(), lr=0.001, alpha=0.99)
其中,alpha是平滑常數(shù),用于計算梯度的移動平均。
五、損失函數(shù)
損失函數(shù)(Loss Function)在機(jī)器學(xué)習(xí)和深度學(xué)習(xí)領(lǐng)域扮演著核心角色,它是評估模型預(yù)測質(zhì)量的重要標(biāo)準(zhǔn)。損失函數(shù)量化了模型預(yù)測值與真實標(biāo)簽之間的偏差,訓(xùn)練過程本質(zhì)上是通過優(yōu)化算法(如梯度下降)不斷調(diào)整模型參數(shù),以最小化這個損失值。PyTorch,作為一個強(qiáng)大的深度學(xué)習(xí)框架,內(nèi)置了多種損失函數(shù),以適應(yīng)不同類型的機(jī)器學(xué)習(xí)任務(wù),主要包括但不限于以下幾類:
1. 均方誤差損失(Mean Squared Error, MSE)
用于回歸問題,計算預(yù)測值與真實值之間差的平方的平均值。
import torch
import torch.nn as nn
# 假設(shè)模型輸出和真實標(biāo)簽
outputs = model(inputs) # 模型的預(yù)測輸出
targets = labels # 真實標(biāo)簽
# 定義損失函數(shù)
mse_loss = nn.MSELoss()
# 計算損失
loss = mse_loss(outputs, targets)
2. 交叉熵?fù)p失(Cross-Entropy)
用于分類問題,計算預(yù)測概率分布與真實標(biāo)簽之間的交叉熵?fù)p失。
# 假設(shè)模型輸出為每個類別的概率分布
outputs = model(inputs)
# 確保標(biāo)簽是類別索引(而非one-hot編碼),對于多分類問題
targets = torch.LongTensor(labels) # 確保標(biāo)簽是整數(shù)
cross_entropy_loss = nn.CrossEntropyLoss()
loss = cross_entropy_loss(outputs, targets)
3. 二元交叉熵?fù)p失(Binary Cross-Entropy)
二元交叉熵?fù)p失通常用于二分類問題,其中每個樣本屬于兩個類別之一。
# 假設(shè)二分類問題,直接輸出概率
outputs = model(inputs) # 輸出已經(jīng)是概率
targets = labels.float() # 標(biāo)簽轉(zhuǎn)換為float,二分類通常為0或1
bce_loss = nn.BCELoss()
loss = bce_loss(outputs, targets)
如果兩類樣本數(shù)量嚴(yán)重不平衡,可以使用加權(quán)二元交叉熵?fù)p失(Weighted Binary Cross-Entropy Loss)來調(diào)整不同類別的權(quán)重,以確保模型在訓(xùn)練時對較少出現(xiàn)的類別給予更多關(guān)注。
import torch
import torch.nn as nn
# 假設(shè)有兩類,其中類0的樣本較少
num_samples = [100, 1000] # 類別0有100個樣本,類別1有1000個樣本
weights = [1 / num_samples[0], 1 / num_samples[1]] # 計算類別權(quán)重
# 創(chuàng)建一個加權(quán)二元交叉熵?fù)p失函數(shù)
weighted_bce_loss = nn.BCEWithLogitsLoss(weight=torch.tensor(weights))
# 假設(shè)model是模型,inputs是輸入數(shù)據(jù),labels是二進(jìn)制標(biāo)簽(0或1)
outputs = model(inputs)
labels = labels.float() # 將標(biāo)簽轉(zhuǎn)換為浮點數(shù),因為BCEWithLogitsLoss期望的是概率
# 計算加權(quán)損失
loss = weighted_bce_loss(outputs, labels)
4. K-L 散度損失(Kullback-Leibler Divergence Loss)
衡量兩個概率分布的差異,常用于生成模型訓(xùn)練,如VAEs和GANs中的鑒別器部分。
Kullback-Leibler散度(KLDivLoss)是一種衡量兩個概率分布之間差異的方法,常用于信息論和機(jī)器學(xué)習(xí)中。在PyTorch中,nn.KLDivLoss是實現(xiàn)這一概念的模塊,用于比較預(yù)測概率分布(通常是softmax函數(shù)的輸出)與目標(biāo)概率分布或“真實”分布。
KLDivLoss的數(shù)學(xué)定義為:
這里,(P)是真實分布,而(Q)是預(yù)測或近似分布。KLDivLoss總是非負(fù)的,并且只有當(dāng)兩個分布完全相同時才為零。
import torch
import torch.nn as nn
# 假設(shè)有兩個概率分布,preds是模型預(yù)測的概率分布,targets是實際的概率分布
preds = torch.randn(3, 5).softmax(dim=1) # 預(yù)測概率分布,使用softmax轉(zhuǎn)換
targets = torch.randn(3, 5).softmax(dim=1) # 真實概率分布
# 初始化KLDivLoss實例,reduction參數(shù)定義了損失的聚合方式,可以是'mean'、'sum'或'none'
criterion = nn.KLDivLoss(reduction='batchmean') # 'batchmean'表示對批量數(shù)據(jù)求平均
# 計算KLDivLoss
loss = criterion(preds.log(), targets) # 注意:preds應(yīng)該取對數(shù),因為KLDivLoss默認(rèn)期望log_softmax的輸出
print('KLDivLoss:', loss.item())
5. 三元組損失(Triplet Margin Loss)
三元組損失(Triplet Margin Loss)是深度學(xué)習(xí)中用于學(xué)習(xí)特征表示的一種損失函數(shù),尤其在人臉識別、圖像檢索等領(lǐng)域廣泛應(yīng)用。它的目標(biāo)是學(xué)習(xí)到一個特征空間,在這個空間中,同類別的樣本之間的距離小于不同類別樣本之間的距離,且保持一定的邊際差(margin)。
三元組損失函數(shù)的數(shù)學(xué)定義為:
其中:
- a是錨點樣本的特征向量
- p是正樣本的特征向量
- n是負(fù)樣本的特征向量
- d(x, y)表示樣本x和樣本y之間的距離(通常是歐氏距離或余弦距離)
- m是預(yù)設(shè)的邊際值,用于保證正樣本和負(fù)樣本之間的差距至少為m。
這個損失函數(shù)的目的是最小化所有滿足的三元組的損失,這樣就能確保錨點樣本與正樣本的距離小于與負(fù)樣本的距離至少m個單位。
在PyTorch中,可以使用torch.nn.TripletMarginLoss來實現(xiàn)三元組損失。
import torch
import torch.nn as nn
# 設(shè)置隨機(jī)種子以獲得可復(fù)現(xiàn)的結(jié)果
torch.manual_seed(42)
# 假設(shè)特征維度
feature_dim = 128
# 生成隨機(jī)三元組數(shù)據(jù)
num_triplets = 10
anchors = torch.randn(num_triplets, feature_dim)
positives = torch.randn(num_triplets, feature_dim)
negatives = torch.randn(num_triplets, feature_dim)
# 將它們組合成形狀為 (num_triplets, 3, feature_dim) 的張量
triplets = torch.stack((anchors, positives, negatives), dim=1)
# 初始化三元組損失函數(shù),設(shè)置邊際值m
triplet_loss = nn.TripletMarginLoss(margin=1.0)
# 計算損失
loss = triplet_loss(triplets[:, 0], triplets[:, 1], triplets[:, 2])
print('Triplet Margin Loss:', loss.item())
6. 使用損失函數(shù)進(jìn)行訓(xùn)練
在訓(xùn)練循環(huán)中,通過計算模型輸出與真實標(biāo)簽的損失,并調(diào)用反向傳播和優(yōu)化器更新參數(shù)來訓(xùn)練模型。
output = model(inputs)
loss = criterion(output, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
六、數(shù)據(jù)加載與預(yù)處理
在PyTorch中,數(shù)據(jù)加載與預(yù)處理是構(gòu)建深度學(xué)習(xí)模型不可或缺的環(huán)節(jié),它確保數(shù)據(jù)以高效、規(guī)范的方式被送入模型進(jìn)行訓(xùn)練或測試。
1. 數(shù)據(jù)集的定義
在PyTorch中,數(shù)據(jù)集的定義通常通過創(chuàng)建一個新的類來實現(xiàn),這個類繼承自torch.utils.data.Dataset。這個自定義類需要實現(xiàn)以下兩個核心方法:
- __len__方法:這個方法返回數(shù)據(jù)集中的樣本數(shù)量。它告訴外界調(diào)用者數(shù)據(jù)集中有多少個樣本可以用來訓(xùn)練或測試模型。
- __getitem__方法:這個方法根據(jù)給定的索引返回一個樣本數(shù)據(jù)及其對應(yīng)的標(biāo)簽(如果有)。它允許按需訪問數(shù)據(jù)集中的任意一個樣本,通常包括數(shù)據(jù)的加載和必要的預(yù)處理。
一個基本的數(shù)據(jù)集定義示例如下:
from torch.utils.data import Dataset
class CustomDataset(Dataset):
def __init__(self, data, labels, transform=None):
self.data = data
self.labels = labels
self.transform = transform
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
sample = {'data': self.data[idx], 'label': self.labels[idx]}
if self.transform:
sample = self.transform(sample)
return sample
其中,CustomDataset類接收3個參數(shù):data和labels、transform,分別代表數(shù)據(jù)集中的樣本數(shù)據(jù)和對應(yīng)的標(biāo)簽及預(yù)處理變換。在__init__方法中,將這些參數(shù)存儲在類的屬性中,以便在__getitem__方法中訪問。__len__方法返回數(shù)據(jù)集的長度,即樣本數(shù)量。__getitem__方法通過索引index獲取對應(yīng)的數(shù)據(jù)和標(biāo)簽。
此外,為了增強(qiáng)數(shù)據(jù)的多樣性和模型的泛化能力,可以在數(shù)據(jù)集類中集成數(shù)據(jù)預(yù)處理邏輯,或者通過傳遞一個變換對象(如torchvision.transforms中的變換)來動態(tài)地對數(shù)據(jù)進(jìn)行變換,如旋轉(zhuǎn)、縮放、裁剪等。
2. 數(shù)據(jù)加載器
數(shù)據(jù)加載器(DataLoader)在PyTorch中是一個非常重要的組件,它負(fù)責(zé)從數(shù)據(jù)集中高效地加載數(shù)據(jù),并為模型訓(xùn)練和驗證提供批次(batch)數(shù)據(jù)。DataLoader類位于torch.utils.data模塊中,提供了以下幾個關(guān)鍵功能:
- 批量加載:它能夠?qū)?shù)據(jù)集分割成多個小批量(batch),這是深度學(xué)習(xí)訓(xùn)練過程中的標(biāo)準(zhǔn)做法,有助于提高訓(xùn)練效率和內(nèi)存利用率。
- 數(shù)據(jù)混洗:通過設(shè)置shuffle=True,可以在每個訓(xùn)練epoch開始前隨機(jī)打亂數(shù)據(jù)集的順序,增加模型訓(xùn)練的隨機(jī)性,有助于提高模型的泛化能力。
- 多線程加載:通過num_workers參數(shù),可以在后臺使用多個線程并發(fā)地加載數(shù)據(jù),減少數(shù)據(jù)I/O等待時間,進(jìn)一步加速訓(xùn)練過程。
- 內(nèi)存節(jié)省:DataLoader通過按需加載數(shù)據(jù)(即僅在訓(xùn)練過程中需要時才從磁盤加載數(shù)據(jù)到內(nèi)存),避免一次性將整個數(shù)據(jù)集加載到內(nèi)存中,這對于大規(guī)模數(shù)據(jù)集尤為重要。
創(chuàng)建一個DataLoader實例的基本用法如下:
from torch.utils.data import DataLoader
from your_dataset_module import YourCustomDataset
custom_dataset = CustomDataset(data, labels,transform=...)
# 創(chuàng)建DataLoader實例
data_loader = DataLoader(
dataset=custom_dataset, # 數(shù)據(jù)集實例
batch_size=32, # 每個批次的樣本數(shù)
shuffle=True, # 是否在每個epoch開始時打亂數(shù)據(jù)
num_workers=4, # 使用的子進(jìn)程數(shù),用于數(shù)據(jù)加載(0表示不使用多線程)
drop_last=False, # 如果數(shù)據(jù)集大小不能被batch_size整除,是否丟棄最后一個不完整的batch
)
# 使用data_loader在訓(xùn)練循環(huán)中迭代獲取數(shù)據(jù)
for inputs, labels in data_loader:
# 在這里執(zhí)行模型訓(xùn)練或驗證的代碼
pass
3. 數(shù)據(jù)預(yù)處理與轉(zhuǎn)換
在PyTorch中,torchvision.transforms模塊提供了豐富的預(yù)處理和轉(zhuǎn)換功能,以下是一些常用的轉(zhuǎn)換操作:
(1) 常見的預(yù)處理與轉(zhuǎn)換操作:
- Resize:調(diào)整圖像大小到指定尺寸,例如,transforms.Resize((256, 256))會將圖像調(diào)整為256x256像素。
- CenterCrop:從圖像中心裁剪出指定大小的區(qū)域,如transforms.CenterCrop(224)。
- RandomCrop:隨機(jī)從圖像中裁剪出指定大小的區(qū)域,增加了數(shù)據(jù)多樣性,有利于模型學(xué)習(xí)。
- RandomHorizontalFlip:以一定概率水平翻轉(zhuǎn)圖像,是常用的數(shù)據(jù)增強(qiáng)手段之一。
- RandomRotation:隨機(jī)旋轉(zhuǎn)圖像一定角度,進(jìn)一步增強(qiáng)數(shù)據(jù)多樣性。
- ToTensor:將PIL圖像或numpy數(shù)組轉(zhuǎn)換為PyTorch的Tensor,并將顏色通道從RGB調(diào)整為Tensorflow所期望的格式(HWC -> CHW)。
- Normalize:對圖像像素值進(jìn)行標(biāo)準(zhǔn)化,通常使用特定數(shù)據(jù)集(如ImageNet)的均值和標(biāo)準(zhǔn)差,例如transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])。
(2) 組合變換
為了簡化應(yīng)用多個變換的過程,可以使用Compose類將多個變換操作組合在一起,形成一個變換管道,如:
transform = transforms.Compose([
transforms.Resize((256, 256)),
transforms.RandomCrop((224, 224)),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
# 將轉(zhuǎn)換應(yīng)用于數(shù)據(jù)集
dataset = CustomDataset(data, labels, transform=transform)
七、模型的保存與加載
在PyTorch中,保存和加載模型是通過torch.save()和torch.load()函數(shù)完成的。以下是詳細(xì)的解釋和代碼示例:
1. 模型的保存
模型的參數(shù)和狀態(tài)可以保存為狀態(tài)字典(state_dict),或者保存整個模型對象,包括模型結(jié)構(gòu)和參數(shù)。
- 保存狀態(tài)字典(僅參數(shù)):
# 定義模型
model = SimpleModel()
# 保存狀態(tài)字典
torch.save(model.state_dict(), 'model_state.pth')
- 保存整個模型(結(jié)構(gòu)+參數(shù)):
# 保存整個模型
torch.save(model, 'model.pth')
2. 模型的加載
加載模型時,可以單獨加載狀態(tài)字典并重新構(gòu)建模型,或者直接加載整個模型。
- 加載狀態(tài)字典并重建模型:
# 加載狀態(tài)字典
loaded_state_dict = torch.load('model_state.pth')
# 創(chuàng)建相同結(jié)構(gòu)的新模型
new_model = SimpleModel()
# 將加載的狀態(tài)字典加載到新模型
new_model.load_state_dict(loaded_state_dict)
- 加載整個模型:
# 加載整個模型
loaded_model = torch.load('model.pth')
3. 跨設(shè)備加載模型
如果模型在GPU上訓(xùn)練并保存,但在CPU上加載,可以使用map_location參數(shù):
# 在CPU上加載GPU上保存的模型
loaded_model = torch.load('model.pth', map_location=torch.device('cpu'))
4. 保存與加載模型的結(jié)構(gòu)和參數(shù)
在保存整個模型時,模型的結(jié)構(gòu)和參數(shù)都會被保存。
# 保存整個模型(包括結(jié)構(gòu)和參數(shù))
torch.save(model, 'model.pth')
# 加載整個模型
loaded_model = torch.load('model.pth')
5. 僅保存與加載模型的結(jié)構(gòu)
如果只想保存和加載模型的結(jié)構(gòu)而不包含參數(shù),可以使用 torch.save 時設(shè)置 save_model_obj=False。
# 保存模型結(jié)構(gòu)
torch.save(model, 'model_structure.pth', save_model_obj=False)
# 加載模型結(jié)構(gòu)
loaded_model_structure = torch.load('model_structure.pth')
6. 僅保存和加載模型的參數(shù)
如果只想保存和加載模型參數(shù)而不包含模型結(jié)構(gòu),可以使用 torch.save 時設(shè)置 save_model_obj=False。
# 保存模型參數(shù)
torch.save(model.state_dict(), 'model_parameters.pth')
# 加載模型參數(shù)
loaded_parameters = torch.load('model_parameters.pth')
model.load_state_dict(loaded_parameters)
八、學(xué)習(xí)率調(diào)整
學(xué)習(xí)率調(diào)整是深度學(xué)習(xí)模型訓(xùn)練過程中的一個重要環(huán)節(jié),它有助于模型在訓(xùn)練過程中找到更好的權(quán)重。PyTorch 提供了torch.optim.lr_scheduler模塊來實現(xiàn)各種學(xué)習(xí)率調(diào)整策略。
1. StepLR
StepLR是一種基礎(chǔ)且常用的學(xué)習(xí)率調(diào)整策略,它按照預(yù)定的周期(通常是按 epoch 計算)來調(diào)整學(xué)習(xí)率。其中,step_size參數(shù)指定了衰減發(fā)生的時間間隔。比如,如果step_size=5,則學(xué)習(xí)率每過5個epoch就會調(diào)整一次。 gamma參數(shù)控制了每次調(diào)整時學(xué)習(xí)率的衰減比例。如果gamma=0.1,這意味著每到達(dá)一個step_size,學(xué)習(xí)率就會乘以0.1,也就是衰減到原來的10%。
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR
# 初始化模型和優(yōu)化器
model = YourModel()
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
# 創(chuàng)建 StepLR 調(diào)度器
scheduler = StepLR(optimizer, step_size=5, gamma=0.1)
# 訓(xùn)練循環(huán)
for epoch in range(num_epochs):
# 訓(xùn)練過程...
# 在每個epoch結(jié)束時調(diào)用scheduler的step()方法來更新學(xué)習(xí)率
scheduler.step()
如上示例中,學(xué)習(xí)率會在每個第5、10、15...個epoch后自動減少為原來的10%,直到訓(xùn)練結(jié)束。
2. MultiStepLR
MultiStepLR 與 StepLR 類似,都是基于周期(epoch)來調(diào)整學(xué)習(xí)率,但提供了更靈活的衰減時間點控制。通過 milestones 參數(shù),可以精確指定學(xué)習(xí)率應(yīng)該在哪些特定的周期數(shù)下降。gamma 參數(shù)則決定了每次在這些指定周期學(xué)習(xí)率下降的比例。
例如,如果設(shè)置milestones=[10, 20, 30]和gamma=0.1,則:
- 在訓(xùn)練的第10個epoch結(jié)束后,學(xué)習(xí)率會首次乘以0.1,即減少到原來的10%。
- 接著,在第20個epoch后,學(xué)習(xí)率再次乘以0.1,相對于初始值衰減為原來的1%。
- 最后,在第30個epoch后,學(xué)習(xí)率又一次乘以0.1,最終相對于初始值衰減為原來的0.1%。
這種方式允許根據(jù)訓(xùn)練過程中的性能變化或預(yù)期的學(xué)習(xí)曲線,更加精細(xì)地控制學(xué)習(xí)率的下降時機(jī),有助于模型更好地收斂或避免過擬合。下面是使用 MultiStepLR 的簡單示例代碼:
import torch.optim as optim
from torch.optim.lr_scheduler import MultiStepLR
# 初始化模型和優(yōu)化器
model = YourModel()
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
# 創(chuàng)建 MultiStepLR 調(diào)度器
scheduler = MultiStepLR(optimizer, milestones=[10, 20, 30], gamma=0.1)
# 訓(xùn)練循環(huán)
for epoch in range(num_epochs):
# 訓(xùn)練過程...
# 每個epoch結(jié)束時調(diào)用scheduler的step()方法檢查是否需要調(diào)整學(xué)習(xí)率
scheduler.step()
3. ExponentialLR
ExponentialLR 是一種學(xué)習(xí)率調(diào)整策略,它使學(xué)習(xí)率按照指數(shù)函數(shù)的方式逐漸衰減。與 StepLR 和 MultiStepLR 在特定的周期突然改變學(xué)習(xí)率不同,ExponentialLR 在每個訓(xùn)練步驟(或每個epoch,具體取決于調(diào)度器的更新頻率)后,都按照一個固定的比率逐漸減少學(xué)習(xí)率。這對于需要平滑降低學(xué)習(xí)率,以更細(xì)致地探索解空間或在訓(xùn)練后期緩慢逼近最優(yōu)解的場景非常有用。
使用 ExponentialLR 的代碼示例如下:
import torch.optim as optim
from torch.optim.lr_scheduler import ExponentialLR
# 初始化模型和優(yōu)化器
model = YourModel()
optimizer = optim.SGD(model.parameters(), lr=initial_lr, momentum=0.9)
# 創(chuàng)建 ExponentialLR 調(diào)度器
# 其中 gamma 參數(shù)指定了學(xué)習(xí)率衰減的速率,例如 gamma=0.9 表示每經(jīng)過一個調(diào)整周期,學(xué)習(xí)率變?yōu)樵瓉淼?90%
scheduler = ExponentialLR(optimizer, gamma=0.9)
# 訓(xùn)練循環(huán)
for epoch in range(num_epochs):
# 訓(xùn)練過程...
# 每個epoch結(jié)束時調(diào)用scheduler的step()方法更新學(xué)習(xí)率
scheduler.step()
其中,initial_lr即為設(shè)定的初始學(xué)習(xí)率,gamma=0.9 表示每次更新后,學(xué)習(xí)率都會乘以0.9,因此學(xué)習(xí)率會以指數(shù)形式逐漸減小。
4. 使用學(xué)習(xí)率調(diào)整器
在PyTorch中使用學(xué)習(xí)率調(diào)整器(Learning Rate Scheduler)是一個提高模型訓(xùn)練效率和性能的有效策略。下面以StepLR為例展示如何使用學(xué)習(xí)率調(diào)整器。
import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR
# 假設(shè)的模型定義
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.linear = nn.Linear(10, 1)
def forward(self, x):
return self.linear(x)
# 實例化模型和優(yōu)化器
model = SimpleModel()
optimizer = optim.SGD(model.parameters(), lr=0.1)
# 創(chuàng)建學(xué)習(xí)率調(diào)整器
scheduler = StepLR(optimizer, step_size=5, gamma=0.1) # 每5個epoch學(xué)習(xí)率減半
# 訓(xùn)練循環(huán)
num_epochs = 30
for epoch in range(num_epochs):
# 假設(shè)的訓(xùn)練步驟,這里簡化處理
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
output = model(data)
loss = F.mse_loss(output, target)
loss.backward()
optimizer.step()
# 每個epoch結(jié)束時更新學(xué)習(xí)率
scheduler.step()
print(f"Epoch [{epoch+1}/{num_epochs}], LR: {scheduler.get_last_lr()[0]}")
九、模型評估
模型評估是機(jī)器學(xué)習(xí)項目中不可或缺的一環(huán),它旨在量化模型在未知數(shù)據(jù)上的表現(xiàn),確保模型具有良好的泛化能力。以下是模型評估的關(guān)鍵步驟。
1. 設(shè)置模型為評估模式
在PyTorch中,通過調(diào)用model.eval()方法,模型會被設(shè)置為評估模式。這一步驟至關(guān)重要,因為它會影響到某些層的行為,比如關(guān)閉Dropout層和Batch Normalization層的訓(xùn)練時特有的特性,確保模型的預(yù)測是確定性的,并且不會影響模型的內(nèi)部狀態(tài)。
model.eval()
2. 使用驗證集或測試集進(jìn)行推理
遍歷驗證集或測試集,對輸入數(shù)據(jù)進(jìn)行前向傳播,得到模型的預(yù)測輸出。
model.eval()
with torch.no_grad():
for inputs, labels in dataloader:
outputs = model(inputs)
# 進(jìn)行后續(xù)處理..
3. 計算性能指標(biāo)
(1) 準(zhǔn)確率(Accuracy)
準(zhǔn)確率(Accuracy)是機(jī)器學(xué)習(xí)中最基本且直觀的性能評估指標(biāo)之一,尤其適用于多分類問題。它定義為模型正確分類的樣本數(shù)占總樣本數(shù)的比例。
import torch
# 假設(shè) outputs 和 labels 都是形狀為 (batch_size,) 的張量
# 對于多分類問題,outputs 通常包含每個類別的概率,需要獲取預(yù)測類別
_, predicted = torch.max(outputs.data, 1)
# 將預(yù)測和真實標(biāo)簽轉(zhuǎn)換為相同的數(shù)據(jù)類型(例如,都轉(zhuǎn)為整數(shù))
if isinstance(predicted, torch.Tensor):
predicted = predicted.cpu().numpy()
if isinstance(labels, torch.Tensor):
labels = labels.cpu().numpy()
# 計算并輸出準(zhǔn)確率
accuracy = (predicted == labels).sum() / len(labels)
print(f'Accuracy: {accuracy}')
(2) 精確度(Precision)
精確度(Precision)是模型預(yù)測為正類的樣本中,真正為正類的比例。
from sklearn.metrics import precision_score
# 假設(shè) predictions 和 true_labels 是形狀為 (n_samples,) 的數(shù)組
# predictions 是模型的預(yù)測結(jié)果,true_labels 是對應(yīng)的真值標(biāo)簽
# 如果是多分類問題,labels 參數(shù)是所有類別的列表
# 二分類問題
precision_binary = precision_score(true_labels, predictions)
# 多分類問題,宏平均
precision_macro = precision_score(true_labels, predictions, average='macro')
# 多分類問題,微平均
precision_micro = precision_score(true_labels, predictions, average='micro')
print(f'Binary Precision: {precision_binary}')
print(f'Macro Average Precision: {precision_macro}')
print(f'Micro Average Precision: {precision_micro}')
(3) 召回率(Recall)
召回率(Recall),也稱為靈敏度或真正率,衡量的是模型識別出的所有正類樣本中,正確識別的比例。
from sklearn.metrics import recall_score
# 假設(shè) predictions 和 true_labels 是形狀為 (n_samples,) 的數(shù)組
# predictions 是模型的預(yù)測結(jié)果,true_labels 是對應(yīng)的真值標(biāo)簽
# 對于多分類問題,labels 參數(shù)是所有類別的列表
# 二分類問題
recall_binary = recall_score(true_labels, predictions)
# 多分類問題,宏平均
recall_macro = recall_score(true_labels, predictions, average='macro')
# 多分類問題,微平均
recall_micro = recall_score(true_labels, predictions, average='micro')
print(f'Binary Recall: {recall_binary}')
print(f'Macro Average Recall: {recall_macro}')
print(f'Micro Average Recall: {recall_micro}')
(4) F1分?jǐn)?shù)(F1 Score)
F1分?jǐn)?shù)是精確度(Precision)和召回率(Recall)的調(diào)和平均值,旨在提供一個綜合評價指標(biāo),特別是對于類別不平衡的數(shù)據(jù)集。
from sklearn.metrics import f1_score
# 假設(shè) predictions 和 true_labels 是形狀為 (n_samples,) 的數(shù)組
# predictions 是模型的預(yù)測結(jié)果,true_labels 是對應(yīng)的真值標(biāo)簽
# 對于多分類問題,labels 參數(shù)是所有類別的列表
# 二分類問題
f1_binary = f1_score(true_labels, predictions)
# 多分類問題,宏平均
f1_macro = f1_score(true_labels, predictions, average='macro')
# 多分類問題,微平均
f1_micro = f1_score(true_labels, predictions, average='micro')
print(f'Binary F1 Score: {f1_binary}')
print(f'Macro Average F1 Score: {f1_macro}')
print(f'Micro Average F1 Score: {f1_micro}')
4. ROC曲線
ROC曲線(Receiver Operating Characteristic Curve)是一種評估二分類模型性能的方法,特別是在正負(fù)樣本比例不平衡或者對假陽性(False Positives, FP)和假陰性(False Negatives, FN)的代價不等同的場景下特別有用。ROC曲線通過改變決策閾值,展示了模型在不同閾值下的真正例率(True Positive Rate, TPR)與假正例率(False Positive Rate, FPR)之間的關(guān)系。