天天看點

【機器學習執行個體】Titanic生存預測

資料集及代碼連結:https://github.com/CCH21/Lab_MLGroup_Tasks/tree/master/Task_Titanic

資料集概述

  如下圖所示,Titanic資料集共包含有三個csv檔案,其中

train.csv

是訓練集,

test.csv

是待預測的測試集,

gender_submission.csv

是測試集的真實結果。

【機器學習執行個體】Titanic生存預測
【機器學習執行個體】Titanic生存預測
【機器學習執行個體】Titanic生存預測
【機器學習執行個體】Titanic生存預測

資料描述

import pandas as pd
from IPython.display import display

# 檢視訓練集和測試集
training_set = pd.read_csv('train.csv')
test_set = pd.read_csv('test.csv')
display(training_set)
display(test_set)
           
【機器學習執行個體】Titanic生存預測
【機器學習執行個體】Titanic生存預測

特征選擇與資料預處理

  首先,我們需要檢視一下訓練集和測試集的特征值缺失情況。

# 檢視訓練集各特征的缺失情況
for column in training_set.columns:
    print('%-15s%-10.4f%-3d' % (column, training_set[column].count() / len(training_set), training_set[column].count()))
           
【機器學習執行個體】Titanic生存預測
# 檢視測試集各特征的缺失情況
for column in test_set.columns:
    print('%-15s%-10.4f%-3d' % (column, test_set[column].count() / len(test_set), test_set[column].count()))
           
【機器學習執行個體】Titanic生存預測

  可以看出,在訓練集中,

Age

,

Cabin

Embarked

特征是有缺失值的,其中

Cabin

的缺失值占到了超過77%的比例。在測試集中,

Age

,

Fare

Cabin

特征有缺失值。

  觀察資料。

Cabin

的缺失值過多,這時有兩種解決方案,一是給所有的缺失值标記上

Unknown

,二是直接删除這一特征。由于船艙号比較複雜,難以進行分析,是以選擇直接删除這一特征列。

PassengerID

肯定與最終的預測結果無關,是以删除此列。

Ticket

特征同樣難以分析,是以删掉。比較特殊的是

Name

一列,它其實包含了一些人物的性别、社會地位等資訊,可以保留但不易分析。其實,性别與社會地位這方面的資訊,我們可以從

Sex

Fare

等特征中得知,故删除

Name

列。

# 删除PassengerId, Name, Ticket, Cabin特征
training_set = training_set.drop(columns=['PassengerId', 'Name', 'Ticket', 'Cabin'])
test_set = test_set.drop(columns=['PassengerId', 'Name', 'Ticket', 'Cabin'])
display(training_set)
display(test_set)
           
【機器學習執行個體】Titanic生存預測
【機器學習執行個體】Titanic生存預測

  接下來是對缺失值的處理。目前訓練集還有兩個特征值有缺失值,分别是

Age

Embarked

。對于

Age

特征,我們可以用訓練集中

Age

一列的平均值來填補完整。對于

Embarked

特征,由于隻有兩個樣本有缺失值,是以可以直接删除這兩個樣本。

# 用訓練集Age一列的平均數填補Age缺失值
training_set['Age'] = training_set['Age'].fillna(training_set['Age'].mean())
# 去除訓練集中有缺失值的樣本
training_set.dropna(axis=0,inplace=True)
display(training_set)
           
【機器學習執行個體】Titanic生存預測

  再次檢查訓練集,可以發現所有的樣本的特征值都是完整無空缺的。

# 檢查訓練集的缺失情況
for column in training_set.columns:
    print('%-15s%-10.4f%-3d' % (column, training_set[column].count() / len(training_set), training_set[column].count()))
           
【機器學習執行個體】Titanic生存預測

  對于測試集的空缺值,我們不能選擇删除樣本的方式。通過觀察資料集可以發現,

Fare

一列有一個頻繁出現的

8.05

。由于

Fare

一列缺失值不多,是以選擇用衆數填補。

Age

一列的缺失值仍然選擇使用平均值填補。

