<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【機器學習】如何在交叉驗證中使用SHAP?

          共 6813字,需瀏覽 14分鐘

           ·

          2024-05-28 11:00

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

          1. 介紹

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

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

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

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

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

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

          圖1. 機器學習中的不同評估程序。

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

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

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

          2. SHAP實踐

          2.1. SHAP值的基本實現

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

          因此,我們從SHAP值的基本實現開始。

          我假設您熟悉SHAP的一般用途和其實現代碼的外觀,因此我不會花太長時間進行說明。

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

          2.2. 將交叉驗證與SHAP值相結合

          我們經常使用sklearncross_val_score或類似方法自動實現交叉驗證。

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

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

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

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

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

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

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

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

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

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

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

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

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

          但我們仍然不清楚穩(wěn)定性。即,如果數據被分割得不同,結果會如何改變。

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

          2.3. 重復交叉驗證

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

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

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

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

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

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

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

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

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

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

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

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

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

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

          以上代碼表示:對于原始數據框中的每個樣本索引,從每個 SHAP 值列表(即每個交叉驗證重復)中制作數據框。該數據框將每個交叉驗證重復作為行,每個 X 變量作為列。我們現在使用相應的函數和使用 axis = 1 以列為單位執(zhí)行計算,對每列取平均值、標準差、最小值和最大值。然后我們將每個轉換為數據框。

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

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

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

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

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

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

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

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

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

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

          我們可以根據我們收集的其他統(tǒng)計數據,例如標準差,想出類似的情節(jié)。

          2.4. 嵌套交叉驗證

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

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

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

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

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

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

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


          我們隨后對原始代碼進行以下更改:

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

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

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

          3. 結論

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

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

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

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


          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  激情啪啪网站 | 日韩高清一级 | 在线欧美日本 | 欧美三级韩国三级日本三斤在线观看 | 欧美成人免费在线观看 |