Sklearn中二分類問題的交叉熵計(jì)算

二分類問題的交叉熵

??在二分類問題中揭绑,損失函數(shù)(loss function)為交叉熵(cross entropy)損失函數(shù)坦报。對(duì)于樣本點(diǎn)(x,y)來說上煤,y是真實(shí)的標(biāo)簽休玩,在二分類問題中,其取值只可能為集合{0, 1}. 我們假設(shè)某個(gè)樣本點(diǎn)的真實(shí)標(biāo)簽為yt, 該樣本點(diǎn)取yt=1的概率為yp, 則該樣本點(diǎn)的損失函數(shù)為

-log(yt|yp)=-(ytlog(yp)+(1-yt)log(1-yp))

對(duì)于整個(gè)模型而言劫狠,其損失函數(shù)就是所有樣本點(diǎn)的損失函數(shù)的平均值拴疤。注意到,對(duì)于該損失函數(shù)独泞,其值應(yīng)該為非負(fù)值呐矾,因?yàn)閥p的取值在(0,1)之間。

自己實(shí)現(xiàn)的方法有問題懦砂?

??在Python的sklearn模塊中蜒犯,實(shí)現(xiàn)二分類問題的交叉熵?fù)p失函數(shù)為log_loss()。我們嘗試著運(yùn)行官網(wǎng)中給出的例子荞膘,同時(shí)罚随,用自己的方法實(shí)現(xiàn)該損失函數(shù),其Python代碼如下:

from sklearn.metrics import log_loss
from math import log # 自然對(duì)數(shù)為底

# 二分類的交叉熵?fù)p失函數(shù)
# 利用sklearn模塊的計(jì)算結(jié)果
y_true = [0, 0, 1, 1]
y_pred = [[.9, .1], [.8, .2], [.3, .7], [.01, .99]]
sk_log_loss = log_loss(y_true, y_pred)
print('Loss by sklearn: %s.'%sk_log_loss)

# 利用公式計(jì)算得到的結(jié)果
Loss = 0
for label, prob in zip(y_true, y_pred):
    Loss -= (label*log(prob[0])+(1-label)*log(prob[1]))

Loss = Loss/len(y_true)
print('Loss by equation: %s.'% Loss)

在y_pred中羽资,每個(gè)樣本點(diǎn)都對(duì)應(yīng)一組概率淘菩,如果我們把第一個(gè)概率作為樣本分類為0的概率,第二個(gè)概率作為樣本分類為1的概率屠升,我們就會(huì)得到以下的輸出結(jié)果:

Loss by sklearn: 0.1738073366910675.
Loss by equation: 2.430291498935543.

我們驚訝的發(fā)現(xiàn)潮改,兩種方法得到的損失函數(shù)值竟然是不一樣的「古可是汇在,貌似我們的計(jì)算公式也沒有出問題啊,這到底是怎么回事呢微服?
??這時(shí)候趾疚,我們最好的辦法是借助源代碼的幫助缨历,看看源代碼是怎么實(shí)現(xiàn)的,與我們的計(jì)算方法有什么不一樣糙麦。

研究sklearn中的log_loss()源代碼

??sklearn模塊中的log_loss()函數(shù)的源代碼地址為:https://github.com/scikit-learn/scikit-learn/blob/ed5e127b/sklearn/metrics/classification.py#L1576 辛孵。
??在具體分析源代碼之前,我們應(yīng)該注意以下幾點(diǎn)(這也是從源代碼中發(fā)現(xiàn)的):

  • 損失函數(shù)中的對(duì)數(shù)以自然常數(shù)e為底赡磅;
  • 預(yù)測(cè)概率的值有可能會(huì)出現(xiàn)0或1的情形魄缚,這在公式中是無意義的。因此焚廊,該代碼使用了numpy中的clip()函數(shù)冶匹,將預(yù)測(cè)概率控制在[eps, 1-eps]范圍內(nèi),其中eps為一個(gè)很小的數(shù),避免了上述問題的出現(xiàn)咆瘟。

