loss函數學習筆記


一直對機器學習里的loss函數不太懂,這里做點筆記。
符號表示的含義,主要根據Andrew Ng的課程來的,\(m\)個樣本,第\(i\)個樣本為\(\vec x^{(i)}\),對應ground truth標簽為\(y^{(i)}\)

線性回歸

假設函數:

\[\begin{align} h_{\vec \theta}(\vec x^{(i)}) & = \vec \theta^T \vec x \\ \end{align} \]

損失函數:
使用MSE(mean squared error)作為loss function

\[\begin{align} J(\vec \theta) & = \frac{1}{2m} \sum\limits_{i=1}^{m}(h_{\vec \theta}(\vec x^{(i)}-y^{(i)})^2 \\ \end{align} \]

有mini-SGD梯度下降來優化

邏輯回歸

邏輯回歸用於二分類,所以也叫邏輯分類。
先把線性回歸泛化為廣義線性模型:

\[\begin{align} h_{\vec \theta}(\vec x) & = g^{-1}(\vec \theta^T \vec x^{(i)}) \\ \end{align} \]

考慮到執行二分類,要預測的\(y^{(i)} \in {0,1}\),因此使用Sigmoid函數:

\[\begin{align} g^{-1}(z) & = \frac{1}{1+e^{-z}} \\ \end{align} \]

得到邏輯回歸的假設函數:

\[\begin{align} h_{\vec \theta}(\vec x) & = \frac{1}{1+e^{-\vec \theta^T \vec x}} \\ \end{align} \]

獲得邏輯回歸的損失函數,則和線性模型不同。是從極大似然估計入手的,因為根據經驗風險最小化的原則,應當搜索參數\(\vec \theta\)使得loss函數取值最小,數學表達式上等價於似然函數取最大。那么首先寫出概率密度函數(p.d.f),似然函數是所有樣本的概率密度乘積,再取對數,以及乘以\(-1\),就得到邏輯回歸損失函數。

邏輯回歸的每個樣本\(\vec x^{(i)}\)對應的類別標簽\(y^{(i)}\)服從兩點分布(Bernoulli分布),其p.d.f為:

\[\begin{align} f(y^{(i)}|\phi) & = \phi^{y^{(i)}}(1-\phi)^{1-y^{(i)}} \\ \phi & = h_{\vec \theta}(x^{(i)}) \\ \end{align} \]

其中\(\phi\)表示\(p(y^{(i)}=1)\),也就是\(x^{(i)}\)被預測為正樣本(“1”類)的概率。

對應的似然函數數為:

\[\begin{align} l(\vec \theta) & = \prod\limits_{i=1}^{m}p(y^{(i)}|h_{\vec \theta}(\vec x^{(i)})) \\ & = (h_{\vec \theta}(\vec x^{(i)})^{y^{(i)}})(1-h_{\vec \theta}(\vec x^{(i)}))^{1-y^{(i)}} \\ \end{align} \]

則邏輯回歸的損失函數(也即負對數似然函數為):

\[\begin{align} J(\vec \theta) & = -ln l(\vec \theta) \\ & = \sum\limits_{i=1}^{m}[y^{(i)}ln(h_{\vec \theta}(\vec x^{(i)}))+(1-y^{(i)})ln(1-h_{\vec \theta}(\vec x^{(i)}))] \\ \end{align} \]

對應的優化求解,通常也是用梯度下降來搞

Softmax回歸

考慮多類分類問題,\(y^{(i)} \in \{1,2,...,K\}\),則將邏輯回歸擴展一下可以得到想要的假設函數和損失函數。

Softmax

Sigmoid是這樣的映射:\(\sigma: \mathbb{R} \rightarrow \{0,1\}\)
Softmax則是這樣的映射:\(\sigma: \mathbb{R}^{K} \rightarrow \{0,1\}^{K}\)
也即,Softmax對一個只有一個1的one-hot編碼的類別標簽向量\(\vec t^{(i)}\)做映射,效果上是\(\vec t^{(i)}\)的每個維度都被Softmax映射到\(\{0,1\}\)內,但並不是各個維度獨立執行sigmoid,而是:

\[\begin{align} Softmax(\vec x^{(i)}) & = [\frac{e^{x_1^{(i)}}}{\sum\limits_{j=1}^Ke^{x_j^{(i)}}};\frac{e^{x_2^{(i)}}}{\sum\limits_{j=1}^Ke^{x_j^{(i)}}}; ...; \frac{e^{x_K^{(i)}}}{\sum\limits_{j=1}^Ke^{x_j^{(i)}}};] \\ \end{align} \]

所以,看到很多網上的資料寫說softmax看作是sigmoid的泛化形式,我覺得有誤導嫌疑,從公示上看並不像,僅僅是效果上相似。

Softmax回歸的假設函數

相當於在線性回歸對於各個類別的預測的概率向量基礎上,包了一層Softmax:

\[\begin{align} h_{\vec \theta}(\vec x^{(i)}) & = Softmax(\vec \theta_1^T\vec x^{(i)}; \vec \theta_2^T\vec x^{(i)}, ...;\vec \theta_K^T\vec x^{(i)}) \\ & = (p(y^{(i)}=1|\vec x^{(i)};\vec \theta_1); p(y^{(i)}=2|\vec x^{(i)};\vec \theta_1); ...; p(y^{(i)}=K|\vec x^{(i)};\vec \theta_1)) \\ & = \frac{1}{\sum\limits_{j=1}^Ke^{\vec \theta_j^T\vec x^{(i)}}}(e^{\vec \theta_1^T\vec x^{(i)}}; e^{\vec \theta_2^T\vec x^{(i)}}; ...; e^{\vec \theta_K^T\vec x^{(i)}}) \\ \end{align} \]

Softmax回歸的loss函數

依然是用負對數似然函數作為損失函數,只不過此時的p.d.f是服從多點分布的了:

\[\begin{align} f(y^{(i)}|h_{\vec\theta}(\vec x^{(i)})) & = \prod\limits_{j=1}^Kp(y^{(i)}=j) \\ & = \prod\limits_{j=1}^K(h_{\vec \theta_j}(\vec x^{(i)})^{y^{(i)}}) \\ \end{align} \]

其似然函數為:

\[\begin{align} l(\vec \theta) & = \prod\limits_{i=1}^mf(y^{(i)}|h_{\vec\theta}(\vec x^{(i)})) \\ \end{align} \]

使用負對數似然函數作為損失函數:

\[\begin{align} J(\vec \theta) & = -ln l(\vec \theta) \\ & = -\sum\limits_{i=1}^mlnf(y^{(i)}|h_{\vec \theta}(\vec x^{(i)})) \\ & = -\sum\limits_{i=1}^m \sum\limits_{j=1}^K y^{(i)}ln(h_{\vec\theta_j}(\vec x^{(i)})) \\ & = -\sum\limits_{i=1}^m \sum\limits_{j=1}^K (I(y^{(i)}=j)ln(h_{\vec\theta_j}(\vec x^{(i)}))) \\ & = -\sum\limits_{i=1}^m ln(\frac{e^{\vec\theta_{y^{(i)}}\vec x^{(i)}}}{\sum\limits_{l=1}^Ke^{\vec\theta_l^T \vec x^{(i)}}}) \\ \end{align} \]


交叉熵損失函數Cross-Entropy Loss Function

邏輯回歸是做二分類,其損失函數是2類情況下的Cross-Entropy Loss

Softmax回歸是做多類分類,其損失函數是K類情況下的Cross-Entropy Loss:

\[\begin{align} -\sum\limits_{c=1}^K{y_{gt}\log(y_{pred})} \end{align} \]

其中\(y_{gt}\)表示ground truth的y取值;\(y_{pred}\)表示分類器預測出來的y取值

Softmax Loss和Cross-Entropy Loss是一樣的嗎?

Cross-Entropy Loss,交叉熵損失函數。

嚴格說起來Cross-Entropy Loss則是規范屬術語,而Softmax Loss不是規范術語。Softmax classifier是一個線性分類器,使用到了Cross-Entropy Loss函數。也就是說,交叉熵損失函數的梯度,告訴了Softmax分類器應該如何在SGD更新公式里更新參數\(\vec \theta\)

但是,約定俗成的說法,當人們提到SoftmaxLoss時,說的就是Cross-Entropy Loss。

(ref: https://www.quora.com/Is-the-softmax-loss-the-same-as-the-cross-entropy-loss)

此外也注意到,Softmax回歸和Logistic回歸,它們的損失函數都是交叉熵損失函數。


Caffe里的線性回歸、邏輯回歸、softmax回歸的損失函數

EuclideanLoss

EuclideanLoss作為線性回歸的損失函數

SigmoidCrossEntropyLoss

SigmoidCrossEntropyLoss是計算cross-entropy (logistic) loss,也就是multi-label並且label相互獨立,例如“民族歌曲、女聲、優雅”這樣的標簽;當然也可用於互斥的label,也即多類分類展開為one-hot編碼,但此時和SoftmaxWithLoss計算結果是不一樣的。

這個函數具體實現的時候,為了數值的穩定性,做了處理。參考:http://www.caffecn.cn/?/question/25

SoftmaxWithLoss

SoftmaxWithLoss是計算multinomial logistic loss,也就是服從多點分布的情形,單個標簽,one-hot編碼后只有一個1,其計算結果和SigmoidCrossEntropyLoss不能混為一談。

具體計算時,各個維度分別減去最大維度上的值再計算softmax(作為預測出的概率),然后套用到負對數似然損失函數中。參考shuzfan的博客:https://blog.csdn.net/shuzfan/article/details/51460895

二分類時,SigmoidCrossEntropyLoss和SoftmaxWithLoss的異同
兩者相同的地方:都是用交叉熵作為損失函數的大模樣

\[\frac{1}{m}\sum\limits_{i=1}^{m}[y^{(i)}\ln (\hat{y^{(i)}}) + (1-y^{(i)}) \ln (1-\hat{y^{(i)}})] \]

其中\(\hat{y^{(i)}}\)也就是\(h_{\vec \theta}(\vec x^{(i)})\)

兩者不同的地方:前者用sigmoid分別處理特征的各個維度,處理后作為預測的概率\(\hat y\);后者用softmax處理整個特征的各個維度。注意sigmoid是獨立考慮計算各個維度的,而sofmax必須知道所有維度取值后才可以分別計算各個維度。

用代碼運行結果驗證:
取x=[3,5]作為分類器/回歸器/損失函數的輸入,對應的ground truth類別標簽為1,one-hot編碼后為[0,1]。
分別以EuclideanLoss、SigmoidCrossEntropyLoss、SoftmaxWithLoss作為loss函數進行計算(這里是為了示范,實際情況下分類任務不用EuclideanLoss)。

test.py:

#!/usr/bin/env python
# coding:utf-8

from __future__ import print_function
import os, sys
pycaffe_dir = '/home/chris/work/caffe-BVLC/python'
sys.path.insert(0, pycaffe_dir)

import numpy as np
import caffe
from caffe import layers as L, params as P, to_proto
from caffe.proto import caffe_pb2
import yaml
from matplotlib import pyplot as plt


x = np.array([3,5], dtype=np.float32)
x = x[np.newaxis, :]

# single_label:把類別對應的索引作為single_label,從0開始
y1 = np.array([1], dtype=np.float32)
y1 = y1[np.newaxis, :]

# full_label:one-hot編碼格式的類別標簽向量,只有一個1,其他都是0
y2 = np.array([0, 1], dtype=np.float32)
y2 = y2[np.newaxis, :]

print('x.shape:', x.shape)
print('y1.shape:', y1.shape)
print('y2.shape:', y2.shape)


caffe.set_mode_cpu()
solver = caffe.SGDSolver('solver.pt')
solver.net.blobs['data'].data[...] = x
solver.net.blobs['single_label'].data[...] = y1
solver.net.blobs['full_label'].data[...] = y2

solver.step(1)
print('===========================')
print('x: [3,5], y:1,i.e. [0,1]')

# 0.12692806
# 也就是-math.log(math.exp(0)/(math.exp(-2)+math.exp(0)))
softmax_loss = solver.net.blobs['softmax_loss'].data
print('softmax_loss:', softmax_loss)

# 3.0553026
# 也就是-(-3-math.log(1+math.exp(-3))-math.log(1+math.exp(-5)))
sigmoid_cross_entropy_loss = solver.net.blobs['sigmoid_cross_entropy_loss'].data
print('sigmoid_cross_entropy_loss:', sigmoid_cross_entropy_loss)

# 12.5
euclidean_loss = solver.net.blobs['euclidean_loss'].data
print('euclidean_loss:', euclidean_loss)

solver.pt:

train_net: "train.pt"
base_lr: 0.1
display: 10
max_iter: 300
lr_policy: "step"
gamma: 0.1
momentum: 0.9
weight_decay: 0.0005
stepsize: 200
snapshot: 300
snapshot_prefix: "test"
solver_mode: CPU
device_id: 0

train.pt:

layer{
  name: "data"
  type: "Input"
  top: "data"
  top: "single_label"
  top: "full_label"
  input_param {
    shape{
      dim: 1
      dim: 2
    }
    shape{
      dim: 1
      dim: 1
    }
    shape{
      dim: 1
      dim: 2
    }
  }
}

layer {
  name: "euclidean_loss"
  type: "EuclideanLoss"
  bottom: "data"
  bottom: "full_label"
  top: "euclidean_loss"
}

layer{
  name: "sigmoid_cross_entropy_loss"
  type: "SigmoidCrossEntropyLoss"
  bottom: "data"
  bottom: "full_label"
  top: "sigmoid_cross_entropy_loss"
}

layer {
  name: "softmax_loss"
  type: "SoftmaxWithLoss"
  bottom: "data"
  bottom: "single_label"
  top: "softmax_loss"
}

運行結果:

x: [3,5], y:1,i.e. [0,1]
softmax_loss: 0.12692806
sigmoid_cross_entropy_loss: 3.0553026
euclidean_loss: 12.5


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM