1. 【機(jī)器學(xué)習(xí)】如何在交叉驗證中使用SHAP?

        共 6813字,需瀏覽 14分鐘

         ·

        2024-05-28 11:00

        在許多情況下,機(jī)器學(xué)習(xí)模型比傳統(tǒng)線性模型更受歡迎,因為它們具有更好的預(yù)測性能和處理復(fù)雜非線性數(shù)據(jù)的能力。然而,機(jī)器學(xué)習(xí)模型的一個常見問題是它們?nèi)狈山忉屝?。例如,集成方法如XGBoost和隨機(jī)森林將許多個體學(xué)習(xí)器的結(jié)果組合起來生成結(jié)果。盡管這通常會帶來更好的性能,但它使得難以知道數(shù)據(jù)集中每個特征對輸出的貢獻(xiàn)。為了解決這個問題,可解釋人工智能(explainable AI, xAI)被提出并越來越受歡迎。xAI領(lǐng)域旨在解釋這些不可解釋的模型(所謂的黑匣子模型)如何進(jìn)行預(yù)測,實現(xiàn)最佳的預(yù)測準(zhǔn)確性和可解釋性。這樣做的動機(jī)在于,許多機(jī)器學(xué)習(xí)的真實應(yīng)用場景不僅需要良好的預(yù)測性能,還要解釋生成結(jié)果的方式。例如,在醫(yī)療領(lǐng)域,可能會根據(jù)模型做出的決策而失去或挽救生命,因此了解決策的驅(qū)動因素非常重要。此外,能夠識別重要變量對于識別機(jī)制或治療途徑也很有幫助。最受歡迎、最有效的xAI技術(shù)之一是SHAP。

        1. 介紹

        SHAP概念由Lundberg & Lee于2017年提出,但實際上是基于早在此之前存在的博弈論Shapley值。

        簡而言之,SHAP值通過計算每個特征的邊際貢獻(xiàn)來工作,方法是在許多有和沒有該特征的模型中查看(每個觀察值的)預(yù)測,根據(jù)每個這些減少特征集模型中的權(quán)重計算這種貢獻(xiàn),然后總結(jié)所有這些實例的加權(quán)貢獻(xiàn)。

        在這里,簡單地說:對于一個觀察值而言,SHAP值的絕對值越大,影響預(yù)測的作用就越大。因此,對于給定特征的所有觀察值的絕對SHAP值的平均值越大,該特征就越重要。

        使用SHAP庫在Python中實現(xiàn)SHAP值很容易,許多在線教程已經(jīng)解釋了如何實現(xiàn)。然而,我發(fā)現(xiàn)所有整合SHAP值到Python代碼的指南都存在兩個主要缺陷。

        第一點是:大多數(shù)指南在基本的訓(xùn)練/測試拆分上使用SHAP值,但不在交叉驗證上使用(見圖1)

        使用交叉驗證可以更好地了解結(jié)果的普適性,而基本的訓(xùn)練/測試拆分的結(jié)果很容易受到數(shù)據(jù)劃分方式的影響而發(fā)生劇烈變化。正如我在最近的“營養(yǎng)研究中的機(jī)器學(xué)習(xí)”(https://doi.org/10.1093/advances/nmac103)文章中所解釋的那樣,除非你處理的數(shù)據(jù)集非常龐大,否則交叉驗證幾乎總是優(yōu)于訓(xùn)練/測試拆分。

        圖1. 機(jī)器學(xué)習(xí)中的不同評估程序。

        另一個缺點是:我遇到的所有指南都沒有使用多次交叉驗證來推導(dǎo)其SHAP值

        雖然交叉驗證比簡單的訓(xùn)練/測試拆分有很大的改進(jìn),但最好每次都使用不同的數(shù)據(jù)拆分來重復(fù)多次。特別是在數(shù)據(jù)集較小的情況下,結(jié)果可能會因數(shù)據(jù)如何拆分而大為不同。這就是為什么經(jīng)常建議重復(fù)100次交叉驗證以對結(jié)果有信心的原因。

        為了解決這些缺點,我決定編寫一些代碼來實現(xiàn)它。本文將向您展示如何獲取多次重復(fù)交叉驗證的SHAP值,并結(jié)合嵌套交叉驗證方案。對于我們的模型數(shù)據(jù)集,我們將使用波士頓住房數(shù)據(jù)集,并選擇功能強大但不可解釋的隨機(jī)森林算法。

        2. SHAP實踐

        2.1. SHAP值的基本實現(xiàn)

        無論何時,當(dāng)使用各種循環(huán)構(gòu)建代碼時,通常最好從最內(nèi)部的循環(huán)開始向外工作。試圖從外部開始構(gòu)建代碼,按運行順序構(gòu)建代碼,容易混淆且在出現(xiàn)問題時更難進(jìn)行故障排除。

        因此,我們從SHAP值的基本實現(xiàn)開始。

        我假設(shè)您熟悉SHAP的一般用途和其實現(xiàn)代碼的外觀,因此我不會花太長時間進(jìn)行說明。

        我會在代碼中添加注釋,因此您可以檢查這些注釋,如果您仍然不確定,那么請查看介紹中的鏈接或庫的文檔。我還會在需要時導(dǎo)入庫,而不是在開始時一次性導(dǎo)入所有庫,這樣有助于理解。

        2.2. 將交叉驗證與SHAP值相結(jié)合

        我們經(jīng)常使用sklearncross_val_score或類似方法自動實現(xiàn)交叉驗證。

        但是這種方法的問題在于所有過程都在后臺進(jìn)行,我們無法訪問每個fold中的數(shù)據(jù)。

        當(dāng)然,如果我們想獲得所有數(shù)據(jù)點的SHAP值,則需要訪問每個數(shù)據(jù)點(請記住,每個數(shù)據(jù)點在測試集中僅用一次,在訓(xùn)練中使用k-1次)。為了解決這個問題,我們可以將KFold.split結(jié)合使用。

        通過循環(huán)遍歷我們的KFold對象,并使用.split方法,我們可以獲取每個折疊的訓(xùn)練和測試索引。

        在這里,折疊是一個元組,其中fold[0]是每個折疊的訓(xùn)練索引,fold[1]是測試索引。

        現(xiàn)在,我們可以使用此方法從原始數(shù)據(jù)幀中自己選擇訓(xùn)練和測試數(shù)據(jù),從而提取所需的信息。

        我們通過創(chuàng)建新的循環(huán)來完成此操作,獲取每個折疊的訓(xùn)練和測試索引,然后像通常一樣執(zhí)行回歸和 SHAP 過程。

        然后,我們只需在循環(huán)外添加一個空列表來跟蹤每個樣本的 SHAP 值,然后在循環(huán)結(jié)束時將其添加到列表中。我使用 #-#-# 來表示這些新添加的內(nèi)容。

        現(xiàn)在,我們針對每個樣本都有SHAP值,而不僅僅是數(shù)據(jù)的一個測試分割樣本,我們可以使用SHAP庫輕松繪制這些值。

        我們首先需要更新X的索引,以匹配它們出現(xiàn)在每個折疊的每個測試集中的順序,否則顏色編碼的特征值會全部錯誤。

        請注意,我們在summary_plot函數(shù)中重新排序X,以便我們不保存我們對原始X數(shù)據(jù)幀的更改。

        上面,是帶交叉驗證的SHAP,包括所有數(shù)據(jù)點,所以比之前的點密集。

        從圖中可以看出,與僅使用訓(xùn)練/測試拆分時相比,現(xiàn)在有更多的數(shù)據(jù)點(實際上是全部數(shù)據(jù)點)。

        這樣,我們的過程已經(jīng)得到了改善,因為我們可以利用整個數(shù)據(jù)集而不僅僅是一部分。

        但我們?nèi)匀徊磺宄€(wěn)定性。即,如果數(shù)據(jù)被分割得不同,結(jié)果會如何改變。

        幸運的是,我們可以在下面編寫代碼來解決這個問題。

        2.3. 重復(fù)交叉驗證

        使用交叉驗證可以大大提高工作的魯棒性,尤其是在數(shù)據(jù)集較小的情況下。然而,如果我們真的想做好數(shù)據(jù)科學(xué),交叉驗證應(yīng)該在許多不同的數(shù)據(jù)拆分上重復(fù)執(zhí)行。

        首先,我們現(xiàn)在需要考慮的不僅僅是每個折疊的SHAP值,還需要考慮每個重復(fù)和每個折疊的SHAP值,然后將它們合并到一個圖表中進(jìn)行繪制。

        在Python中,字典是強大的工具,這就是我們將用來跟蹤每個樣本在每個折疊中的SHAP值。

        首先,我們決定要執(zhí)行多少次交叉驗證重復(fù),并建立一個字典來存儲每個重復(fù)中每個樣本的SHAP值。

        這是通過循環(huán)遍歷數(shù)據(jù)集中的所有樣本并在我們的空字典中為它們創(chuàng)建一個鍵來實現(xiàn)的,然后在每個樣本中創(chuàng)建另一個鍵來表示交叉驗證重復(fù)。

        接下來,我們在現(xiàn)有代碼中添加一些新行,使我們能夠重復(fù)交叉驗證過程CV_repeats次,并將每次重復(fù)的SHAP值添加到我們的字典中。

        這很容易實現(xiàn),只需更新代碼末尾的一些行,以便我們不再將每個樣本的SHAP值列表附加到列表中,而是更新字典。

        注:收集每個折疊的測試分?jǐn)?shù)可能也很重要,盡管我們在這里不這樣做,因為重點是使用SHAP值,但這可以通過添加另一個字典輕松更新,其中CV重復(fù)是鍵,測試分?jǐn)?shù)是值。

        代碼看起來像這樣,其中 #-#-# 表示對現(xiàn)有代碼的更新:

        為了可視化,假設(shè)我們想要檢查索引號為10的樣本的第五個交叉驗證重復(fù),我們只需寫:

        其中第一個方括號代表樣本編號,第二個代表重復(fù)次數(shù)。輸出是在第五次交叉驗證重復(fù)后,樣本編號為10的X每列的SHAP值。

        要查看一個個體所有交叉驗證重復(fù)的SHAP值,只需在第一個方括號中鍵入數(shù)字即可:

        然而,這對我們來說并沒有太多用處(除了故障排除目的)。我們真正需要的是繪制一個圖表來可視化這些數(shù)據(jù)。

        我們首先需要對每個樣本的交叉驗證重復(fù)進(jìn)行SHAP值的平均值計算,以便繪制一個值(如果您愿意,您也可以使用中位數(shù)或其他統(tǒng)計數(shù)據(jù))。取平均值很方便,但可能會隱藏數(shù)據(jù)內(nèi)部的可變性,這也是我們需要了解的。因此,雖然我們正在取平均值,但我們還將獲得其他統(tǒng)計數(shù)據(jù),例如最小值,最大值和標(biāo)準(zhǔn)偏差:

        以上代碼表示:對于原始數(shù)據(jù)框中的每個樣本索引,從每個 SHAP 值列表(即每個交叉驗證重復(fù))中制作數(shù)據(jù)框。該數(shù)據(jù)框?qū)⒚總€交叉驗證重復(fù)作為行,每個 X 變量作為列。我們現(xiàn)在使用相應(yīng)的函數(shù)和使用 axis = 1 以列為單位執(zhí)行計算,對每列取平均值、標(biāo)準(zhǔn)差、最小值和最大值。然后我們將每個轉(zhuǎn)換為數(shù)據(jù)框。

        現(xiàn)在,我們只需像繪制通常的值一樣繪制平均值。我們也不需要重新排序索引,因為我們從字典中取出SHAP值,它與X的順序相同。

        上圖是重復(fù)交叉驗證多次后的平均SHAP值。

        由于我們的結(jié)果已經(jīng)經(jīng)過多次交叉驗證的平均化,因此它們比僅執(zhí)行一次簡單的訓(xùn)練/測試拆分更加健壯和可信。

        但是,如果您比較之前和之后的圖形,并且除了額外的數(shù)據(jù)點外,幾乎沒有什么變化,您可能會感到失望。但是不要忘記,我們使用的是一個模型數(shù)據(jù)集,該數(shù)據(jù)集非常整潔,具有良好的特性,并且與結(jié)果具有強烈的關(guān)系。在不那么理想的情況下,像重復(fù)交叉驗證這樣的技術(shù)將揭示實際數(shù)據(jù)在結(jié)果和特征重要性方面的不穩(wěn)定性。

        如果我們想要進(jìn)一步增強我們的結(jié)果(當(dāng)然我們想要),我們可以添加一些圖表來了解我們建議的特征重要性的變異性。這很重要,因為每個樣本的平均SHAP值可能會掩蓋它們在數(shù)據(jù)不同分割下的變化程度。

        為了做到這一點,我們必須將我們的數(shù)據(jù)幀轉(zhuǎn)換為長格式,之后我們可以使用 seaborn 庫來制作一個 catplot

        上圖,我們可以看到每個樣本的每次CV重復(fù)中的范圍(最大值-最小值)。理想情況下,我們希望   軸上的值盡可能小,因為這意味著更一致的特征重要性。

        我們應(yīng)該謹(jǐn)記,這種可變性也對絕對特征重要性敏感,即被認(rèn)為更重要的特征自然會具有更大范圍的數(shù)據(jù)點。我們可以通過對數(shù)據(jù)進(jìn)行縮放來部分地解決這個問題。

           的圖與   的圖相似,但現(xiàn)在每個觀測值都按每個特征的平均值縮放。

        請注意LSTAT和RM這兩個最重要的特征看起來有多不同?,F(xiàn)在,我們可以更好地反映按特征的整體重要性縮放的可變性,這可能更或不更相關(guān),具體取決于我們的研究問題。

        我們可以根據(jù)我們收集的其他統(tǒng)計數(shù)據(jù),例如標(biāo)準(zhǔn)差,想出類似的情節(jié)。

        2.4. 嵌套交叉驗證

        所有這些都很好,但有一件事情缺失了:我們的隨機(jī)森林是默認(rèn)模式。雖然它在這個數(shù)據(jù)集上表現(xiàn)得很好,但在其他情況下可能不是這樣。此外,為什么我們不應(yīng)該嘗試最大化我們的結(jié)果呢?

        我們應(yīng)該注意不要陷入機(jī)器學(xué)習(xí)示例中似乎很常見的陷阱,即在測試集中也存在的數(shù)據(jù)上優(yōu)化模型超參數(shù)。通過簡單的訓(xùn)練/測試拆分,我們可以輕松避免這種情況。只需在訓(xùn)練數(shù)據(jù)上優(yōu)化超參數(shù)即可。

        但是一旦交叉驗證進(jìn)入方程式,這個概念似乎被忘記了。實際上,人們經(jīng)常使用交叉驗證來優(yōu)化超參數(shù),然后使用交叉驗證對模型進(jìn)行評分。在這種情況下,發(fā)生了數(shù)據(jù)泄漏,我們的結(jié)果將會(即使只是稍微)過于樂觀。

        嵌套交叉驗證是我們的解決方案。它涉及在我們正常的交叉驗證方案(這里稱為“外循環(huán)”)中取出每個訓(xùn)練折疊,并使用訓(xùn)練數(shù)據(jù)中的另一個交叉驗證(稱為“內(nèi)循環(huán)”)來優(yōu)化超參數(shù)。這意味著我們在訓(xùn)練數(shù)據(jù)上優(yōu)化超參數(shù),然后仍然可以獲得有關(guān)優(yōu)化模型在未見數(shù)據(jù)上表現(xiàn)如何的更少偏差的想法。

        這個概念可能有點難以理解,但對于希望了解更多細(xì)節(jié)的人,我在上面鏈接的文章中進(jìn)行了解釋。無論如何,代碼并不那么困難,閱讀代碼可能會有助于理解。實際上,我們在上面的過程中已經(jīng)準(zhǔn)備了大部分的代碼,只需要進(jìn)行一些小的調(diào)整。讓我們看看它的表現(xiàn)。

        嵌套交叉驗證的主要考慮因素,特別是在我們使用許多重復(fù)時,是需要花費很多時間才能運行。因此,我們將保持參數(shù)空間較小,并使用隨機(jī)搜索而不是網(wǎng)格搜索(盡管隨機(jī)搜索通常在大多數(shù)情況下表現(xiàn)良好)。如果您確實想要更徹底地進(jìn)行搜索,可能需要在HPC上保留一些時間。

        無論如何,在我們的初始for循環(huán)之外,我們將建立參數(shù)空間:


        我們隨后對原始代碼進(jìn)行以下更改:

        • CV現(xiàn)在將變?yōu)?/span>cv_outer,因為我們現(xiàn)在有兩個交叉驗證,我們需要適當(dāng)?shù)匾妹總€交叉驗證
        • 在我們的for循環(huán)中,我們循環(huán)遍歷訓(xùn)練和測試ID,我們添加內(nèi)部交叉驗證方案cv_inner
        • 然后,我們使用RandomizedSearchCV來優(yōu)化我們的模型在inner_cv上選擇我們最好的模型,然后使用最佳模型從測試數(shù)據(jù)中派生SHAP值(這里的測試數(shù)據(jù)是外部折疊測試)。

        就是這樣。為了演示目的,我們將CV_repeats減少到2,因為否則,我們可能要在這里一段時間。在實際情況下,您需要保持足夠高的次數(shù)以保持穩(wěn)健的結(jié)果,同時也要獲得最佳參數(shù),對于這些參數(shù),您可能需要HPC(或耐心)。

        請參見下面的代碼,其中 #-#-# 表示新添加的內(nèi)容。

        3. 結(jié)論

        能夠解釋復(fù)雜的AI模型變得越來越重要。

        SHAP值是一種很好的方法,但是在較小的數(shù)據(jù)集中,單次訓(xùn)練/測試拆分的結(jié)果并不總是可信的。

        通過多次重復(fù)(嵌套)交叉驗證等程序,您可以增加結(jié)果的穩(wěn)健性,并更好地評估如果基礎(chǔ)數(shù)據(jù)也發(fā)生變化,結(jié)果可能會如何變化。

        本文來自:https://towardsdatascience.com/using-shap-with-cross-validation-d24af548fadc為適合中文閱讀習(xí)慣,閱讀更有代入感,原文翻譯后有刪改。Dan Kirk | 作者羅伯特 | 編輯
           
        知識管理王者,我的第二大腦,Obsidian配置指南
        本地運行“小型”大模型,配合筆記應(yīng)用王者Obsidian做知識管理
        116頁PDF小冊子:機(jī)器學(xué)習(xí)中的概率論、統(tǒng)計學(xué)、線性代數(shù)
        可能是全網(wǎng)最全的速查表:Python Numpy Pandas Matplotlib 機(jī)器學(xué)習(xí) ChatGPT等


        瀏覽 54
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
          
          

            1. 欧美撸一撸 | 日韩欧美午夜电影 | 日韩国产无码一区二区 | 中国女人无套内谢 | 综合色色色 |