日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

KL散度、交叉熵与JS散度数学公式以及代码例子

發(fā)布時(shí)間:2023/12/14 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 KL散度、交叉熵与JS散度数学公式以及代码例子 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

KL散度、交叉熵與JS散度數(shù)學(xué)公式以及代碼例子

1.1 KL 散度概述

KL 散度 ,Kullback-Leibler divergence,(也稱相對(duì)熵,relative entropy)是概率論和信息論中十分重要的一個(gè)概念,是兩個(gè)概率分布(probability distribution)間差異的非對(duì)稱性度量。

對(duì)離散概率分布的 KL 散度 計(jì)算公式為:
KL(p∣∣q)=∑p(x)log?p(x)q(x)(1)KL(p||q)=\sum p(x)\log{{p(x)}\over{q(x)}} \tag{1} KL(p∣∣q)=p(x)logq(x)p(x)?(1)

對(duì)連續(xù)概率分布的 KL 散度 計(jì)算公式為:
KL(p∣∣q)=∫p(x)log?p(x)q(x)dx(2)KL(p||q)=\int p(x)\log {{p(x)}\over{q(x)}}dx \tag{2} KL(p∣∣q)=p(x)logq(x)p(x)?dx(2)

一般情況下,我們得到的數(shù)據(jù)都是離散的。

KL 散度 的重要性質(zhì):

  • KL 散度 的結(jié)果是非負(fù)的。
  • KL 散度 是非對(duì)稱的,即 KL(p∣∣q)!=KL(q∣∣p)KL(p||q) \ !=\ KL(q||p)KL(p∣∣q)?!=?KL(q∣∣p)

具體內(nèi)容參考 [1] 《深度學(xué)習(xí)輕松學(xué)》。

1.2 KL 散度計(jì)算方法的代碼實(shí)現(xiàn)

1.2.1 自己編寫代碼

請結(jié)合 公式 (1) 理解以下代碼:

import numpy as np import mathdef KL(p,q):# p,q 為兩個(gè) list,表示對(duì)應(yīng)取值的概率 且 sum(p) == 1 ,sum(q) == 1return sum(_p*math.log(_p/_q) for (_p,_q) in zip(p,q) if _p != 0 )P = [0.2, 0.4, 0.4] Q = [0.4, 0.2, 0.4]print(KL(P,Q))

輸出內(nèi)容為:

0.13862943611198905

計(jì)算過程KL(P,Q)=0.2?log?0.20.4+0.4?log?0.40.2+0.4?log?0.40.4=0.13862943611198905KL(P,Q) = 0.2*\log{{0.2}\over{0.4}}+0.4*\log{{0.4}\over{0.2}}+0.4*\log{{0.4}\over{0.4}}=0.13862943611198905KL(P,Q)=0.2?log0.40.2?+0.4?log0.20.4?+0.4?log0.40.4?=0.13862943611198905

當(dāng)然如果是 二分類問題 計(jì)算過程也是一樣的。

import numpy as np import mathdef KL(p,q):# p,q 為兩個(gè) list,表示對(duì)應(yīng)取值的概率 且 sum(p) == 1 ,sum(q) == 1return sum(_p*math.log(_p/_q) for (_p,_q) in zip(p,q) if _p != 0 )P = [0, 1] Q = [0.4,0.6]print(KL(P,Q))

輸出結(jié)果為:

0.5108256237659907

可以自己復(fù)制粘貼填寫更多測試數(shù)值,需要 保證

  • P 中每一組的各項(xiàng)的和為 1
  • Q 中每一組各項(xiàng)的和為 1
  • Q 中每一組不允許出現(xiàn) 0

注意: 以上內(nèi)容只考慮維度為 1 的情況,如 P=[[0.1,0.2,0.7],[0.2,0.3,0.5]] 這種情況沒有考慮到。

1.2.2 使用已存在的庫 scipy

from scipy import statsP = [0.2, 0.4, 0.4] Q = [0.4, 0.2, 0.4] stats.entropy(P,Q)

輸出內(nèi)容為:

0.13862943611198905

和上面的例子一樣,可以測試那些數(shù)據(jù)。

2.1 交叉熵基本概述

交叉熵(Cross Entropy)是 Shannon 信息論中一個(gè)重要概念,主要用于度量兩個(gè)概率分布間的差異性信息。

對(duì) 二分類 任務(wù)的 交叉熵 計(jì)算公式為:

CrossEntropy(y,y^)=?(y?log?(y^)+(1?y)?log?(1?y^))(3)Cross Entropy\ (y, {\hat y}) = -(y*\log(\hat y)+(1-y)*\log(1-\hat y)) \tag{3} CrossEntropy?(y,y^?)=?(y?log(y^?)+(1?y)?log(1?y^?))(3)
其中,yyy 可以理解為數(shù)據(jù)集中的 label,也就是接下來例子中的 ytruey_{true}ytrue?;而 y^\hat yy^? 可以理解與模型的預(yù)測標(biāo)簽,也就是接下來的例子中的 ypredy_{pred}ypred?

