決策樹(下):泰坦尼克乘客生存預測

決策樹(下):泰坦尼克乘客生存預測

決策樹分類的應用場景有很多,比如在金融行業用決策樹做貸款風險評估,醫療行業用決策樹生成輔助診斷,用sklearn工具解決泰坦尼克乘客生存預測:

sklearn中的決策樹模型

sklearn中自帶的決策樹分類器DecisionTreeClassifier

clf = DecisionTreeClassifier(criterion='entropy')

在構建DecisionTreeClassifier類時,其中一個參數是criterion,決定了構造的分類樹是採用ID3分類是還是CART分類樹,對應的取值分別是entropy或者gini,用criterion=‘entropy’,然後打印clf,看下決策樹在sklearn:

DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=None,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=None,
            splitter='best')

criterion採用不同決策樹算法外,一般建議使用默認參數,默認參數不會限制決策樹的最大深度,不限制葉子節點數,認爲所有分類的權重都相等。

在構造決策樹分類器後,使用fit方法讓分類器進行擬合,使用predict方法對新數據進行預測,得到預測的分類結果,使用score方法得到分類器的準確率

img

泰坦尼克乘客生存預測

究竟有多少人遇難,可以得到部分數據< https://github.com/cystanford/Titanic_Data >,完整的項目代碼見:< https://github.com/cystanford/Titanic_Data/blob/master/titanic_analysis.py >,有兩個數據集csv

  • train.csv是訓練數據集,包含特徵信息和存活與否的標籤
  • test.csv測試數據集,只包含特徵信息

用決策樹分類對訓練集進行訓練,針對測試集中的乘客進行生存預測,並告知分類器的準確率,訓練集中,包括以下字段

img

生存預測的關鍵流程

對訓練集中乘客的生存進行預測,分爲兩個重要階段:

  • 準備階段:首先對訓練集、測試集的數據進行探索,分析數據質量,對數據進行清洗,通過特徵選擇對數據進行降維
  • 分類階段:首先通過訓練集的特徵矩陣、分類結果得到決策樹分類器,然後將分類器應用於測試集,然後對分類器的準確性進行分析,對決策樹模型進行可視化

模塊1:數據探索

如何進行數據探索?需要了解一些函數:

  • 使用info()瞭解數據表的基本情況:行數、列數、每列的數據類型、數據完整度
  • 使用describe()瞭解數據表的統計情況:總數、平均數、標準差、最小值、最大值
  • 使用describe(include=[‘O’])查看字符串類型(非數字)的整體情況
  • 使用head查看前幾行數據
  • 使用tail查看後幾行數據
import pandas as pd
# 數據加載
train_data = pd.read_csv('./Titanic_Data/train.csv')
test_data = pd.read_csv('./Titanic_Data/test.csv')
# 數據探索
print(train_data.info())
print('-'*30)
print(train_data.describe())
print('-'*30)
print(train_data.describe(include=['O']))
print('-'*30)
print(train_data.head())
print('-'*30)
print(train_data.tail())

模塊2:數據清洗

有些字段數據缺失,比如Age年齡字段,是數值型,可以通過平均值進行補齊,Fare爲船票價格,數值型,也可以用其他人購買船票的平均值進行補齊

# 使用平均年齡來填充年齡中的nan值
train_data['Age'].fillna(train_data['Age'].mean(), inplace=True)
test_data['Age'].fillna(test_data['Age'].mean(),inplace=True)
# 使用票價的均值填充票價中的nan值
train_data['Fare'].fillna(train_data['Fare'].mean(), inplace=True)
test_data['Fare'].fillna(test_data['Fare'].mean(),inplace=True)

Cabin爲船艙,有大量缺失值,Embarked爲登錄港口

先觀察Embarked的取值print(train_data['Embarked'].value_counts())

結果如下

S 644
C 168
Q 77

Name:Embarked ,dtype:int64