??在log_loss()函數(shù)中嚼隘,參數(shù)為:y_true, y_pred, eps, normalize, sample_weight,labels,為了分析問題的方便袒餐,我們只考慮該函數(shù)在所有默認(rèn)參數(shù)取默認(rèn)值時(shí)的情形飞蛹。y_true為樣本的真實(shí)標(biāo)簽,y_pred為預(yù)測(cè)概率灸眼。
??對(duì)于樣本的真實(shí)標(biāo)簽y_true, 源代碼中的處理代碼為:

    lb = LabelBinarizer()

    if labels is not None:
        lb.fit(labels)
    else:
        lb.fit(y_true)
        
    transformed_labels = lb.transform(y_true)

    if transformed_labels.shape[1] == 1:
        transformed_labels = np.append(1 - transformed_labels,
                                       transformed_labels, axis=1)

也就說卧檐,當(dāng)我們的y_true為一維的時(shí)候,處理后的標(biāo)簽應(yīng)當(dāng)為二維的焰宣,比如說霉囚,我們輸入的y_true為[0,0,1,1],那么處理后的標(biāo)簽應(yīng)當(dāng)為:

[[1 0]
 [1 0]
 [0 1]
 [0 1]]

??對(duì)于預(yù)測(cè)概率匕积,源代碼中的處理過程為

    # Clipping
    y_pred = np.clip(y_pred, eps, 1 - eps)

    # If y_pred is of single dimension, assume y_true to be binary
    # and then check.
    if y_pred.ndim == 1:
        y_pred = y_pred[:, np.newaxis]
    if y_pred.shape[1] == 1:
        y_pred = np.append(1 - y_pred, y_pred, axis=1)

也就說盈罐,當(dāng)我們的y_true為一維的時(shí)候,處理后的標(biāo)簽應(yīng)當(dāng)為二維的闪唆,這跟處理樣本的真實(shí)標(biāo)簽y_true是一樣的暖呕。處理完y_true和y_pred后,之后就按照損失函數(shù)的公式得到計(jì)算值苞氮。

自己實(shí)現(xiàn)二分類問題的交叉熵計(jì)算

??在我們分析完log_loss的源代碼后,我們就能自己用公式來實(shí)現(xiàn)這個(gè)函數(shù)了瓤逼,其Python代碼如下:

from sklearn.metrics import log_loss
from math import log # 自然對(duì)數(shù)為底

# 二分類的交叉熵?fù)p失函數(shù)的計(jì)算

# y_true為一維笼吟,y_pred為二維
# 用sklearn的log_loss函數(shù)計(jì)算損失函數(shù)
y_true = [0,0,1,1]
y_pred = [[0.1,0.9], [0.2,0.8], [0.3,0.7], [0.01, 0.99]]
sk_log_loss = log_loss(y_true,y_pred)
print('Loss by sklearn: %s.'%sk_log_loss)

# 用公式自己實(shí)現(xiàn)損失函數(shù)的計(jì)算
Loss = 0
for label, prob in zip(y_true, y_pred):
    Loss -= ((1-label)*log(prob[0])+label*log(prob[1]))

Loss = Loss/len(y_true)
print('Loss by equation: %s.'% Loss)

# y_true為一維,y_pred為一維
# 用sklearn的log_loss函數(shù)計(jì)算損失函數(shù)
y_true = [0,0,1,1]
y_pred = [0.1, 0.2, 0.3, 0.01]
sk_log_loss = log_loss(y_true,y_pred)
print('Loss by sklearn: %s.'%sk_log_loss)

# 用公式自己實(shí)現(xiàn)損失函數(shù)的計(jì)算
Loss = 0
for label, prob in zip(y_true, y_pred):
    Loss -= ((1-label)*log(1-prob)+label*log(prob))

Loss = Loss/len(y_true)
print('Loss by equation: %s.'% Loss)

運(yùn)行該函數(shù)霸旗,輸出的結(jié)果為:

Loss by sklearn: 1.0696870713050948.
Loss by equation: 1.0696870713050948.
Loss by sklearn: 1.5344117643215158.
Loss by equation: 1.5344117643215158.

??這樣我們就用公式能自己實(shí)現(xiàn)二分類問題的交叉熵計(jì)算了贷帮,計(jì)算結(jié)果與sklearn的log_loss()函數(shù)一致。