注意: 如果二分類問題時(shí),yyy 的取值并非 [0,1] 兩種這種正常模式,需要分別求和再求均值,這一部分內(nèi)容將會(huì)在后面 2.3 進(jìn)行討論。

對(duì) 多分類 任務(wù)的交叉熵計(jì)算公式為:

CrossEntropy(y,y^)=∑y?log?(1y^)(4)Cross Entropy\ (y, {\hat y}) = \sum y*\log ({{1}\over{\hat y}}) \tag{4} CrossEntropy?(y,y^?)=y?log(y^?1?)(4)
公式 4 可以寫成如下格式:

CrossEntropy(y,y^)=?∑y?log?(y^)(5)Cross Entropy\ (y, {\hat y}) = -\sum y*\log ({\hat y}) \tag{5} CrossEntropy?(y,y^?)=?y?log(y^?)(5)

其中, 多分類 任務(wù)的計(jì)算公式同樣適用于 二分類 ,因?yàn)槎诸惾蝿?wù)直接等于兩個(gè)概率運(yùn)算的和,所以沒必要加 ∑\sum 符號(hào)。

2.2 交叉熵計(jì)算方法的代碼實(shí)現(xiàn)

2.2.1 自己編寫代碼

參考 公式4 ,編寫代碼比較簡單。

import mathdef CE(p,q):# p,q 為兩個(gè) list,表示對(duì)應(yīng)取值的概率 且 sum(p) == 1 ,sum(q) == 1return sum(_p*math.log( 1 /_q) for (_p,_q) in zip(p,q) if _q != 0 )P = [0.,1.] Q = [0.6,0.4]print(CE(P,Q))

計(jì)算過程CE(P,Q)=0?log?(10.6)+1?log?(10.4)=log?(2.5)=0.91629073187415506518352721176801CE(P, Q)=0*\log({{1}\over{0.6}})+1*\log({{1}\over{0.4}})=\log(2.5)=0.91629073187415506518352721176801CE(P,Q)=0?log(0.61?)+1?log(0.41?)=log(2.5)=0.91629073187415506518352721176801

輸出內(nèi)容為:

0.9162907318741551

注意對(duì)比前文中對(duì) KL 的實(shí)現(xiàn)的代碼,非常相似,除了函數(shù)名就改動(dòng)兩個(gè)地方。

根據(jù) 公式5,代碼實(shí)現(xiàn)如下:

import mathdef CE(p,q):# p,q 為兩個(gè) list,表示對(duì)應(yīng)取值的概率 且 sum(p) == 1 ,sum(q) == 1return -sum(_p*math.log(_q) for (_p,_q) in zip(p,q) if _q != 0 )P = [0.,1.] Q = [0.6,0.4]print(CE(P,Q))

輸出結(jié)果為:

0.916290731874155

2.2.1 使用 tensorflow2

主要是因?yàn)槭褂?tensorflow 的時(shí)候可能會(huì)用到這個(gè)函數(shù),所以特地在這里介紹一下計(jì)算過程。

注意 這里只適合 Binary 這種情況,也就是說標(biāo)簽只是 0 與 1 兩種。具體參考 [3]

這里直接上例子,然后解釋計(jì)算過程:

import tensorflow as tfy_true = [0., 1.] y_pred = [0.6, 0.4] bce = tf.keras.losses.BinaryCrossentropy() bce(y_true, y_pred).numpy()

輸出內(nèi)容為:

0.9162905

在官方文檔中給出的例子有兩組數(shù)據(jù),代碼如下:

import tensorflow as tfy_true = [[0., 1.], [0., 1.]] y_pred = [[0.6, 0.4], [0.4, 0.6]] # Using 'auto'/'sum_over_batch_size' reduction type. bce = tf.keras.losses.BinaryCrossentropy() bce(y_true, y_pred).numpy()

輸出內(nèi)容為:

0.71355796

這種情況只是分別求兩組結(jié)果,再進(jìn)行平均即可。

2.3 當(dāng)測試數(shù)據(jù)為全0或全1 的二分類時(shí)

上面的公式以及自己編寫的代碼中,都沒有考慮到當(dāng)測試數(shù)據(jù)為全0 或全 1 這種情況,接下來在這里討論,在二分類問題中,應(yīng)該如何計(jì)算結(jié)果。

