Python打卡訓練營-Day13-不平衡數據的處理

@浙大疏錦行

知識點:

  1. 不平衡數據集的處理策略:過采樣、修改權重、修改閾值
  2. 交叉驗證代碼

過采樣

過采樣一般包含2種做法:隨機采樣和SMOTE
過采樣是把少的類別補充和多的類別一樣多,欠采樣是把多的類別減少和少的類別一樣
一般都是缺數據,所以很少用欠采樣?
隨機過采樣ROS
隨機過采樣是從少數類中隨機選擇樣本,并將其復制后添加到訓練集。
隨機過采樣的步驟如下:

確定少數類的樣本數。
從少數類中隨機選擇樣本,并將其復制。
將復制的樣本添加到訓練集。
隨機過采樣的優點是,它可以增加少數類的樣本數,從而提高模型的泛化能力小。
隨機過采樣的缺點是,它可能會增加訓練集的大小,從而增加訓練時間。此外,它可能會增加
噪聲,并且可能會增加模型的偏差。

?smote過采樣
smote:過采樣是合成樣本的方法。

對于少數類中的每個樣本,計算它與少數類中其他樣本的距離,得到其k近鄰(一般k取5或其他合適的值)。
從k近鄰中隨機選擇一個樣本。
計算選定的近鄰樣本與原始樣本之間的差值。
生成一個在0到1之間的隨機數。
將差值乘以隨機數,然后加到原始樣本上,得到一個新的合成樣本。
重復上述步驟,直到合成出足夠數量的少數類樣本,使得少數類和多數類樣本數量達到某種平衡。
使用過采樣后的數據集訓練模型并評估模型性能。
SMOTEE的核心思想是通過在少數類樣本的特征空間中進行插值來合成新的樣本

修改權重
在處理類別不平衡的數據集時,標準機器學習算法(如默認的隨機森林)可能會過度偏向多數類,導致對少數類的預測性能很差。為了解決這個問題,常用的策略包括在數據層面(采樣)和算法層面進行調整。本文重點討論兩種算法層面的方法:修改類別權重和修改分類閾值。

挑戰:標準算法的優化目標(如最小化整體誤差)會使其優先擬合多數類,因為這樣做能更快地降低總誤差。
后果:對少數類樣本的識別能力不足(低召回率),即使整體準確率看起來很高。
目標:提高模型對少數類的預測性能,通常關注召回率(Recall)、F1分數(F1-Score))、AUC-PR等指標。
?方法一:修改類別權重(Cost-SensitiveLearning)
這種方法在模型訓練階段介入,通過調整不同類別樣本對損失函數的貢獻來影響模型的學習過程。

核心思想:為不同類別的錯誤分類分配不同的”代價”或”權重”。通常,將少數類樣本錯分為多數類的代價設置得遠高于反過來的情況。
作用機制:修改模型的損失函數。當模型錯誤分類一個具有高權重的少數類樣本時,會受到更大的懲罰(更高的損失值)。
目的:迫使學習算法在優化參數時更加關注少數類,努力學習到一個能夠更好地區分少數類的決策邊界。它試圖從根本上讓模型“學會”識別少數類。
影響:直接改變模型的參數學習過程和最終學到的模型本身。
在RandomForestClassifier中應用(class_weight參數)
Scikit-learn中的RandomForestclassifier提供了class_weight參數來實現代價敏感學

1.class_weight=None(默認值):

所有類別被賦予相同的權重(1)。
算法在構建樹和計算分裂標準(如基尼不純度)時,不區分多數類和少數類。
在不平衡數據上,這自然導致模型偏向多數類。
?2.class weight='balanced':

算法自動根據訓練數據y中各類別的頻率來調整權重(1)。
權重計算方式與類別頻率成反比:weight=n_samples/(n_classes*np.bincount(y))。
這意味著少數類樣本獲得更高的權重,多數類樣本獲得較低的權重。
目的是在訓練中“放大"少數類的重要性,促使模型提升對少數類的識別能力。
3.class_weight={dict}(手動設置):

