前言
前些天學習了一下決策樹算法(ID3、C4.5、cart算法),今天實際練習一下。
數據集、測試集地址:
https://github.com/cystanford/Titanic_Data
原始數據:
train.csv 是訓練數據集,包含特征信息和存活與否的標簽;
test.csv: 測試數據集,只包含特征信息。
我們需要做的,就是使用訓練集的數據,構建決策樹,然后對測試集數據進行預測。
訓練集中的數據特征:
數據分析流程:
接下來我們會按照以上這6個步驟,去對泰坦尼克號乘客進行生存預測。
數據探索:
數據探索,其實就是對現有數據進行分析。比如行數、列數、數據完整度等。
進行數據探索,你需要知道如下幾個函數:
使用info()查看數據表的基本信息:行數、列數、每列的數據類型、數據完整度;
使用describe()了解數據表的統計情況:總數、平均值、標准值、最小值、最大值等;
使用describe(include=['0'])查看字符串(非數字)類型的整體情況
使用head查看前幾行數據(默認5行)
使用tail查看后幾行數據(默認后5行)
接下來我們執行一下這些命令
import pandas as pd # 數據加載 train_data = pd.read_csv('../niki/train.csv')
info()查看數據表基本信息
# 數據探索 print(train_data.info())
可以看到它展示了:行數、數據完整度、數據類型、字段名、數據類型數、內存使用情況。
describe()查看數據表的統計信息:
# 數據探索 print(train_data.describe())
可以看出,它展示的依次是:數據量、平均值、標准差、最小值、還有25%、50%、75%所含的數據、最大值
上面的輸出結果只展示了部分數據,如果想展示全部的數據,只需要在describe方法執行之前,加上上面兩句指令即可:
# 顯示所有列 pd.set_option('display.max_columns', None) # 顯示所有行 pd.set_option('display.max_rows', None)
describe(include=['0'])查看字符串類型整體情況:
# 數據探索 print(train_data.describe(include=['O']))
展示了數據的數量,有多少數據是不等的,出現數量最多的數據是什么,出現了幾次。
head tail查看數據的前幾行和后幾行:
這兩條命令和linux查看文件的命令是一樣的。
# 數據探索 print(train_data.head()) print('-'*50) print(train_data.tail())
數據清洗:
我們對訓練集和測試集中的數據進行探索,可以得知:
Age、Fare、Cabin、Embarked存在缺失,Age數值型,代表年齡。我們可以用平均值補齊,Fare是船票價格,同理。
# 數據清洗 train_data['Age'].fillna(train_data['Age'].mean(), inplace=True) test_data['Age'].fillna(test_data['Age'].mean(), inplace=True) train_data['Fare'].fillna(train_data['Fare'].mean, inplace=True) test_data['Fare'].fillna(test_data['Fare'].mean, inplace=True)
Cabin為船艙信息,由於訓練集和測試集中有大量的缺失數據,所以無法進行補齊。
Embarked是港口信息,我們可以使用value_counts()方法進行觀察:
print(train_data['Embarked'].value_counts())
發現S的占比超過了70%,所以我們可以用s值進行補齊
train_data['Embarked'].fillna('S', inplace=True) test_data['Embarked'].fillna('S', inplace=True)
特征選擇:
通過數據探索,我們可以發現PassengerId為乘客的編號,對分類沒有作用,可以舍棄,Name為乘客姓名,也可以舍棄,Cabin缺失值太多,可以舍棄,Ticket為船票號碼,雜亂無章,可以舍棄,剩余的字段包括:Pclass、Sex、Age、SibSp、Parch 和 Fare,這些屬性分別表示了乘客的船票等級、性別、年齡、親戚數量以及船票價格,可能會和乘客的生存預測分類有關系。
我們現將這些值放到特征向量里:
# 特征選擇 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 來表示。我們可以用klearn 特征選擇中的 DictVectorizer 類進行上述操作:
from sklearn.feature_extraction import DictVectorizer dvec = DictVectorizer(sparse=False) train_features = dvec.fit_transform(train_features.to_dict(orient='record'))
fit_transfrom可以將特征向量轉換成特征矩陣,然后我們可以通過查看dvec的feature_name_屬性來獲取特征值。
這樣我們就得到了一個10個特征值,891個樣本的10列的特征矩陣。
決策樹模型:
我們可以使用ID3算法構建決策樹,即創建DecisionTreeClassifier的時候,設置criterion='entropy'
from sklearn.tree import DecisionTreeClassifier # 構造ID3決策樹 clf = DecisionTreeClassifier(criterion='entropy') # 決策樹訓練 clf.fit(train_features, train_labels)
模型的預測 & 評估:
我們首先應該得到測試集的特征矩陣,然后使用訓練好的clf樹進行預測。
test_features=dvec.transform(test_features.to_dict(orient='record')) # 決策樹預測 pred_labels = clf.predict(test_features)
在模型評估中,我們可以使用決策樹的score函數得到准確率,但是由於我們不知道測試集中的結果,所以我們這里使用訓練集的數據,進行一下預測。
但是這么做顯然是不准確的,因為我們的決策樹是通過訓練集數據構建出來的。所以它的正確率會趨近於100%,那么有沒有什么方法可以在不知道測試機數據結果的時候,來統計決策樹的准確率呢?
這里就會使用k折交叉驗證的方式。
-
- K折交叉驗證是這樣的,我們將整個訓練集分成k等份
- 使用其中的1份作為測試數據,其余的數據作為訓練數據
- 計算測試數據的准確性
- 使用不同的訓練集重復2、3動作
sklearn的model_selection模型中,就提供了用於k折交叉驗證的函數,cross_val_score,參數cv代表將原始數據划分成多少份。
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)))
可以看出,結果差異還是比較大的
決策樹可視化:
我們可以用Grapviz進行決策樹的可視化:
import graphviz from sklearn import tree # 決策樹可視化 dot_data = tree.export_graphviz(clf, out_file=None) graph = graphviz.Source(dot_data) graph.view()
結果:
決策樹下載地址:https://github.com/cystanford/Titanic_Data