损失函数之Cross-Entropy介绍及C++实现
? ? ? 在深度學習中,損失函數用來評估模型的預測值與真實值之間的差異程度,是模型對數據擬合程度的反映,擬合的越差,損失函數的值越大;反之,損失函數越小,說明模型的預測值就越接近真實值,模型的準確性也就越好。深度學習的模型訓練的目標就是使損失函數的值盡可能小。因此損失函數又被稱為目標函數。深度學習的模型訓練的過程就是不斷地最小化損失函數。選擇適合的損失函數不僅影響最終預測的準確性,而且影響訓練的效率。
? ? ? 常用的損失函數包括:最小均方差損失函數、L1范數損失函數、L2范數損失函數、交叉熵損失函數等。
? ? ? 1948年,香農提出了信息熵的概念,并且發展為一門獨立的學科,即信息論。香農將平均自信息量定義為信息熵,簡稱為熵。在信息論中,信息熵是為了消除不確定性所需的度量,為了驗證概率低的事件,需要大量的信息,此時的信息熵很大;相反,為了驗證概率高的事件,則需要少量的信息,此時的信息熵很小。
? ? ? 交叉熵用于度量分布之間的信息差異。交叉熵是信息論中的重要概念,熵是對不確定問題的度量準則,而交叉熵是信息論領域的一種度量,建立在熵的基礎上,通常是用來度量兩個概率分布之間信息的差異。
? ? ? 最小化交叉熵的過程也就是極大似然估計,深度學習訓練的目的,就是最小化交叉熵,使預測的數據分布與真實的數據分布盡量相同。
? ? ? 交叉熵損失函數(Cross-Entropy Loss Function)通常被用來解決深度學習中的分類問題。
? ? ? 對于多分類,每個樣本都有一個已知的類標簽(class label),概率為1.0,所有其它標簽的概率為0.0。模型(model)可以估計樣本屬于每個類別標簽的概率。然后可以使用交叉熵來計算兩個概率分布之間的差異。
? ? ? 如果一個分類問題具有三個類別,并且一個樣本具有第一類的標簽,則概率分布將為[1,0,0];如果一個樣本具有第二類的標簽,則它概率分布為[0,1,0]。
? ? ? PyTorch中的交叉熵損失函數的計算還包含了Softmax。Softmax能將原網絡輸出轉變為概率形式。
? ? ? Softmax交叉熵損失函數是最常用的分類損失函數。若要將樣本分為C個類別,在使用Softmax交叉熵損失時,需要將神經網絡的最后一層輸出設置為C,得到C個分數后輸入Softmax交叉熵損失函數。
? ? ? Softmax交叉損失函數實際上分為兩步:求Softmax和求交叉熵損失,其中第一步操作可以得到當前樣本屬于某類別的概率,然后將這些概率與實際值One-Hot向量求交叉熵,因為實際值是僅在第y個位置為1,其它部分為0,所以最終只保留了第y個位置的交叉熵。
? ? ? 在深度學習樣本訓練的過程中,采用One-Hot形式進行標簽編碼,再計算交叉熵損失。在使用交叉熵損失函數的網絡訓練之前,需要將樣本的實際值也轉化為概率值形式。為達到這個目的,常用的方法為獨熱編碼即One-Hot編碼,又稱一位有效編碼,其方法是使用N位狀態寄存器來對N個狀態進行編碼,每個狀態都有它獨立的寄存器位,并且在任意時候,其中只有一位有效。
? ? ?Softmax的介紹參考:https://blog.csdn.net/fengbingchun/article/details/75220591
? ? ? 交叉熵損失函數公式如下:來自于:https://programmathically.com/an-introduction-to-neural-network-loss-functions/
? ? ?
?? ? ? N:樣本數;M:類別數;y:預期結果;y hat:模型產生的結果
? ? ? 交叉熵損失函數的C++實現如下:
template<typename _Tp> // y實際值; t預測值; m類別數
_Tp loss_function_cross_entropy(const _Tp* y, const _Tp* t, int m)
{_Tp loss = 0.;for (auto i = 0; i < m; ++i)loss += -y[i] * std::log(t[i]);return loss;
}
? ? ? 測試代碼如下:
int test_loss_function()
{
{ // only one sampleconst int classes_number = 5;std::vector<float> sample = { 0.0418, 0.0801, -1.3888, -1.9604, 1.0712 };std::vector<float> target = { 0, 0, 1, 0, 0 }; // One-Hotstd::vector<float> input(classes_number);assert(sample.size() == classes_number && target.size() == classes_number && input.size() == classes_number);fbc::activation_function_softmax(sample.data(), input.data(), classes_number);float output = fbc::loss_function_cross_entropy(target.data(), input.data(), classes_number);fprintf(stdout, "output: %.4f\n", output);
}{ // five samplesconst int classes_number = 5, samples_number = 5;std::vector<std::vector<float>> samples = {{0.0418, 0.0801, -1.3888, -1.9604, 1.0712 },{0.3519, -0.6115, -0.0325, 0.4484, -0.1736},{0.1530, 0.0670, -0.3894, -1.0830, -0.4757},{-1.3519, 0.2115, 1.2325, -1.4484, 0.9736},{1.1230, -0.5670, 1.0894, 1.9890, 0.03567}};std::vector<std::vector<float>> targets = {{0, 0, 0, 0, 1},{0, 0, 0, 1, 0},{0, 0, 1, 0, 0},{0, 1, 0, 0, 0},{1, 0, 0, 0, 0}};std::vector<std::vector<float>> inputs(samples_number);assert(samples[0].size() == classes_number && targets[0].size() == classes_number && inputs.size() == samples_number);float output = 0.;for (int i = 0; i < samples_number; ++i) {inputs[i].resize(classes_number);fbc::activation_function_softmax(samples[i].data(), inputs[i].data(), classes_number);output += fbc::loss_function_cross_entropy(targets[i].data(), inputs[i].data(), classes_number);}output /= samples_number;fprintf(stdout, "output: %.4f\n", output);
}return 0;
}
? ? ? 執行結果如下:
?? ? ? 調用PyTorch接口測試代碼如下:
import torch
import torch.nn as nnloss = nn.CrossEntropyLoss()input = torch.tensor([[0.0418, 0.0801, -1.3888, -1.9604, 1.0712]])
target = torch.tensor([2]).long() # target為2,one-hot表示為[0,0,1,0,0]
output = loss(input, target)
print("output:", output)data1 = [[ 0.0418, 0.0801, -1.3888, -1.9604, 1.0712],[ 0.3519, -0.6115, -0.0325, 0.4484, -0.1736],[ 0.1530, 0.0670, -0.3894, -1.0830, -0.4757],[ -1.3519, 0.2115, 1.2325, -1.4484, 0.9736],[ 1.1230, -0.5670, 1.0894, 1.9890, 0.03567]]
data2 = [4, 3, 2, 1, 0]input = torch.tensor(data1)
target = torch.tensor(data2)
output = loss(input, target)
print("output:", output)
??? ? ? 執行結果如下:可見C++實現的代碼與調用PyTorch接口兩邊產生的結果完全一致
??? ? ? ?GitHub:
??? ? ? ??? ? ? https://github.com/fengbingchun/NN_Test
??? ? ? ??? ? ? https://github.com/fengbingchun/PyTorch_Test
總結
以上是生活随笔為你收集整理的损失函数之Cross-Entropy介绍及C++实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows上通过cmake-gui生
- 下一篇: pybind11介绍