1. 程式人生 > 其它 >Python——隨機森林模型與ROC曲線

Python——隨機森林模型與ROC曲線

隨機森林模型,針對迴歸問題的預測值,可以使用所有樹的平均值;而分類問題的預測值,可以使用所有決策樹的投票來決定。Python中,使用sklearn庫就可以完成隨機森林模型的使用。針對隨機森林模型對測試樣本可預測出一個預測概率,然後將這個預測值與一個分類閾值進行比較,如果大於閾值則分為正類,否則為反類。例如:針對每一個測試樣本預測出一個[0,1]之間的概率,然後將這個值與0.5比較,如果大於0.5則判斷為正類,反之為負類。閾值的好壞直接反映了學習演算法的泛化能力。根據預測值的概率,可以使用受試者工作特徵曲線(ROC)來分析機器學習演算法的泛化效能。在ROC曲線中,縱軸是真正例率(True positive rate),橫軸是假正例率(False Positive rate)。ROC曲線與橫軸圍成的面積大小稱為學習器的AUC(Area Under ROC curve),該值越接近於1,說明演算法模型越好。本文章將會使用兩種資料集介紹如何對隨機森林模型視覺化ROC曲線,對模型效果進行分析。首先匯入會使用到的庫或模組。

## 輸出高清影象
%config InlineBackend.figure_format = 'retina'
%matplotlib inline
## 影象顯示中文的問題
import matplotlib
matplotlib.rcParams['axes.unicode_minus']=False
import seaborn as sns
sns.set(font= "Kaiti",style="ticks",font_scale=1.4)
import pandas as pd
pd.set_option("max_colwidth", 200)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder,label_binarize
from sklearn.model_selection import  train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import *
## 忽略提醒
import warnings
warnings.filterwarnings("ignore")

1 二分類資料的ROC曲線視覺化

下面使用泰坦尼克號二分類資料集,介紹如何使用隨機森林演算法建立分類模型。首先是資料準備程式:

## 讀取資料泰坦尼克號預處理後資料
train = pd.read_csv("data/Titanic處理後資料.csv")
# 將字串型別的分類變數進行重新編碼
label = LabelEncoder()
train["Name"] = label.fit_transform(train["Name"])
train["Embarked"] = label.fit_transform(train["Embarked"])
train["Sex"] = label.fit_transform(train["Sex"])
# 定於預測目標變數名
Target = ["Survived"]
## 定義模型的自變數名
train_x = ["Pclass", "Name", "Sex", "Age", "SibSp", "Parch","Fare","Embarked"]
##將訓練集切分為訓練集和驗證集
X_train,X_val,y_train,y_val = train_test_split(train[train_x], train[Target],
                                               test_size = 0.25,random_state = 1)
print("X_train.shape :",X_train.shape)
print("X_val.shape :",X_val.shape)
print(X_train.head())
 
X_train.shape : (668, 8)
X_val.shape : (223, 8)
     Pclass  Name  Sex   Age  SibSp  Parch     Fare  Embarked
35        1     2    1  42.0      1      0  52.0000         2
46        3     2    1  28.0      1      0  15.5000         1
453       1     2    1  49.0      1      0  89.1042         0
291       1     3    0  19.0      1      0  91.0792         0
748       1     2    1  19.0      1      0  53.1000         2

下面的程式中使用RandomForestClassifier()函式建立了包含100個決策樹,最大深度為5的隨機森林模型,針對訓練好的模型並計算出其它訓練集和驗證集上的預測精度。執行程式後可發現在訓練集上的預測集精度為0.86,在驗證集上的預測精度是0.79。

## 使用隨機森林對泰坦尼克資料進行分類
rfc1 = RandomForestClassifier(n_estimators = 100, # 樹的數量
                              max_depth= 5,       # 子樹最大深度
                              oob_score=True,
                              class_weight = "balanced",
                              random_state=1)
rfc1.fit(X_train,y_train)
## 輸出其在訓練資料和驗證資料集上的預測精度
rfc1_lab = rfc1.predict(X_train)
rfc1_pre = rfc1.predict(X_val)
print("隨機森林的OOB score:",rfc1.oob_score_)
print("訓練資料集上的精度:",accuracy_score(y_train,rfc1_lab))
print("驗證資料集上的精度:",accuracy_score(y_val,rfc1_pre))
 
隨機森林的OOB score: 0.8263473053892215
訓練資料集上的精度: 0.8607784431137725
驗證資料集上的精度: 0.7982062780269058

使用訓練資料集訓練得到隨機森林模型後,針對測試集的ROC曲線可以使用下面的程式進行視覺化,執行程式後可得到圖1。通過圖1可以發現,隨機森林分類器在驗證集上的預測情況,並且AUC的取值為0.8614。

## 視覺化在驗證集上的Roc曲線
pre_y = rfc1.predict_proba(X_val)[:, 1]
fpr_Nb, tpr_Nb, _ = roc_curve(y_val, pre_y)
aucval = auc(fpr_Nb, tpr_Nb)    # 計算auc的取值
plt.figure(figsize=(10,8))
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_Nb, tpr_Nb,"r",linewidth = 3)
plt.grid()
plt.xlabel("假正率")
plt.ylabel("真正率")
plt.xlim(0, 1)
plt.ylim(0, 1)
plt.title("隨機森林ROC曲線")
plt.text(0.15,0.9,"AUC = "+str(round(aucval,4)))
plt.show()