可以提供一個字典,手動為每個類別標簽指定權重,例如class_weight={:1,1:10}表示類別1的權重是類別0的10倍。
●優點:

從模型學習的根本上解決問題。
可能得到泛化能力更強的模型。
許多常用算法內置支持,實現方便。
●注意:使用class_weight時,推薦結合交叉驗證(特別是StratifiedKFold)來可靠地評估其效果和模型的穩定性。

方法二:修改分類閾值
這種方法在模型訓練完成之后介入,通過調整最終分類的決策規則來平衡不同類型的錯誤。

核心思想:改變將模型輸出的概率(或得分)映射到最終類別標簽的門檻。
作用機制:模型通常輸出一個樣本屬于正類(通常設為少數類)的概率p。默認情況下,如果p>0.5,則預測為正類。修改閾值意味著改變這個0.5,例如,如果要求更高的召回率,可以將閾值降低(如p>0.3就預測為正類)。
目的:在不改變已訓練好的模型的情況下,根據業務需求調整精確率(Precision)和召回率(Recall)之間的權衡。通常用于提高少數類的召回率(但可能會犧牲精確率)。
影響:不改變模型學到的參數或決策邊界本身,只改變如何解釋模型的輸出。
優點:
實現簡單,無需重新訓練模型。
非常直觀,可以直接在PR曲線或ROC曲線上選擇操作點。
適用于任何輸出概率或分數的模型。
缺點:
治標不治本。如果模型本身就沒學好如何區分少數類(概率輸出普遍很低),單純降低閾值可能效果有限或導致大量誤報(低精確率)。
?實踐建議