CrossEntropy(y,y^)=?(y?log?(y^)+(1?y)?log?(1?y^))(3)Cross Entropy\ (y, {\hat y}) = -(y*\log(\hat y)+(1-y)*\log(1-\hat y)) \tag{3} CrossEntropy?(y,y^?)=?(y?log(y^?)+(1?y)?log(1?y^?))(3)
公式3 所示,在 輸入數(shù)據(jù)的 yyy 為 [0,1] 兩種時(shí),使用 公式3,4,5 計(jì)算都可以。但是如果輸入數(shù)據(jù)的 yyy 全部為 0 的時(shí)候,公式3 與公式4 則不適用。

這個(gè)時(shí)候需要使用 公式3 進(jìn)行計(jì)算,并且同樣需要做一次求均值,如 公式6 所示。

CrossEntropy(y,y^)=?1n∑i=1n(yi?log?(y^i)+(1?yi)?log?(1?y^i))(6)Cross Entropy\ (y, {\hat y}) = -{{1}\over{n}}\sum_{i=1}^n(y_i*\log(\hat y_i)+(1-y_i)*\log(1-\hat y_i)) \tag{6} CrossEntropy?(y,y^?)=?n1?i=1n?(yi??log(y^?i?)+(1?yi?)?log(1?y^?i?))(6)

對(duì)應(yīng)的代碼實(shí)現(xiàn)如下:

import mathdef CE(p,q):return -sum((_p*math.log(_q)+(1-_p)*math.log(1-_q) )for (_p,_q) in zip(p,q) if _q != 0 )/len(p)P = [0.,0.] Q = [0.6,0.4]print(CE(P,Q))

輸出結(jié)果為:

0.7135581778200728

計(jì)算過程CE(p,q)=?12((0?log?0.6+1?log?0.4)+(0?log?0.4+1?log?0.6))=?12log?0.24=0.71355817782007287419452065403584CE(p,q)=-{{1}\over{2}}((0*\log 0.6 + 1*\log 0.4)+(0*\log 0.4+1*\log0.6))=-{{1}\over{2}}\log0.24=0.71355817782007287419452065403584CE(p,q)=?21?((0?log0.6+1?log0.4)+(0?log0.4+1?log0.6))=?21?log0.24=0.71355817782007287419452065403584

對(duì)應(yīng)的 tensorflow2 代碼如下:

import tensorflow as tfy_true = [0., 0.] y_pred = [0.4, 0.6]bce = tf.keras.losses.BinaryCrossentropy() bce(y_true, y_pred).numpy()

輸出結(jié)果為:

0.71355796

如果測試數(shù)據(jù)為 [1.,1.] 的時(shí)候,輸出結(jié)果是相同的。

3.1 JS 散度概述

JS 散度 Jensen-Shannon divergence 用于描述兩個(gè)概率分布的相似程度。和上面的 KL 的描述一致的話,JS 散度是兩個(gè)概率分布間差異的對(duì)稱性度量。

JS 散度的求解公式如下:
JS(P∣∣Q)=12KL(P∣∣P+Q2)+12KL(Q∣∣P+Q2)(7)JS(P \ ||\ Q ) = {{1}\over{2}}KL(P\ ||\ {{P+Q}\over{2}})+{{1}\over{2}}KL(Q \ ||\ {{P+Q}\over{2}}) \tag{7} JS(P?∣∣?Q)=21?KL(P?∣∣?2P+Q?)+21?KL(Q?∣∣?2P+Q?)(7)

很明顯,等式是對(duì)稱成立的,也就是說 JS(P∣∣Q)==JS(Q∣∣P)JS(P \ || \ Q) == JS(Q\ ||\ P)JS(P?∣∣?Q)==JS(Q?∣∣?P)

3.2 JS散度計(jì)算方法的代碼實(shí)現(xiàn)

公式7 是通過計(jì)算 KL 散度來計(jì)算 JS 散度的,因此代碼實(shí)現(xiàn)需要用到前面的 KL 散度,具體實(shí)現(xiàn)如下:

實(shí)驗(yàn) 1

import mathdef KL(p,q):# p,q 為兩個(gè) list,表示對(duì)應(yīng)取值的概率 且 sum(p) == 1 ,sum(q) == 1return sum(_p*math.log(_p/_q) for (_p,_q) in zip(p,q) if _p != 0 )def JS(p,q):M = [0.5*(_p +_q) for (_p,_q) in zip(p,q)]return 0.5*(KL(p,M)+KL(q,M))P = [0.,1.] Q = [0.6,0.4]print(JS(P,Q)) print(JS(Q,P))

輸出內(nèi)容為:

0.27435846855026524 0.27435846855026524

可以看出 JS(P,Q)JS(P,Q)JS(P,Q)JS(Q,P)JS(Q,P)JS(Q,P) 相等。


實(shí)驗(yàn) 2