圖1 二分類資料的ROC曲線

2多分類資料的ROC曲線視覺化

針對多類資料的ROC曲線的視覺化方式有兩種:

第一種為:採用將原始資料的真實類別標籤矩陣和模型預測得到的概率矩陣分別按行展開,轉置後形成兩列,這就可以近似的看作獲得了一個二分類的結果,進而可以視覺化ROC曲線。

第二種方式為:將每類一類資料和其他類別的資料看作為一個二分類類的資料模型,然後對資料視覺化ROC曲線。為了方便計算每一類樣本的ROC曲線的相關取值,可以將類別標籤使用label_binarize進行編碼。

下面使用一個多分類的資料集,然後使用隨機森林模型對其建立分類器,然後針對預測的結果使用ROC曲線進行分析。先匯入資料並建立模型,程式如下所示:

## 資料準備
bbcdata  = np.load("data/bbc_tfidf.npz")
train_tfidf = bbcdata['arr_0']
test_tfidf = bbcdata['arr_1']
y_train = bbcdata['arr_2']
y_test = bbcdata['arr_3']
print(train_tfidf.shape)
print(y_train.shape)
print(test_tfidf.shape)
print(y_test.shape)
## 為方便後面視覺化ROC曲線,對標籤使用label_binarize進行編碼
y_test_lb = label_binarize(y_test,classes=[0,1,2,3,4])
 
(1557, 1000)
(1557,)
(668, 1000)
(668,)
 
## 使用隨機森林對資料進行分類
rfc1 = RandomForestClassifier(n_estimators = 100, # 樹的數量
                              max_depth= 5,       # 子樹最大深度
                              oob_score=True,
                              class_weight = "balanced",
                              random_state=1)
rfc1.fit(train_tfidf,y_train)
## 輸出其在訓練資料和測試資料集上的預測精度
rfc1_lab = rfc1.predict(train_tfidf)
rfc1_pre = rfc1.predict(test_tfidf)
print("隨機森林的OOB score:",rfc1.oob_score_)
print("訓練資料集上的精度:",accuracy_score(y_train,rfc1_lab))
print("測試資料集上的精度:",accuracy_score(y_test,rfc1_pre))

隨機森林的OOB score: 0.9004495825305073
訓練資料集上的精度: 0.9569685292228645
測試資料集上的精度: 0.937125748502994 

2.1 針對所有類別的資料視覺化一條ROC曲線

針對所有類別的資料使用一條ROC曲線對模型結果進行視覺化的程式如下,執行程式後可獲得如圖2所示的ROC曲線。

## 視覺化演算法的ROC曲線
plt.figure(figsize=(8,7))
## 對測試集進預測
pre_score = rfc1.predict_proba(test_tfidf)
## 計算繪製ROC曲線的取值
fpr_micro, tpr_micro, _ = roc_curve(y_test_lb.ravel(), pre_score.ravel())
AUC = auc(fpr_micro, tpr_micro)  # AUC大小
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_micro, tpr_micro,"r",linewidth = 3)
plt.xlabel("假正率")
plt.ylabel("真正率")
plt.xlim(0, 1)
plt.ylim(0, 1)
plt.grid()
plt.title("隨機森林ROC曲線")
plt.text(0.2,0.8,"AUC = "+str(round(AUC,4)))
plt.show()

圖2 多分類模型使用一條ROC曲線視覺化模型結果

2.2 針對每類資料均視覺化一條ROC曲線

針對每個類別的預測效果,也可以使用下面的程式視覺化每個類別的ROC曲線進行分析,執行下面的程式,可獲得如圖3所示的ROC曲線。

## 視覺化每個類別的ROC曲線
lable_names = ["sport","business","politics","tech","entertainment"]
colors = ["r","b","g","m","k",]
linestyles =["-", "--", "-.", ":", "-"]
pre_score = rfc1.predict_proba(test_tfidf)
fig  = plt.figure(figsize=(8,7))
for ii, color in zip(range(pre_score.shape[1]), colors):
    ## 計算繪製ROC曲線的取值
    fpr_ii, tpr_ii, _ = roc_curve(y_test_lb[:,ii], pre_score[:,ii])
    plt.plot(fpr_ii, tpr_ii,color = color,linewidth = 2,
             linestyle = linestyles[ii],
             label = "class:"+lable_names[ii])
plt.plot([0, 1], [0, 1], 'k--')
plt.xlabel("假正率")
plt.ylabel("真正率")
plt.xlim(0, 1)
plt.ylim(0, 1)
plt.grid()
plt.legend()
plt.title("每個類別的ROC曲線")
## 新增區域性放大圖
inset_ax = fig.add_axes([0.3, 0.45, 0.4, 0.4],facecolor="white")
for ii, color in zip(range(pre_score.shape[1]), colors):
    ## 計算繪製ROC曲線的取值
    fpr_ii, tpr_ii, _ = roc_curve(y_test_lb[:,ii], pre_score[:,ii])
    ## 區域性放大圖
    inset_ax.plot(fpr_ii, tpr_ii,color = color,linewidth = 2,
                  linestyle = linestyles[ii])
    inset_ax.set_xlim([-0.01,0.1])
    inset_ax.set_ylim([0.88,1.01])
    inset_ax.grid()
plt.show()

圖3 多分類模型視覺化每個類別的ROC曲線