評估指標先行:明確你的目標,使用適合不平衡數據的指標(Recall,F1-Score,AUC-PRBalanced Accuracy,MCC)來評估模型。
優先嘗試根本方法:通常建議首先嘗試修改權重(class_weight='balanced')或數據采樣方法如SMOT),因為它們試圖從源頭改善模型學習。
交叉驗證評估:在使用class_weight或采樣方法時,務必使用分層交叉驗證(Stratified K-Fold來獲得對模型性能的可靠估計。
閾值調整作為補充:修改閾值可以作為一種補充手段或最后的微調。即使使用了權重調整,有時仍需根據具體的業務需求(如必須達到某個召回率水平)來調整閾值,找到最佳的操作點。
組合策略:有時結合多種方法(如SMOTE+class_weight)可能會產生更好的結果。
總之,修改權重旨在訓練一個“更好”的模型,而修改閾值是在一個“已有”模型上調整其表現。
理解它們的差異有助于你選擇更合適的策略來應對不平衡數據集的挑戰。

import numpy as np # 引入 numpy 用于計算平均值等
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold, cross_validate # 引入分層 K 折和交叉驗證工具
from sklearn.metrics import make_scorer, accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report
import time
import warnings
warnings.filterwarnings("ignore")# 假設 X_train, y_train, X_test, y_test 已經準備好
# X_train, y_train 用于交叉驗證和最終模型訓練
# X_test, y_test 用于最終評估# --- 1. 默認參數的隨機森林 (原始代碼,作為對比基準) ---
print("--- 1. 默認參數隨機森林 (訓練集 -> 測試集) ---")
start_time = time.time()
rf_model_default = RandomForestClassifier(random_state=42)
rf_model_default.fit(X_train, y_train)
rf_pred_default = rf_model_default.predict(X_test)
end_time = time.time()
print(f"默認模型訓練與預測耗時: {end_time - start_time:.4f} 秒")
print("\n默認隨機森林 在測試集上的分類報告:")
print(classification_report(y_test, rf_pred_default))
print("默認隨機森林 在測試集上的混淆矩陣:")
print(confusion_matrix(y_test, rf_pred_default))
print("-" * 50)# --- 2. 帶權重的隨機森林 + 交叉驗證 (在訓練集上進行CV) ---
print("--- 2. 帶權重隨機森林 + 交叉驗證 (在訓練集上進行) ---")# 確定少數類標簽 (非常重要!)
# 假設是二分類問題,我們需要知道哪個是少數類標簽才能正確解讀 recall, precision, f1
# 例如,如果標簽是 0 和 1,可以這樣查看:
counts = np.bincount(y_train)
minority_label = np.argmin(counts) # 找到計數最少的類別的標簽
majority_label = np.argmax(counts)
print(f"訓練集中各類別數量: {counts}")
print(f"少數類標簽: {minority_label}, 多數類標簽: {majority_label}")
# !!下面的 scorer 將使用這個 minority_label !!# 定義帶權重的模型
rf_model_weighted = RandomForestClassifier(random_state=42,class_weight='balanced'  # 關鍵:自動根據類別頻率調整權重# class_weight={minority_label: 10, majority_label: 1} # 或者可以手動設置權重字典
)# 設置交叉驗證策略 (使用 StratifiedKFold 保證每折類別比例相似)
cv_strategy = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) # 5折交叉驗證# 定義用于交叉驗證的評估指標
# 特別關注少數類的指標,使用 make_scorer 指定 pos_label
# 注意:如果你的少數類標簽不是 1,需要修改 pos_label
scoring = {'accuracy': 'accuracy','precision_minority': make_scorer(precision_score, pos_label=minority_label, zero_division=0),'recall_minority': make_scorer(recall_score, pos_label=minority_label),'f1_minority': make_scorer(f1_score, pos_label=minority_label)
}print(f"開始進行 {cv_strategy.get_n_splits()} 折交叉驗證...")
start_time_cv = time.time()# 執行交叉驗證 (在 X_train, y_train 上進行)
# cross_validate 會自動完成訓練和評估過程
cv_results = cross_validate(estimator=rf_model_weighted,X=X_train,y=y_train,cv=cv_strategy,scoring=scoring,n_jobs=-1, # 使用所有可用的 CPU 核心return_train_score=False # 通常我們更關心測試折的得分
)end_time_cv = time.time()
print(f"交叉驗證耗時: {end_time_cv - start_time_cv:.4f} 秒")# 打印交叉驗證結果的平均值
print("\n帶權重隨機森林 交叉驗證平均性能 (基于訓練集劃分):")
for metric_name, scores in cv_results.items():if metric_name.startswith('test_'): # 我們關心的是在驗證折上的表現# 提取指標名稱(去掉 'test_' 前綴)clean_metric_name = metric_name.split('test_')[1]print(f"  平均 {clean_metric_name}: {np.mean(scores):.4f} (+/- {np.std(scores):.4f})")print("-" * 50)# --- 3. 使用權重訓練最終模型,并在測試集上評估 ---
print("--- 3. 訓練最終的帶權重模型 (整個訓練集) 并在測試集上評估 ---")
start_time_final = time.time()
# 使用與交叉驗證中相同的設置來訓練最終模型
rf_model_weighted_final = RandomForestClassifier(random_state=42,class_weight='balanced'
)
rf_model_weighted_final.fit(X_train, y_train) # 在整個訓練集上訓練
rf_pred_weighted = rf_model_weighted_final.predict(X_test) # 在測試集上預測
end_time_final = time.time()print(f"最終帶權重模型訓練與預測耗時: {end_time_final - start_time_final:.4f} 秒")
print("\n帶權重隨機森林 在測試集上的分類報告:")
# 確保 classification_report 也關注少數類 (可以通過 target_names 參數指定標簽名稱)
# 或者直接查看報告中少數類標簽對應的行
print(classification_report(y_test, rf_pred_weighted)) # , target_names=[f'Class {majority_label}', f'Class {minority_label}'] 如果需要指定名稱
print("帶權重隨機森林 在測試集上的混淆矩陣:")
print(confusion_matrix(y_test, rf_pred_weighted))
print("-" * 50)# 對比總結 (簡單示例)
print("性能對比 (測試集上的少數類召回率 Recall):")
recall_default = recall_score(y_test, rf_pred_default, pos_label=minority_label)
recall_weighted = recall_score(y_test, rf_pred_weighted, pos_label=minority_label)
print(f"  默認模型: {recall_default:.4f}")
print(f"  帶權重模型: {recall_weighted:.4f}")

