0 結果展示
0.1 鳶尾花分類
import pandas as pd
import numpy as npfrom sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, recall_score, f1_score, classification_report, roc_auc_score,confusion_matrix
from sklearn.datasets import load_iris
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifierimport matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑體
plt.rcParams['axes.unicode_minus'] = False # 解決負號顯示問題iris = load_iris()
data = pd.DataFrame(iris.data, columns=iris.feature_names)
data["target"] = iris.target
X = data.drop(columns="target")
y = data["target"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)rf = RandomForestClassifier(n_estimators=100,criterion="gini", # 分裂的標準max_depth=None, # 不限制深度min_samples_leaf=1,min_samples_split=2,)
rf.fit(X_train, y_train)y_pred = rf.predict(X_test)df = pd.DataFrame({"feature": X.columns,"importance": rf.feature_importances_
})
print("classification_report:")
print(classification_report(y_test, y_pred))
print("confusion_matrix:")
print(confusion_matrix(y_test, y_pred))
df.sort_values(by="importance", inplace=True, ascending=False) # 降序
plt.figure(figsize=(10,8))
plt.bar(df.feature, df.importance,color = ["b","g","r","pink"])
plt.show()
0.2 信用卡欺詐檢測
data = pd.read_csv("../data/creditcard.csv")
import pandas as pd
import numpy as npfrom sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, recall_score, f1_score, classification_report, roc_auc_score,confusion_matrix
from sklearn.datasets import load_iris
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import roc_curve
import matplotlib.pyplot as plt
# 數據集劃分
X=data.drop(columns=["Time","Class"])
y=data["Class"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,stratify=y.values,random_state=42)
# 特征工程
#標準化
transfer = StandardScaler()
X["Amount"] = transfer.fit_transform(X["Amount"].to_frame())# fit_transform只接受二維
# 訓練
rf = RandomForestClassifier(n_estimators=100,class_weight="balanced",n_jobs=-1,
) # class_weight根據類別的比例采樣,因為1和0類別數量差距太大了
rf.fit(X_train, y_train)
#驗證
y_pred = rf.predict(X_test)
y_pred_proba = rf.predict_proba(X_test)print(classification_report(y_test, y_pred))
fpr,tpr,_ = roc_curve(y_test,y_pred_proba[:,1]) # 計算fpr和tpr,這個函數只需要正類,所以不用指定label,只需呀指定pos_label
# 繪制ROC 曲線
plt.figure(figsize=(10,5))
plt.plot(fpr,tpr,color="blue",label="ROC")
plt.plot([0,1],[0,1],color="red",linestyle="--")
#
plt.title("ROC")
plt.plot(fpr,tpr,label='ROC')
plt.plot([0,1],[0,1],linestyle='--')
plt.show()
AUC =roc_auc_score(y_test,y_pred_proba[:,1])
print(AUC)
(集成中的算法 大多數情況都是用樹模型去做的,幾乎沒有其他模型去做)
1 Bagging
1】什么是Bagging
- Bagging(Bootstrap Aggregating)是一種并行式集成學習方法
- 核心思想是通過對訓練樣本進行有放回的隨機抽樣(自助采樣法),構建多個弱學習器,然后對這些學習器的預測結果進行投票或平均。
2】Bagging的關鍵特點
- ?自助采樣(Bootstrap Sampling)?:從原始訓練集中有放回地隨機抽取n個樣本(n通常等于原始訓練集大小)
- ?并行訓練?:基學習器之間相互獨立,可以并行訓練
- ?降低方差?:特別適合不穩定的學習算法(如決策樹)
- ?簡單投票/平均?:分類問題用投票,回歸問題用平均
3】Bagging算法流程
- 1.對訓練集進行T次自助采樣,得到T個采樣集
- 2.用每個采樣集訓練一個基學習器
- 3.對分類問題:采用投票法結合T個基學習器的結果
- 4.對回歸問題:采用平均法結合T個基學習器的結果
1.1 隨機森林
sklearn.ensemble.RandomForestClassifier(n_estimators=10,
criterion=’gini’,
max_depth=None,
bootstrap=True,
random_state=None,
min_samples_split=2
)
參數:
1】n_estimators:integer,optional(default = 10)森林?的樹?數量120,200,300,500,800,1200
在利?最?投票數或平均值來預測之前,你想要建??樹的數量。
2】Criterion:string,可選(default =“gini”)
分割特征的測量?法
3】max_depth:integer或None,可選(默認=?)
樹的最?深度 5,8,15,25,30
4】max_features=“auto”,每個決策樹的最?特征數量
If “auto”, then max_features=sqrt(n_features)
If “sqrt”, then max_features=sqrt(n_features) (same as “auto”).
If “log2”, then max_features=log2(n_features)
If None, then max_features=n_features
5】bootstrap:boolean,optional(default = True)
是否在構建樹時使?放回抽樣
6】min_samples_split 內部節點再劃分所需最?樣本數
這個值限制了?樹繼續劃分的條件,如果某節點的樣本數少于min_samples_split,則不會繼續再嘗試選擇
最優特征來進?劃分,默認是2。
如果樣本量不?,不需要管這個值。
如果樣本量數量級?常?,則推薦增?這個值。
7】min_samples_leaf 葉?節點的最?樣本數
這個值限制了葉?節點最少的樣本數,如果某葉?節點數??于樣本數,則會和兄弟節點?起被剪枝,
默認是1。
葉是決策樹的末端節點。 較?的葉?使模型更容易捕捉訓練數據中的噪聲。
?般來說,我更偏向于將最?葉?節點數?設置為?于50。
8】min_impurity_split: 節點劃分最?不純度
這個值限制了決策樹的增?,如果某節點的不純度(基于基尼系數,均?差)?于這個閾值,則該節點不再?成?節點。即為葉?節點 。
?般不推薦改動默認值1e-7。
9】class_weight:調整類別權重
balanced:自動按樣本數的反比給出權重:n_samples / (n_classes * np.bincount(y))
balanced_subsample:與"balanced” 類似,但 僅基于每次自助抽樣后的子樣本 計算權重
1.2隨機森林常見問題
1 為什么隨機森林比單棵決策樹好?
- 樣本隨機性:減少過擬合風險
- 特征隨機性:增加樹之間的多樣性
- 集體決策:降低單棵樹的錯誤率
2 如何選擇n_estimators參數?
- 開始時選擇較小的值(如50-100)
- 觀察驗證集性能隨樹數量增加的變化
- 當性能不再顯著提升時停止增加
- 計算資源允許的情況下可以設置較大值
3 如何處理類別不平衡問題?
- 使用class_weight="balanced"參數調整類別權重
- 對少數類進行過采樣
- 使用balanced_subsample參數(自助采樣時保持類別比例)
4 隨機森林有哪些優缺點?
?優點?:
- 高準確性
- 能處理高維數據
- 能評估特征重要性
- 對缺失值和異常值較魯棒
- 不需要特征縮放
?缺點?:
- 模型解釋性較差
- 訓練時間可能較長(樹多時)
- 可能占用較多內存
**常規bagging實現,以決策樹為例 **
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, recall_score,f1_score, classification_report,roc_auc_score
from sklearn.datasets import load_iris
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
data = pd.DataFrame(iris.data, columns=iris.feature_names)
data["target"] = iris.target
X=data.drop(columns="target")
y= data["target"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,random_state=42)
#%%
# bagging
bagging = BaggingClassifier(estimator=DecisionTreeClassifier(), # 弱學習器設置為決策樹n_estimators=100, # 100棵決策樹max_samples=0.8, # 每次采樣80%的樣本max_features=0.8, # 每次采樣80%的特征random_state=42 , )
bagging.fit(X_train, y_train)y_pred = bagging.predict(X_test)
print(accuracy_score(y_test, y_pred))
隨機森林實現
# rf
rf = RandomForestClassifier(n_estimators=100,criterion="gini",# 分裂的標準max_depth=None, # 不限制深度min_samples_leaf=1,min_samples_split=2,)
rf.fit(X_train,y_train)y_pred = rf.predict(X_test)
print(accuracy_score(y_test, y_pred))df = pd.DataFrame({"feature" : X.columns,"importance" : rf.feature_importances_
})
df.sort_values(by="importance",inplace=True,ascending=False)# 降序
df
2 可視化決策邊界
import numpy as np
from sklearn.decomposition import PCA # 主成分降維
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑體
plt.rcParams['axes.unicode_minus'] = False # 解決負號顯示問題
pca = PCA(n_components=2) # n_components表示需要降到幾維,以便可視化
X_pca = pca.fit_transform(X)
train_X_pca, test_X_pca, train_y_pca, test_y_pca = train_test_split(X_pca,y,test_size=0.2,random_state=42)rf_pca = RandomForestClassifier(n_estimators=100,)
rf_pca.fit(train_X_pca,train_y_pca)# ---------------1 創建網格點 1----------------------------------
# 網格點的主要目的是為了可視化"測試點"
# 1.繪制決策邊界
# 2.填充顏色區域
# 3.展示分類的效果X_min,X_max = X_pca[:,0].min()-1,X_pca[:,0].max()+1 # 根據第一個主要成分定義X軸范圍。+1和-1防止樣本正好在邊界上
y_min,y_max = X_pca[:,1].min()-1,X_pca[:,1].max()+1 # 根據第二個主要成分定義Y軸范圍。xx,yy = np.meshgrid(np.arange(X_min,X_max,0.02), # 根據范圍創建等差數列作為一個個網格np.arange(y_min,y_max,0.02), # 根據范圍創建等差數列作為一個個網格
)
#---------2 此時已經生成了一個空白的網格面板 2---------# 預測網格點,將xx,yy網格矩陣變成一維數組(x,y)
"注意np.c_后面跟的是中括號"
Z = rf_pca.predict(np.c_[xx.ravel(), yy.ravel()]) # ravel()將網格矩陣變為一維,
# np.c_[] # 將兩個一維數組按列合并成一個二維數組
# 格式: [[x1,y1],[x2,y2],[x3,y3]........]#---------3 以上操作用已經訓練好的rf_pca對每一個網格點均進行預測,故當(xx[i],yy[i])的元素處于會被分類為0的坐標時就會被分類為0,其他類別也是, 3 -------------
# --------3 ,此時Z為0,1,2的三個類別,每個網格點都被劃分好了類別 3-----------# 繪制決策邊界
Z = Z.reshape(xx.shape)#-----------------4 將分類好的網格點重新reshape為原來的形狀,否則無法畫出來,為contourf繪制作準備 4-------------------------------
plt.figure(figsize=(10,8))#--------------------------5 繪制----------------------------------
plt.contourf(xx, yy, Z, ) # xx和yy表示了每個網格點,Z表示了每個網格點的類型,故第三個參數需要和xx和yy形狀相同
plt.scatter(X_pca[:,0], X_pca[:,1],c=y,edgecolors="k") # c=y表示用目標值進行著色,逐個著色,標簽不同顏色不同
plt.title("隨機森林決策邊界的可視化")
plt.xlabel("主要成分1")
plt.ylabel("主要成分2")plt.show()
3 boosting
1】什么是Boosting
Boosting是一種序列式集成學習方法,通過將多個弱學習器(如決策樹樁)組合成一個強學習器。
與Bagging不同,Boosting的基學習器是順序訓練的,每個基學習器都會嘗試修正前一個學習器的錯誤。
2】Boosting的核心思想
- ?逐步改進?:每個新模型都專注于糾正前一個模型的錯誤
- ?加權訓練?:錯誤分類的樣本在后續訓練中獲得更高權重
- ?線性組合?:將所有弱學習器的預測結果加權組合
3】Boosting工作流程
-
- 初始化樣本權重均等
-
- 對當前樣本權重,訓練學習器hth_tht?
-
- 計算該學習器的加權錯誤率?=∑i=1mwi(t)?I(h(xi)≠yi)\epsilon = \sum_{i=1}^m w_i^{(t)} \cdot I(h(x_i) \neq y_i)?=∑i=1m?wi(t)??I(h(xi?)=yi?)(h(xi)h(x_i)h(xi?)表示對樣本i的預測,III表示如果括號內條件為真(即預測錯誤)則返回1,否則返回0)
-
- 計算該學習器權重 αt\alpha_tαt? ,αt=12ln?1??t?t\alpha_t = \frac{1}{2} \ln \frac{1 - \epsilon_t}{\epsilon_t}αt?=21?ln?t?1??t??.
-
- 更新樣本權重(注意非學習器權重),wi(t+1)=wi(t)?exp?(?αtyiht(xi))Ztw_i^{(t+1)} = \frac{w_i^{(t)} \cdot \exp(-\alpha_t y_i h_t(x_i))}{Z_t}wi(t+1)?=Zt?wi(t)??exp(?αt?yi?ht?(xi?))?(這一步是Ada的做法,梯度提升樹是通過求殘差的梯度來逼近最優權重)
-
- 重復步驟2-6直到達到預設的基學習器數量
-
- 將所有基學習器加權組合成最終模型
4】常見Boosting算法
- 1.AdaBoost (Adaptive Boosting)
- 2.Gradient Boosting
- 3.XGBoost
- 4.LightGBM
- 5.CatBoost
3.1 GradientBoostingClassifier和AdaBoostClassifier
3.1 api實現
api:
from sklearn.ensemble import AdaBoostClassifier,GradientBoostingClassifier
AdaBoost模型:
AdaBoostClassifier(
estimator=DecisionTreeClassifier(max_depth=1),
n_estimators,
learning_rate,
random_state=42
)
Gradient Boosting模型:
GradientBoostingClassifier(
n_estimators,
learning_rate,
max_depth,
random_state
)
plt.show()
#%% md
3.2 Boosting算法常見問題
1 如何選擇n_estimators和learning_rate?
- n_estimators?:開始時選擇中等大小(50-100),觀察驗證誤差隨樹數量增加的變化
- learning_rate?:通常選擇較小的值(0.01-0.1),較小的學習率通常需要更多的樹
2 Boosting容易過擬合嗎?
- AdaBoost相對不容易過擬合
- Gradient Boosting容易過擬合,可以通過以下方法控制:
- 減小max_depth
- 增加min_samples_leaf
- 使用早停(early stopping)
- 添加子采樣(subsample)
3 為什么Gradient Boosting通常比AdaBoost表現更好?
Gradient Boosting直接優化損失函數,可以處理更多樣的問題,并且對異常值不那么敏感。
4什么時候應該使用Boosting?
- 當需要高預測精度時
- 當數據質量較好(噪聲和異常值較少)時
- 當有足夠的計算資源時(特別是對于大型數據集)
#%% md
3.3 boosting算法對比
特性 | AdaBoost | Gradient Boosting |
---|---|---|
核心思想 | 調整樣本權重 | 梯度下降優化損失函數 |
基學習器 | 通常是決策樹樁(max_depth=1) | 通常是較淺的決策樹 |
學習率 | 有 | 有(更關鍵) |
對異常值敏感性 | 較敏感 | 較不敏感 |
訓練速度 | 較快 | 較慢 |
過擬合風險 | 較低 | 較高 |
主要參數 | n_estimators, learning_rate | n_estimators, learning_rate, max_depth |
boosting實現
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, recall_score, f1_score, classification_report, roc_auc_score
from sklearn.datasets import load_iris
from sklearn.ensemble import BaggingClassifier,AdaBoostClassifier, GradientBoostingClassifier
from sklearn.tree import DecisionTreeClassifier
import numpy as np
from sklearn.decomposition import PCA # 主成分降維
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑體
plt.rcParams['axes.unicode_minus'] = False # 解決負號顯示問題
# plt.rcParams['image.cmap'] = 'plasma' # 設置默認調色板為 plasma
iris = load_iris()
data = pd.DataFrame(iris.data, columns=iris.feature_names)
data["target"] = iris.target
X = data.drop(columns="target")
y = data["target"]pca.fit_transform(X)
train_X_pca ,test_X_pca,train_y_pca ,test_y_pca = train_test_split(X,y,test_size=0.2)
train_X_pca = pca.fit_transform(train_X_pca)
test_X_pca = pca.transform(test_X_pca)
# 訓練
Ada = AdaBoostClassifier()
Ada.fit(train_X_pca,train_y_pca)
GB = GradientBoostingClassifier()
GB.fit(train_X_pca,train_y_pca)
# 創建網格范圍
x_min ,x_max = train_X_pca[:,0].min()-1,train_X_pca[:,0].max()+1
y_min ,y_max =train_X_pca[:,1].min()-1,train_X_pca[:,1].max()+1
# 根據范圍創建網格
xx,yy = np.meshgrid(np.arange(x_min,x_max,0.02),np.arange(y_min,y_max,0.02)
)
# 預測網格類別
Ada_Z = Ada.predict(np.c_[xx.ravel(),yy.ravel()])
Ada_Z = Ada_Z.reshape(xx.shape)
GB_Z = GB.predict(np.c_[xx.ravel(),yy.ravel()])
GB_Z = GB_Z.reshape(xx.shape)# 繪制
plt.figure(figsize=(10,8))
fig,axes = plt.subplots(1,2,figsize=(20,8))
axes[0].contourf(xx,yy,Ada_Z)
axes[0].scatter(train_X_pca[:,0],train_X_pca[:,1],c=train_y_pca,edgecolors="k")
axes[0].set_title("AdaBoostClassifier決策邊界")
axes[0].set_xlabel("主成分1")
axes[0].set_ylabel("主成分2")
axes[1].contourf(xx,yy,GB_Z)
axes[1].scatter(train_X_pca[:,0],train_X_pca[:,1],c=train_y_pca,edgecolors="k")
axes[1].set_title("GradientBoostingClassifier決策邊界")
axes[1].set_xlabel("主成分1")
axes[1].set_ylabel("主成分2")plt.show()
3.4 GradientBoostingClassifier算法介紹*
2 GBDT的核心思想
- ?梯度提升?:通過梯度下降來最小化損失函數
- ?決策樹基學習器?:使用決策樹作為弱學習器
- ?殘差學習?:每個新樹學習前序模型的殘差
- ?加法模型?:將多個弱學習器的預測結果累加
3 GBDT工作流程
-
1】 初始化模型(常數值預測)
-
2】 對于每輪迭代(每棵樹):
- 計算當前模型的負梯度(偽殘差)
- 用偽殘差擬合一棵決策樹
- 通過線搜索確定最優步長
- 更新模型(將新樹的預測乘以學習率后加到原模型)
-
3】 組合所有樹的預測結果
4 GBDT的關鍵特點
1】 優點
- ?高預測精度?:在多種任務上表現優異
- ?特征組合?:自動學習高階特征組合
- ?魯棒性?:對異常值和缺失值有一定魯棒性
- ?靈活性?:可處理各種損失函數
2】 缺點
- ?訓練時間較長?:需要順序構建多棵樹
- ?內存消耗大?:需要存儲多棵樹
- ?參數敏感?:需要仔細調參
5 與隨機森林的區別
特性 | GBDT | 隨機森林 |
---|---|---|
基學習器關系 | 順序訓練 | 并行訓練 |
目標 | 減少偏差 | 減少方差 |
樹相關性 | 高度相關 | 低相關 |
過擬合風險 | 較高 | 較低 |
參數敏感性 | 更敏感 | 較不敏感 |
4 boosting和bagging的區別
區別?:數據方面
Bagging:對數據進?采樣訓練;
Boosting:根據前?輪學習結果調整數據的重要性。
區別?:投票方面
Bagging:所有學習器平權投票;
Boosting:對學習器進?加權投票。
區別三:學習順序
Bagging的學習是并行的,每個學習器沒有依賴關系;
Boosting學習是串?,學習有先后順序。
區別四:主要作?
Bagging主要?于提?泛化性能(解決過擬合,也可以說降低?差)
Boosting主要?于提?訓練精度 (解決?擬合,也可以說降低偏差)
5 stacking*
- 原理?:用多個基礎模型的輸出作為新模型的輸入特征
- ?特點?:可以結合不同類型模型的優勢