現在,有一個分類問題:

feature是2維的向量

目標類別有3種

一共有4個樣本:

(x_{11},x_{12},y_1), (x_{21},x_{22},y_2), (x_{31},x_{32},y_3), (x_{41},x_{42},y_4),

我們準備用一個只有一層的全連線神經網路來解決這個問題(使用多層神經網路推導太複雜,並且不利於理解,多層神經網路不是講清此問題的關鍵)。

首先,我們需要使用one-hot來表示目標類別(為什麼使用one-hot是另一個問題),所以,全連線神經網路的最後一層有三個數字。

哎呀!樣本數太多了寫起來很複雜,在計算loss時,只是簡單地對多個樣本產生的損失求均值,所以下面我們改一下問題:假設只有一個樣本,這個樣本的特徵為

(x_1,x_2)

,這個樣本經過全連線神經網路之後輸出為:

(y_{1}

,真實值為

(y_1,y_2,y_3)

y_1

不妨設這個樣本的類別為1,它的one-hot真實向量為(1,0,0)。

其實,在最後一層輸出的時候,我們需要使用softmax把

(y_1

進行歸一化。softmax的過程此處就省略了,

就當#FormatImgID_7#已經是softmax之後的結果了吧(因為softmax不是解釋此問題的關鍵)

下面看平方誤差:

min \quad z=\frac{1}{2}[(y_1-y_1

再看交叉熵誤差:

min \quad z=y_1log\frac{1}{y_1

其中,

y_1

表示真實值,

y_1

表示預測值。三部分是完全相同的,它們反向傳播時效果是相似的。所以,我們只分析

min \quad z=\frac{1}{2}(y_1-y_1

min\quad z=y_1log(y_1

對權值的影響,和

y_1

有關的三個權值是

w_{11},w_{12},w_{13}

,別的權值不用看。我們只分析損失z對

w_{11}

的影響。

對於平方誤差:

\frac{\partial z}{\partial w_{11}}=(y_1-y_1

我們想知道的是什麼?我們想知道的是

\Delta w_{11}=f(y_1-y_1

。也就是

w_{11}

調整的幅度和絕對誤差

y_1-y_1

之間的關係。

記絕對誤差

A=|y_1-y_1

因為我們使用了one-hot,所以

y_1

的真實值只能取0和1,而one-hot之後

y_1

的值必然在0到1之間。

y_1=1

時,

A=y_1-y_1

,代入

\frac{\partial z}{\partial w_{11}}

得到

\frac{\partial z}{\partial w_{11}}=A\times(y_1-A)\times(1-(y_1-A))\times x_1=A^2(1-A)\times x_1

y_1=0

A=y_1

\frac{\partial z}{\partial w_{11}}==-A^2(1-A)\times x_1

此式中,

x_1

是常量,不必關心,我們只看

A^2(1-A)

的形狀

這個函式長啥樣子?

import

matplotlib。pyplot

as

plt

import

numpy

as

np

A

=

np

linspace

0

1

100

plt

plot

A

A

**

2

*

1

-

A

))

plt

xlabel

“absolute error”

plt

ylabel

“$\delta w_

{11}

$”

plt

title

“$\delta w_

{11}

$=f(A)”

plt

show

()

為什麼使用交叉熵作為損失函式

隨著絕對誤差的增大,權值需要調整的幅度先變大後變小,這就導致當絕對誤差很大時,模型顯得“自暴自棄”不肯學習

隨著絕對誤差的增大,權值需要調整的幅度先變大後變小,這就導致當絕對誤差很大時,模型顯得“自暴自棄”不肯學習

對於交叉熵誤差:

\frac{\partial z}{\partial w_{11}}=y_1\times\frac{1}{y_1

可以看到,使用交叉熵之後,絕對誤差和需要調整的幅度成正比。

我們回過頭來比較平方損失和交叉熵損失的區別,會發現:

平方損失的“罪魁禍首”是sigmoid函式求導之後變成

y_1

,平白無故讓曲線變得非常複雜,如果前面能夠產生一個

\frac{1}{y_1

把後面多餘項“吃掉”多好

交叉熵的優勢就是:它求導之後只提供了一個

\frac{1}{y_1

去中和後面的導數。

以上都只是理論推導,那麼實際上到底是不是這麼回事呢?我們可以做個實驗:

y=sigmoid(w\times x+b)

,其中x=1,y=1。w始終在變化,b始終固定為0。2。在w變化過程中,我們記錄下絕對誤差和w的梯度。

import

matplotlib。pyplot

as

plt

import

numpy

as

np

import

tensorflow

as

tf

x

=

tf

placeholder

dtype

=

tf

float32

shape

=

(),

name

=

“x”

y

=

tf

placeholder

dtype

=

tf

float32

shape

=

(),

name

=

“y”

w

=

tf

Variable

0。8

b

=

tf

Variable

0。2

yy

=

tf

sigmoid

w

*

x

+

b

cross

=

-

y

*

tf

log

yy

mse

=

yy

-

y

**

2

cross_grad

=

tf

gradients

cross

w

b

])

mse_grad

=

tf

gradients

mse

w

b

])

abs_error

=

tf

abs

y

-

yy

with

tf

Session

()

as

sess

sess

run

tf

global_variables_initializer

())

w_value_list

=

np

linspace

-

8

8

100

cross_grad_w_list

mse_grad_w_list

abs_error_list

=

[],

[],

[]

for

w_value

in

w_value_list

sess

run

tf

assign

w

w_value

))

abs_error_value

cross_grad_w

_

),

mse_grad_w

_

=

sess

run

([

abs_error

cross_grad

mse_grad

],

feed_dict

=

{

x

1

y

1

})

cross_grad_w_list

append

cross_grad_w

mse_grad_w_list

append

mse_grad_w

abs_error_list

append

abs_error_value

plt

plot

abs_error_list

cross_grad_w_list

label

=

“cross_w=f(A)”

plt

plot

abs_error_list

mse_grad_w_list

label

=

“mse_w=f(A)”

plt

title

“why do we use cross_entropy?”

plt

legend

()

plt

show

()

為什麼使用交叉熵作為損失函式

實驗證明,理論推導是正確的:交叉熵使得梯度與絕對誤差成正比,二範數導致梯度變得扭曲

參考資料