多分類問(wèn)題的交叉熵
??在多分類問(wèn)題中,損失函數(shù)(loss function)為交叉熵(cross entropy)損失函數(shù)粥帚。對(duì)于樣本點(diǎn)(x,y)來(lái)說(shuō),y是真實(shí)的標(biāo)簽,在多分類問(wèn)題中岖赋,其取值只可能為標(biāo)簽集合labels. 我們假設(shè)有K個(gè)標(biāo)簽值,且第i個(gè)樣本預(yù)測(cè)為第k個(gè)標(biāo)簽值的概率為p_{i,k}瓮孙, 即p_{i,k} = \operatorname{Pr}(t_{i,k} = 1), 一共有N個(gè)樣本唐断,則該數(shù)據(jù)集的損失函數(shù)為
L_{\log}(Y, P) = -\log \operatorname{Pr}(Y|P) = - \frac{1}{N} \sum_{i=0}^{N-1} \sum_{k=0}^{K-1} y_{i,k} \log p_{i,k}
一個(gè)例子
??在Python的sklearn模塊中,提供了一個(gè)函數(shù)log_loss()來(lái)計(jì)算多分類問(wèn)題的交叉熵杭抠。再根據(jù)我們?cè)诓┛?a target="_blank" rel="nofollow">Sklearn中二分類問(wèn)題的交叉熵計(jì)算對(duì)log_loss()函數(shù)的源代碼的分析脸甘,我們不難利用上面的計(jì)算公式用自己的方法來(lái)實(shí)現(xiàn)交叉熵的求值。
??我們給出的例子如下:
y_true = ['1', '4', '5'] # 樣本的真實(shí)標(biāo)簽
y_pred = [[0.1, 0.6, 0.3, 0, 0, 0, 0, 0, 0, 0],
[0, 0.3, 0.2, 0, 0.5, 0, 0, 0, 0, 0],
[0.6, 0.3, 0, 0, 0, 0.1, 0, 0, 0, 0]
] # 樣本的預(yù)測(cè)概率
labels = ['0','1','2','3','4','5','6','7','8','9'] # 所有標(biāo)簽
在這個(gè)例子中偏灿,一個(gè)有3個(gè)樣本丹诀,標(biāo)簽為1,4,5,一共是10個(gè)標(biāo)簽翁垂,y_pred是對(duì)每個(gè)樣本的所有標(biāo)簽的預(yù)測(cè)值铆遭。
??接下來(lái)我們將會(huì)用log_loss()函數(shù)和自己的方法分別來(lái)實(shí)現(xiàn)這個(gè)例子的交叉熵的計(jì)算,完整的Python代碼如下:
from sklearn.metrics import log_loss
from sklearn.preprocessing import LabelBinarizer
from math import log
y_true = ['1', '4', '5'] # 樣本的真實(shí)標(biāo)簽
y_pred = [[0.1, 0.6, 0.3, 0, 0, 0, 0, 0, 0, 0],
[0, 0.3, 0.2, 0, 0.5, 0, 0, 0, 0, 0],
[0.6, 0.3, 0, 0, 0, 0.1, 0, 0, 0, 0]
] # 樣本的預(yù)測(cè)概率
labels = ['0','1','2','3','4','5','6','7','8','9'] # 所有標(biāo)簽
# 利用sklearn中的log_loss()函數(shù)計(jì)算交叉熵
sk_log_loss = log_loss(y_true, y_pred, labels=labels)
print("Loss by sklearn is:%s." %sk_log_loss)
# 利用公式實(shí)現(xiàn)交叉熵
# 交叉熵的計(jì)算公式網(wǎng)址為:
# http://scikit-learn.org/stable/modules/model_evaluation.html#log-loss
# 對(duì)樣本的真實(shí)標(biāo)簽進(jìn)行標(biāo)簽二值化
lb = LabelBinarizer()
lb.fit(labels)
transformed_labels = lb.transform(y_true)
# print(transformed_labels)
N = len(y_true) # 樣本個(gè)數(shù)
K = len(labels) # 標(biāo)簽個(gè)數(shù)
eps = 1e-15 # 預(yù)測(cè)概率的控制值
Loss = 0 # 損失值初始化
for i in range(N):
for k in range(K):
# 控制預(yù)測(cè)概率在[eps, 1-eps]內(nèi)沿猜,避免求對(duì)數(shù)時(shí)出現(xiàn)問(wèn)題
if y_pred[i][k] < eps:
y_pred[i][k] = eps
if y_pred[i][k] > 1-eps:
y_pred[i][k] = 1-eps
# 多分類問(wèn)題的交叉熵計(jì)算公式
Loss -= transformed_labels[i][k]*log(y_pred[i][k])
Loss /= N
print("Loss by equation is:%s." % Loss)
輸出的結(jié)果如下:
Loss by sklearn is:1.16885263244.
Loss by equation is:1.16885263244.
這說(shuō)明我們能夠用公式來(lái)自己實(shí)現(xiàn)交叉熵的計(jì)算了枚荣,是不是很神奇呢?
??多分類問(wèn)題的交叉熵計(jì)算是建立在二分類問(wèn)題的交叉熵計(jì)算的基礎(chǔ)上邢疙,有了我們對(duì)log_loss()函數(shù)的源代碼的研究棍弄,那就用自己的方法來(lái)實(shí)現(xiàn)多(二)分類問(wèn)題的交叉熵計(jì)算就不是問(wèn)題了~~
??本次分享到此結(jié)束望薄,歡迎大家交流~~
注意:本人現(xiàn)已開(kāi)通兩個(gè)微信公眾號(hào): 因?yàn)镻ython(微信號(hào)為:python_math)以及輕松學(xué)會(huì)Python爬蟲(chóng)(微信號(hào)為:easy_web_scrape), 歡迎大家關(guān)注哦~~