接下來看一下兩個(gè)概率分布差異大小在 JS 值上的直觀反映:

import mathdef KL(p,q):# p,q 為兩個(gè) list,表示對(duì)應(yīng)取值的概率 且 sum(p) == 1 ,sum(q) == 1return sum(_p*math.log(_p/_q) for (_p,_q) in zip(p,q) if _p != 0 )def JS(p,q):M = [0.5*(_p +_q) for (_p,_q) in zip(p,q)]return 0.5*(KL(p,M)+KL(q,M))P = [0.,1.] Q = [0.01,0.99]print(JS(P,Q))P = [0.,1.] Q = [0.1,0.9]print(JS(P,Q))P = [0.,1.] Q = [0.5,0.5]print(JS(P,Q))P = [0.,1.] Q = [0.9,0.1]print(JS(P,Q))P = [0.,1.] Q = [0.99,0.01]print(JS(P,Q))

輸出內(nèi)容如下:

0.003478298769743019 0.03597375665014844 0.21576155433883565 0.5255973270178643 0.665096412549155

可以看出,最開始的數(shù)據(jù)兩個(gè)概率分布是非常接近的,因?yàn)?JS 值比較小,接著兩個(gè)概率分布差異越來越多,JS 值也越來越大。


實(shí)驗(yàn) 3

接著使用相同的數(shù)據(jù),測試一下 KL 值的大小與概率分布的關(guān)系,因?yàn)?KL 計(jì)算是非對(duì)稱的,因此每次需要輸出兩個(gè)結(jié)果。

import mathdef KL(p,q):# p,q 為兩個(gè) list,表示對(duì)應(yīng)取值的概率 且 sum(p) == 1 ,sum(q) == 1return sum(_p*math.log(_p/_q) for (_p,_q) in zip(p,q) if _p != 0 )P = [0.1,0.9] Q = [0.01,0.99]print(KL(P,Q),KL(Q,P))P = [0.1,0.9] Q = [0.1,0.9]print(KL(P,Q),KL(Q,P))P = [0.1,0.9] Q = [0.5,0.5]print(KL(P,Q),KL(Q,P))P = [0.1,0.9] Q = [0.9,0.1]print(KL(P,Q),KL(Q,P))P = [0.1,0.9] Q = [0.99,0.01]print(KL(P,Q),KL(Q,P))

輸出結(jié)果為:

0.14447934747551233 0.07133122707634103 0.0 0.0 0.3680642071684971 0.5108256237659907 1.7577796618689758 1.7577796618689758 3.8205752275831846 2.224611312865836

可以看出,當(dāng) P 和 Q 相同分布時(shí),KL 散度為 0;KL 散度隨著分布差異的增大而增大,隨著分布差異的減小而減小。


小結(jié)

根據(jù)以上實(shí)驗(yàn),可以看出:

  • 隨著兩個(gè)概率分布差異的增大,KL 散度與 JS 散度的數(shù)值將增大;反之亦然。
  • 隨著兩個(gè)概率分布差異的增大,KL 散度的增大時(shí)不均勻的,而 JS 散度的增大時(shí)均勻的。
  • KL 散度的不對(duì)稱性可能帶來一些潛在的問題。

4. 總結(jié)

本文總結(jié)了 KL 散度、交叉熵以及 JS 散度數(shù)學(xué)公式以及一些性質(zhì),并且通過 python 代碼實(shí)現(xiàn)。在閱讀論文或?qū)嶋H編碼中,如果忘記了這方面的內(nèi)容,可以考慮參考一下。

如有任何疑問,歡迎留言評(píng)論!

感謝您的閱讀!如果有幫助到您的話,歡迎點(diǎn)贊 + 關(guān)注 !感謝!

Smileyan
2021.3.28 22:15

[1] 《深度學(xué)習(xí)輕松學(xué)》核心算法與視覺實(shí)踐 馮超著 電子工業(yè)出版社 P33
[2] 《相對(duì)熵(KL散度)計(jì)算過程》
[3] tensorlflow文檔 tf.keras.metrics.BinaryCrossentropy
[4] 《熵與信息增益》
[5] 百度百科 相對(duì)熵 KL 散度
[6] 百度百科 交叉熵
[7] 熵與信息增益
[8] 二分類、多分類交叉熵的計(jì)算
[9] tensorflow BinaryCrossentropy 源碼
[10] 知乎 為什么交叉熵(cross-entropy)可以用于計(jì)算代價(jià)?
[11] 交叉熵、相對(duì)熵(KL散度)、JS散度和Wasserstein距離(推土機(jī)距離)
[12] tensorflow官網(wǎng) KL公式

總結(jié)

以上是生活随笔為你收集整理的KL散度、交叉熵与JS散度数学公式以及代码例子的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。