一共3個登錄港口,其中S港口最多,因此將其餘缺失的Embarked數值設置爲S

# 使用登錄最多的港口來填充登錄港口的nan值
train_data['Embarked'].fillna('S', inplace=True)
test_data['Embarked'].fillna('S',inplace=True)

模塊3:特徵選擇

特徵選擇是分類器的關鍵,特徵選擇不同,得到的分類器也不同

通過數據探索發現,Passengerld爲乘客編號,對分類沒用,可以放棄;

Name爲乘客姓名,對分類沒用,放棄;

Cabin字段缺失值太多,放棄;Ticket字段爲船票號碼,雜亂無章無規律,放棄;其餘的字段包含:Pclass、Sex、Age、SibSp、Parch、Fare分別表示了乘客的船票等級、性別、年齡、親戚數量、船票價格,可能會和乘客的生存預測有關係,具體什麼關係,交給分類器處理

將Pclass、Sex、Age等字段作特徵,放到特徵向量features裏

# 特徵選擇
features = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
train_features = train_data[features]
train_labels = train_data['Survived']
test_features = test_data[features]

特徵值裏有一些是字符串,需要轉成數值類型,比如Sex,有male和female兩種取值,把它變成Sex = male,和Sex = female兩個字段,數值用0或1來表示

同理,Embarked有S,C,O三種可能,三個字段分別是0,1,來表示

使用DictVectorizer類,將可以處理符號化的對象,將符號轉成數子0/1來表示

from sklearn.feature_extraction import DictVectorizer
dvec=DictVectorizer(sparse=False)
train_features=dvec.fit_transform(train_features.to_dict(orient='record'))

fit_transform函數可以將特徵向量轉化爲特徵值矩陣

dvec在轉化後的特徵屬性是怎樣的,即dvec的feature_names_屬性值

print(dvec.feature_names_)

[‘Age’, ‘Embarked=C’, ‘Embarked=Q’, ‘Embarked=S’, ‘Fare’, ‘Parch’, ‘Pclass’, ‘Sex=female’, ‘Sex=male’, ‘SibSp’]

原本是一列的Embarked,變成了“Embarked=C”“Embarked=Q”"Embarked=S"三列,Sex列變成了“Sex=female”"Sex=male"兩列

模塊4:決策樹模型

使用ID3算法,即在創建DecisionTreeClassifier時,設置criterion=‘entropy’,使用fit進行訓練,將特徵值矩陣和分類標識結果作爲參數傳入得到決策樹分類器

from sklearn.tree import DecisionTreeClassifier
# 構造ID3決策樹
clf = DecisionTreeClassifier(criterion='entropy')
# 決策樹訓練
clf.fit(train_features, train_labels)

模塊5 :模型預測 & 評估

預測中,需要得到測試集的特徵值矩陣,然後使用訓練好的決策樹clf進行預測,得到預測結果pred_labels:

test_features=dvec.transform(test_features.to_dict(orient='record'))
# 決策樹預測
pred_labels = clf.predict(test_features)

決策樹提供了score函數可以直接得到準確率,但是不知道真實的預測結果,無法用預測值和真實的預測結果做比較,只能使用訓練集中的數據進行模型評估,使用決策樹自帶的score函數計算:

# 得到決策樹準確率
acc_decision_tree = round(clf.score(train_features, train_labels), 6)
print(u'score準確率爲 %.4lf' % acc_decision_tree)

score準確率爲0.9820

用訓練集做訓練,再用訓練集自身做準確率評估自然很高,但是不能代表決策樹分類器的準確率

因爲我們沒有測試集的實際結果,因此無法用測試集的預測結果與實際結果作對比,如果使用score函數對訓練集的準確率進行統計,正確率會接近於100%,無法對分類器的在實際環境下做準確率的評估

如何同居決策樹分類器的準確率呢?