--- 1. 默認參數隨機森林 (訓練集 -> 測試集) ---
默認模型訓練與預測耗時: 1.2171 秒

默認隨機森林 在測試集上的分類報告:
? ? ? ? ? ? ? precision ? ?recall ?f1-score ? support

? ? ? ? ? ?0 ? ? ? 0.77 ? ? ?0.97 ? ? ?0.86 ? ? ?1059
? ? ? ? ? ?1 ? ? ? 0.79 ? ? ?0.30 ? ? ?0.43 ? ? ? 441

? ? accuracy ? ? ? ? ? ? ? ? ? ? ? ? ? 0.77 ? ? ?1500
? ?macro avg ? ? ? 0.78 ? ? ?0.63 ? ? ?0.64 ? ? ?1500
weighted avg ? ? ? 0.77 ? ? ?0.77 ? ? ?0.73 ? ? ?1500

默認隨機森林 在測試集上的混淆矩陣:
[[1023 ? 36]
?[ 309 ?132]]
--------------------------------------------------
--- 2. 帶權重隨機森林 + 交叉驗證 (在訓練集上進行) ---
訓練集中各類別數量: [4328 1672]
少數類標簽: 1, 多數類標簽: 0
開始進行 5 折交叉驗證...
交叉驗證耗時: 3.6423 秒

帶權重隨機森林 交叉驗證平均性能 (基于訓練集劃分):
? 平均 accuracy: 0.7798 (+/- 0.0085)
? 平均 precision_minority: 0.8291 (+/- 0.0182)
? 平均 recall_minority: 0.2650 (+/- 0.0400)
? 平均 f1_minority: 0.3998 (+/- 0.0455)
--------------------------------------------------
--- 3. 訓練最終的帶權重模型 (整個訓練集) 并在測試集上評估 ---
最終帶權重模型訓練與預測耗時: 1.1657 秒

帶權重隨機森林 在測試集上的分類報告:
? ? ? ? ? ? ? precision ? ?recall ?f1-score ? support

? ? ? ? ? ?0 ? ? ? 0.76 ? ? ?0.97 ? ? ?0.86 ? ? ?1059
? ? ? ? ? ?1 ? ? ? 0.81 ? ? ?0.27 ? ? ?0.41 ? ? ? 441

? ? accuracy ? ? ? ? ? ? ? ? ? ? ? ? ? 0.77 ? ? ?1500
? ?macro avg ? ? ? 0.78 ? ? ?0.62 ? ? ?0.63 ? ? ?1500
weighted avg ? ? ? 0.78 ? ? ?0.77 ? ? ?0.72 ? ? ?1500

帶權重隨機森林 在測試集上的混淆矩陣:
[[1030 ? 29]
?[ 320 ?121]]
--------------------------------------------------
性能對比 (測試集上的少數類召回率 Recall):
? 默認模型: 0.2993
? 帶權重模型: 0.2744

作業:

從示例代碼可以看到 效果沒有變好,所以很多步驟都是理想是好的,但是現實并不一定可以變好。這個實驗仍然有改進空間,如下。

1. 我還沒做smote+過采樣+修改權重的組合策略,有可能一起做會變好。

2. 我還沒有調參,有可能調參后再取上述策略可能會變好

針對上面這2個探索路徑,繼續嘗試下去,看看是否符合猜測。

代碼實現?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907419.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907419.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907419.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mac OS 使用說明