感悟

??有空就得讀讀程序的源代碼诱告,不僅有助于我們解決問題撵枢,還能給我們很多啟示,比如log_loss()函數(shù)中的np.clip()函數(shù)的應(yīng)用,能很好地避免出現(xiàn)預(yù)測(cè)概率為0或1的情形锄禽。
??log_loss()函數(shù)的實(shí)現(xiàn)雖然簡(jiǎn)單潜必,但閱讀源代碼的樂趣是無窮的。以后也會(huì)繼續(xù)更新沃但,希望大家多多關(guān)注磁滚。

注意:本人現(xiàn)已開通兩個(gè)微信公眾號(hào): 因?yàn)镻ython(微信號(hào)為:python_math)以及輕松學(xué)會(huì)Python爬蟲(微信號(hào)為:easy_web_scrape), 歡迎大家關(guān)注哦~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宵晚,一起剝皮案震驚了整個(gè)濱河市垂攘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淤刃,老刑警劉巖晒他,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異逸贾,居然都是意外死亡陨仅,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門耕陷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掂名,“玉大人,你說我怎么就攤上這事哟沫〗让铮” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵嗜诀,是天一觀的道長(zhǎng)猾警。 經(jīng)常有香客問我,道長(zhǎng)隆敢,這世上最難降的妖魔是什么发皿? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮拂蝎,結(jié)果婚禮上穴墅,老公的妹妹穿的比我還像新娘。我一直安慰自己温自,他們只是感情好玄货,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悼泌,像睡著了一般松捉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上馆里,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天隘世,我揣著相機(jī)與錄音可柿,去河邊找鬼。 笑死丙者,一個(gè)胖子當(dāng)著我的面吹牛复斥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔓钟,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼永票,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了滥沫?” 一聲冷哼從身側(cè)響起侣集,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎兰绣,沒想到半個(gè)月后世分,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缀辩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年臭埋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臀玄。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瓢阴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出健无,到底是詐尸還是另有隱情荣恐,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布累贤,位于F島的核電站叠穆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏臼膏。R本人自食惡果不足惜硼被,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望渗磅。 院中可真熱鬧嚷硫,春花似錦、人聲如沸始鱼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽风响。三九已至,卻和暖如春丹禀,著一層夾襖步出監(jiān)牢的瞬間状勤,已是汗流浹背鞋怀。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留持搜,地道東北人密似。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像葫盼,于是被迫代替她去往敵國(guó)和親残腌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 該文章為轉(zhuǎn)載文章贫导,作者簡(jiǎn)介:汪劍抛猫,現(xiàn)在在出門問問負(fù)責(zé)推薦與個(gè)性化。曾在微軟雅虎工作孩灯,從事過搜索和推薦相關(guān)工作闺金。 T...
    名字真的不重要閱讀 5,221評(píng)論 0 3
  • 機(jī)器學(xué)習(xí)術(shù)語表 本術(shù)語表中列出了一般的機(jī)器學(xué)習(xí)術(shù)語和 TensorFlow 專用術(shù)語的定義。 A A/B 測(cè)試 (...
    yalesaleng閱讀 1,960評(píng)論 0 11
  • 以西瓜書為主線峰档,以其他書籍作為參考進(jìn)行補(bǔ)充败匹,例如《統(tǒng)計(jì)學(xué)習(xí)方法》,《PRML》等 第一章 緒論 1.2 基本術(shù)語 ...
    danielAck閱讀 4,504評(píng)論 0 6
  • 昨天放學(xué)后讥巡,多多和兩個(gè)好朋友在樓下玩掀亩,半小時(shí)后,怒氣沖沖地往回走了欢顷。好像是那倆一起玩槽棍,不響應(yīng)他的號(hào)召,所以生氣...
    luccy99閱讀 125評(píng)論 0 0
  • 每次洗完頭跟個(gè)金毛獅王一樣吱涉,頭發(fā)特別燥刹泄,特別想知道護(hù)發(fā)方法和一些好點(diǎn)兒的洗發(fā)水,護(hù)發(fā)素或者發(fā)膜怎爵、hufa精油之類的...
    張大溫柔dream閱讀 113評(píng)論 0 0