使用K折交叉驗證方式,交叉驗證是一種常用的驗證分類準確率的方法,原理是拿出大部分樣本進行訓練,少量的用於分類器的驗證,K折交叉驗證就是做K次交叉驗證,每次選取K分之一的數據作爲驗證,其餘作爲訓練,輪流K次,取平均值

K折交叉驗證的原理是:

  • 將數據集平均分割成K個等份
  • 使用1份數據作爲測試數據,其餘作爲訓練數據
  • 計算測試準確率
  • 使用不同的測試集,重複2,3步驟

在sklearn的model_selection模型選擇中提供cross_val_score函數,cross_val_score函數中參數cv代表對原始數據劃分成多少份,就是我們的K值,一般建議K值取10,設cv=10,對比下score和cross_val_score兩種函數的正確率和評估結果:

import numpy as np
from sklearn.model_selection import cross_val_score
# 使用K折交叉驗證 統計決策樹準確率
print(u'cross_val_score準確率爲 %.4lf' % np.mean(cross_val_score(clf, train_features, train_labels, cv=10)))

cross_val_score準確率爲 0.7835

對於不知道測試集實際結果的,使用K折交叉驗證才能知道模型的準確率

模塊6:決策樹可視化

使用Graphviz可視化工具把決策樹呈現出來

安裝Graphviz庫:

1 安裝Graphviz工具,下載地址是:< http://www.graphviz.org/download/ >

2 將 Graphviz添加到環境變量PATH中;

3 需要Graphviz庫,如果沒有可以使用pip install graphviz進行安裝

在程序裏面使用Graphviz對決策樹模型進行呈現得到一個決策樹可視化的PDF文件,可視化結果文件Source.gv.pdf在Github上下載:< https://github.com/cystanford/Titanic_Data >

總結:

import pandas as pd
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier

# 數據加載
train_data = pd.read_csv('./train.csv')
test_data = pd.read_csv('./test.csv')
# 數據探索
print(train_data.info())
print('-'*30)
print(train_data.describe())
print('-'*30)
print(train_data.describe(include=['O']))
print('-'*30)
print(train_data.head())
print('-'*30)
print(train_data.tail())
# 數據清洗
# 使用平均年齡來填充年齡中的 nan 值
train_data['Age'].fillna(train_data['Age'].mean(), inplace=True)
test_data['Age'].fillna(test_data['Age'].mean(),inplace=True)
# 使用票價的均值填充票價中的 nan 值
train_data['Fare'].fillna(train_data['Fare'].mean(), inplace=True)
test_data['Fare'].fillna(test_data['Fare'].mean(),inplace=True)
print(train_data['Embarked'].value_counts())

# 使用登錄最多的港口來填充登錄港口的 nan 值
train_data['Embarked'].fillna('S', inplace=True)
test_data['Embarked'].fillna('S',inplace=True)

# 特徵選擇
features = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
train_features = train_data[features]
train_labels = train_data['Survived']
test_features = test_data[features]

dvec=DictVectorizer(sparse=False)
train_features=dvec.fit_transform(train_features.to_dict(orient='record'))
print(dvec.feature_names_)

# 構造 ID3 決策樹
clf = DecisionTreeClassifier(criterion='entropy')
# 決策樹訓練
clf.fit(train_features, train_labels)

test_features=dvec.transform(test_features.to_dict(orient='record'))
# 決策樹預測
pred_labels = clf.predict(test_features)

# 得到決策樹準確率
acc_decision_tree = round(clf.score(train_features, train_labels), 6)
print(u'score 準確率爲 %.4lf' % acc_decision_tree)

_features, train_labels)

test_features=dvec.transform(test_features.to_dict(orient=‘record’))

決策樹預測

pred_labels = clf.predict(test_features)

得到決策樹準確率

acc_decision_tree = round(clf.score(train_features, train_labels), 6)
print(u’score 準確率爲 %.4lf’ % acc_decision_tree)








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章