每次訓練神經網路的時候都會有一個目標,也會有一個輸出。目標和輸出之間的誤差,就是用\(Loss\) \(Function\)來衡量的。所以,誤差\(Loss\)是越小越好的。
此外,我們可以根據誤差\(Loss\),指導輸出\(output\)接近目標\(target\)。即我們可以以\(Loss\)為依據,不斷訓練神經網路,優化神經網路中各個模組,從而優化\(output\)。
\(Loss\) \(Function\)的作用:
(1)計算實際輸出和目標之間的差距
(2)為我們更新輸出提供一定的依據,這個提供依據的過程也叫反向傳播。
計算\(MAE\) (mean absolute error),即假設輸入為\(x_i\),目標為\(y_i\),特徵數量為\(n\)。在預設情況下,\(nn.L1Loss\)通過下面公式計算誤差:
class torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')
引數說明:
reduction:預設為 ‘mean’ ,可選mean和sum。
當reduction='mean'
時,計算誤差採用公式:
當reduction='sum'
時,計算誤差採用公式:
需要注意的是,計算的資料必須為浮點數。
程式碼栗子:
import torch
from torch.nn import L1Loss
input=torch.tensor([1,2,3],dtype=torch.float32)
target=torch.tensor([1,2,5],dtype=torch.float32)
input=torch.reshape(input,(1,1,1,3))
target=torch.reshape(target,(1,1,1,3))
loss1=L1Loss() #reduction='mean'
loss2=L1Loss(reduction='sum') #reduction='mean'
result1=loss1(input,target)
result2=loss2(input,target)
print(result1,result2)
計算\(MSE\) (mean squared error),即假設輸入為\(x_i\),目標為\(y_i\),特徵數量為\(n\)。在預設情況下,\(nn.MSELoss\)通過下面公式計算誤差:
class torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')
引數說明:
reduction:預設為 ‘mean’ ,可選mean和sum。
當reduction='mean'
時,計算誤差採用公式:
當reduction='sum'
時,計算誤差採用公式:
程式碼栗子:
import torch
from torch.nn import L1Loss,MSELoss
input=torch.tensor([1,2,3],dtype=torch.float32)
target=torch.tensor([1,2,5],dtype=torch.float32)
input=torch.reshape(input,(1,1,1,3))
target=torch.reshape(target,(1,1,1,3))
loss_mse1=MSELoss() #reduction='mean'
loss_mse2=MSELoss(reduction='sum') #reduction='mean'
result_mse1=loss_mse1(input,target)
result_mse2=loss_mse2(input,target)
print(result_mse1,result_mse2)
當訓練一個分類問題的時候,假設這個分類問題有\(C\)個類別,那麼有:
*注意:其中的\(log\)在數學中表示的是\(ln\),即以10為底的對數函數
舉個栗子:
我們對包含了人、狗、貓的圖片進行分類,其標籤的索引分別為0、1、2。這時候將一張狗的圖片輸入神經網路,即目標(\(target\))為\(1\)(對應狗的標籤索引)。輸出結果為\([0.1,0.2,0.3]\),該列表中的數位分別代表分類標籤對應的概率。
根據上述分類結果,圖片為人的概率更大,即\(0.3\)。對於該分類的\(Loss\) \(Function\),我們可以通過交叉熵去計算,即:
那麼如何驗證這個公式的合理性呢?根據上面的栗子,分類結果越準確,\(Loss\)應該越小。這條公式由兩個部分組成:
\(log(\sum_{j}exp(x[j])\):主要作用是控制或限制預測結果的概率分佈。比如說,預測出來的人、狗、貓的概率均為0.9,每個結果概率都很高,這顯然是不合理的。此時\(log(\sum_{j}exp(x[j])\)的值會變大,誤差\(loss(x,class)\)也會隨之變大。同時該指標也可以作為分類器效能評判標準。
\(-x[class]\):在已知圖片類別的情況下,預測出來對應該類別的概率\(x[class]\)越高,其預測結果誤差越小。
引數說明:
Input: \((N,C)\),其中\(N\)代表batch_size,\(C\)代表分類的數量(或者叫標籤數量),即資料要分成幾類(或有幾個標籤)。
Target: \((N)\),對於每個資料:\(0\leq{target[i]}\leq{C-1}\)
程式碼栗子:
import torch
from torch.nn import L1Loss,MSELoss,CrossEntropyLoss
x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
x=torch.reshape(x,(1,3))
loss_cross=CrossEntropyLoss()
result_cross=loss_cross(x,y)
print(result_cross)
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
dataset=torchvision.datasets.CIFAR10("./dataset",train=False,download=True,transform=torchvision.transforms.ToTensor())
dataloder=DataLoader(dataset,batch_size=1)
class Demo(nn.Module):
def __init__(self):
super(Demo,self).__init__()
self.model1=Sequential(
Conv2d(3,32,5,padding=2),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self,x):
x=self.model1(x)
return x
demo=Demo()
loss=nn.CrossEntropyLoss()
for data in dataloder:
imgs,targets=data
output=demo(imgs)
# print(output)
#[Run] 一共輸出10個資料,分別代表該影象為各個標籤的概率.具體如下:
# tensor([[-0.0151, -0.0990, 0.0908, 0.0354, 0.0731, -0.0313, -0.0329, 0.1006,
# -0.0953, 0.0449]], grad_fn= < AddmmBackward0 >)
# print(targets)
#[Run] 輸出該影象真實的標籤,具體如下:
# tensor([7])
result_loss=loss(output,targets)
print(result_loss)
如何根據\(Loss\) \(Function\)為更新神經網路資料提供依據?
對於每個折積核當中的引數,設定一個\(grad\)(梯度)。
當我們進行反向傳播的時候,對每一個節點的引數都會求出一個對應的梯度。之後我們根據梯度對每一個引數進行優化,最終達到降低\(Loss\)的一個目的。比較典型的一個方法——梯度下降法。
程式碼舉例:
result_loss.backward()
result_loss=loss(output,targets)
計算出來的結果,是沒有\(grad\)這個引數的。