# 處理測試集的缺失值
# 用測試集Fare一列的衆數填補Fare缺失值
test_set['Fare'] = test_set['Fare'].fillna(test_set['Fare'].dropna().mode()[0])
# 用測試集Age一列的平均數填補Age缺失值
test_set['Age'] = test_set['Age'].fillna(test_set['Age'].mean())
display(test_set)
           
【機器學習執行個體】Titanic生存預測
# 檢查測試集的缺失情況
for column in test_set.columns:
    print('%-15s%-10.4f%-3d' % (column, test_set[column].count() / len(test_set), test_set[column].count()))
           
【機器學習執行個體】Titanic生存預測

  接下來我們加載存活結果資料集,并且指定

X_train

,

X_test

,

y_train

,

y_test

# 加載存活結果資料集
result_set = pd.read_csv('gender_submission.csv')
display(result_set)
           
【機器學習執行個體】Titanic生存預測
X_train = training_set.drop(columns=['Survived'])
y_train = training_set['Survived']
X_test = test_set
y_test = result_set.drop(columns=['PassengerId'])
display(X_train)
display(y_train)
display(X_test)
display(y_test)
           
【機器學習執行個體】Titanic生存預測
【機器學習執行個體】Titanic生存預測
【機器學習執行個體】Titanic生存預測

  下面我們利用

sklearn.feature_extraction

中的

DictVectorizer

特征轉換器,将不為數值型的特征進行轉換。轉換特征後,類别型特征都單獨剝離出來,獨成一列特征,數值型特征則保持不變。

# 使用特征轉換器
from sklearn.feature_extraction import DictVectorizer

vec = DictVectorizer(sparse=False)
X_train = vec.fit_transform(X_train.to_dict(orient='record'))
print(vec.feature_names_)
X_test = vec.transform(X_test.to_dict(orient='record'))
print(vec.feature_names_)
           
【機器學習執行個體】Titanic生存預測

使用機器學習模型預測并且進行模型評估

  這裡我選擇了兩個模型,分别是k-NN分類器和決策樹分類器。

# 使用決策樹分類器模型
from sklearn.tree import DecisionTreeClassifier

dtc = DecisionTreeClassifier()
dtc.fit(X_train, y_train)
y_predict = dtc.predict(X_test)
print(y_predict)
           
【機器學習執行個體】Titanic生存預測
from sklearn.metrics import classification_report

print('Training set score: {:.2f}'.format(dtc.score(X_train, y_train)))
print('Test set score: {:.2f}'.format(dtc.score(X_test, y_test)))
# 輸出更加詳細的分類性能
print(classification_report(y_predict, y_test, target_names=['died', 'survived']))
           
【機器學習執行個體】Titanic生存預測

  決策樹分類器的預測準确度在77%左右,并且識别遇難者的準确率要優于識别幸存者。

# 使用k-NN分類器模型
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt

training_accuracy = []
test_accuracy = []
neighbors_settings = range(1, 11)
for n_neighbors in neighbors_settings:
    knn = KNeighborsClassifier(n_neighbors=n_neighbors)
    knn.fit(X_train, y_train)
    # 記錄訓練集精度
    training_accuracy.append(knn.score(X_train, y_train))
    # 記錄泛化精度
    test_accuracy.append(knn.score(X_test, y_test))

plt.plot(neighbors_settings, training_accuracy, label='training accuracy')
plt.plot(neighbors_settings, test_accuracy, label='test accuracy')
plt.ylabel('Accuracy')
plt.xlabel('n_neighbors')
plt.legend()
           
【機器學習執行個體】Titanic生存預測

  通過改變

n_neighbors

的值(範圍為區間

[1, 10]

)建立不同的k-NN分類器,并且記錄其訓練集精度和泛化精度,繪制出折線圖。從折線圖中可以看出,當

n_neighbors = 5

時,泛化精度最高。

knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
y_predict = knn.predict(X_test)
print(y_predict)
print('Training set score: {:.2f}'.format(knn.score(X_train, y_train)))
print('Test set score: {:.2f}'.format(knn.score(X_test, y_test)))
           
【機器學習執行個體】Titanic生存預測

  k-NN分類器的預測準确率大概在72%左右,稍遜于決策樹分類器。