Mac 的啟動組合鍵 了解可通過在啟動時按住一個或多個按鍵來訪問的 Mac 功能和工具。 若要使用這些組合鍵中的任何一個,請在按下電源按鈕以開啟 Mac 后或在 Mac 開始重新啟動后,立即按住相應按鍵。請一直按住,直至電腦出現對應的行為。 !!!上…

LoadRunner 是什么

LoadRunner 是一款由 Micro Focus(原惠普企業軟件部門)開發的性能測試工具,廣泛應用于軟件、應用程序和系統的 負載測試、壓力測試 和 性能分析。它通過模擬大量用戶并發操作,幫助測試人員評估系統在高負載下的性能、穩定性和可擴…

RISC-V PMA、PMP機制深入分析

1 PMA PMA(Physical Memory Attributes),物理內存屬性,顧名思義就是用來設置物理內存屬性的,但這里說“設置”,并不合理,因為一般情況下各存儲的屬性,在芯片設計時就固定了&#xf…

SQL正則表達式總結

這里寫目錄標題 一、元字符二、正則表達函數1、 regexp_like(x,pattern[,match_option])2、 regexp_instr(x,pattern[,start[,occurrence[,return_option[, match_option]]]]) 3、 REGEXP_SUBSTR(x,pattern[,start[,occurrence[, match_option]]]) 4、 REGEXP_REPLACE(x,patter…

Shortest path 代碼

Project https://graphics.cs.utah.edu/research/projects/shortest-path-to-boundary/ Build and Debug Fork:(在Win10上) https://github.com/chunleili/Shortest-Path-to-Boundary-for-Self-Intersecting-Meshes commit hash d3160168d2b6a58188d12e6cd959da…

AMBA總線家族成員

在AMBA總線協議體系中,AXI4雖然是最新且性能最強的總線協議,但AHB和APB仍然被廣泛使用,主要原因在于??場景適配性、資源優化和系統兼容性??的綜合考量。以下是具體分析: AMBA 1?:僅包含ASB和APB1。?AMBA 2?&am…

前端高頻面試題1:HTML/CSS/瀏覽器/計算機網絡

目錄 1.為什么會出現margin塌陷? 2.如何解決margin塌陷? 3.HTML5有哪些新特性? 4.常見的語義化標簽有哪些?語義化標簽的好處? 5.使用css和js做動畫有何優劣 6.如何實現文本超出展示省略號 7.deep在css中存在嗎&…

基于 Spring Boot + Vue 的墻繪產品展示交易平臺設計與實現【含源碼+文檔】

項目簡介 本系統是一個基于 Spring Boot Vue 技術棧開發的墻繪產品展示交易平臺,旨在提供一個高效、便捷的在線商城平臺,方便用戶瀏覽、選購墻繪產品,并提供管理員進行商品管理、訂單管理等功能。系統采用了前后端分離的架構,前…

STM32F103_Bootloader程序開發05 - Keil修改生成文件的路徑與文件名,自動生成bin格式文件

導言 通過Keil的相關配置,可以靈活地修改輸出文件的保存路徑及文件名稱。在Bootloader程序開發過程中,合理配置輸出文件對于后續固件升級和自動化腳本處理至關重要。完成路徑和文件名配置后,還可以借助Keil自帶的fromelf.exe工具,…

力扣每日一題2025.5.28——題號:3372.連接兩棵樹后最大目標節點數目 |

目錄 題目鏈接:3372. 連接兩棵樹后最大目標節點數目 I - 力扣(LeetCode) 題目描述 解法一: Java寫法: C寫法: 運行時間 時間復雜度和空間復雜度 總結 題目鏈接:3372. 連接兩棵樹后最大目…

華為防火墻NAPT配置

1.實驗拓撲 2.實驗配置 [SW1]dis cu # sysname SW1 # vlan batch 10 20 # interface Vlanif10ip address 192.168.10.254 255.255.255.0 # interface Vlanif20ip address 192.168.20.253 255.255.255.0 # interface GigabitEthernet0/0/1port link-type accessport default vl…

java導入excel

這樣讀取excel時,得到的是結果值,而不是單元格的公式 import cn.hutool.poi.excel.ExcelReader; import cn.hutool.poi.excel.ExcelUtil;InputStream inputStream file.getInputStream(); ExcelReader reader ExcelUtil.getReader(inputStream, 1); L…

stm32cube ide如何生成LL庫工程

在 STM32Cube IDE 里生成使用 LL(Low Layer)庫的工程,可按以下步驟操作: 1. 新建 STM32 工程 啟動 STM32Cube IDE,選擇File→New→STM32 Project。依據需求挑選目標 MCU 型號,接著點擊Next。 2. 配置工程…

阿里通義實驗室突破空間音頻新紀元!OmniAudio讓360°全景視頻“聲”臨其境

在虛擬現實和沉浸式娛樂快速發展的今天,視覺體驗已經遠遠不夠,聲音的沉浸感成為打動用戶的關鍵。然而,傳統的視頻配音技術往往停留在“平面”的音頻層面,難以提供真正的空間感。阿里巴巴通義實驗室(Qwen Lab&#xff0…

二十八、面向對象底層邏輯-SpringMVC九大組件之ViewResolver接口設計

在 Spring MVC 框架中,視圖解析器(ViewResolver)是連接控制器邏輯與具體視圖技術的核心紐帶。它通過抽象化的接口設計,將視圖的渲染邏輯與業務邏輯解耦,使開發者能夠靈活支持 JSP、Thymeleaf、FreeMarker 等多種視圖技…

LiveWallpaperMacOS:讓你的 Mac 桌面動起來

隨著桌面美化需求的不斷提升,用戶對于桌面壁紙的要求已經不再局限于靜態圖片。越來越多的 Mac 用戶希望桌面能像 Windows 一樣,擁有動態壁紙,展現個性、提升體驗。LiveWallpaperMacOS 正是這樣一款讓你的 Mac 桌面煥發活力的開源項目。 本文將詳細介紹 LiveWallpaperMacOS …

豆瓣電視劇數據工程實踐:從爬蟲到智能存儲的技術演進(含完整代碼)

通過網盤分享的文件:資料 鏈接: https://pan.baidu.com/s/1siOrGmM4n-m3jv95OCea9g?pwd4jir 提取碼: 4jir 1. 引言 1.1 選題背景 在影視內容消費升級背景下,豆瓣電視劇榜單作為國內最具影響力的影視評價體系,其數據價值體現在&#xff1a…

集成均衡功能電池保護芯片在大功率移動電源的應用,創芯微CM1341-DAT、杰華特JW3312、賽微微電CW1244、中穎SH366006

一文了解集成均衡功能電池保護IC在大功率移動電源的應用 創芯微CM1341-DAT 創芯微CM1341-DAT是一款專用于4串鋰離子/磷酸鐵鋰電池的保護芯片,內置有高精度電壓檢測電路和電流檢測電路。通過檢測各節電池的電壓、充放電電流及溫度等信息,實現電池過充電…

PHP生成pdf方法

1:第一種方法: 主要使用PHP的擴展 【 “spatie/browsershot”: “3.57”】 使用這個擴展生成PDF需要環境安裝以下依賴 1.1:NPM【版本:9.2.0】 1.2:NODE【版本:v18.19.1】 1.3:puppeteer【npm in…

聯通專線加持!億林網絡 24 核 32G 裸金屬服務器,千兆共享帶寬適配中小型企業 IT 架構

在當今數字化時代,企業的業務運營越來越依賴高效、穩定的 IT 架構。對于中小型企業而言,如何在有限的預算內構建強大且可靠的 IT 基礎設施,是一項關鍵挑戰。億林網絡推出的 24 核 32G 裸金屬服務器,搭配聯通專線和千兆共享帶寬&am…