標籤:

機器學習入門之泰坦尼克號案例

泰坦尼克號案例是一個機器學習入門很好的案例,是一個可以隨著自己的不斷學習而不斷的對模型進行優化的一個案例,這裡就以泰坦尼克號案例來過一遍機器學習的流程。

一 提出問題

和數據分析一樣,得到一個數據的時候,我們想通過這個數據做什麼,或者說我們想讓機器學習什麼,想讓機器做什麼事,這一點是首先要明確的。

這這個案例中,想要達到的就是想通過機器學習的演算法來預測乘客在泰坦尼克號的事故中的生存結果,是否生存下來了。然後通過測試數據集來判斷預測結果的正確度。

二 理解數據

理解數據肯定要先導入數據,而後觀察數據的基本信息,理解數據含義。

#首先導入需要的包import pandas as pdimport numpy as np#導入數據train = pd.read_csv(E:/titanic/train.csv)#訓練集test = pd.read_csv(E:/titanic/test.csv)#測試集al = train.append(test, ignore_index = True)#合併後的數據,方便一起清洗al.info()#看一下數據的基本信息al.head()

因為這個數據集很知名,所以這裡直接放上來各個欄位代表的數據含義了。

圖1 變數名含義1

圖2 變數名含義2

通過對於數據信息的分析,可以發現年齡,座位號,港口,價格這幾列數據是有缺失的。在接下來的數據清理中應該要予以處理。

三 數據清洗

這裡的數據清洗和數據分析的數據清洗大致步驟一樣,只不過有些步驟對於這個數據集是可以省略的。

首先對於缺失值處理一下,如果缺失值是數字類型的,一般用平均數來替代,如果是字元串類型,那麼則用出現最多的那個來替代。

#填充年齡和船票價格al.Age = al.Age.fillna(al.Age.mean())al.Fare = al.Fare.fillna(al.Fare.mean())#填充登船港口,最多的為Sal.Embarked = al.Embarked.fillna(S)#由於座位號那一列缺失過多,所以不能這樣填充#只能填充為U代表Unknow不知道al.Cabin = al.Cabin.fillna(U)

在這樣填充完之後,數據變得規整了,是不是就可以直接拿來給機器學習了呢。

並不行,機器是沒有辦法直接識別字元串所代表的特徵的,那麼對於分類數據而言,這裡最好的是使用一個one -hot的編碼方式,將分類數據分別編碼。

在這裡,性別,港口和船艙等級都是分類數據,需要被重新編碼。

#應用map函數可以對一列數據做同一個操作sexdict = {male:1, female:0}sex = al.Sex.map(sexdict)#把港口也改變一下編碼,應用get_dummies函數embarked = pd.DataFrame()embarked = pd.get_dummies(al.Embarked, prefix = Embarked)#對船艙等級用同樣的方法編碼pclass = pd.DataFrame()pclass = pd.get_dummies(al.Pclass, prefix = Pclass)

接下來對姓名列進行分析,提取姓名中的頭銜特徵。

#觀察數據發現#頭銜前面是逗號,後面是點號#所以建立一個函數分割一下就好了def title1(name): name1 = name.split(,)[1] name2 = name1.split(.)[0] #strip函數移除字元串頭尾指定的字元 name3 = name2.strip() return name3#應用函數titiee = pd.DataFrame()titiee[Title] = al.Name.map(title1)#因為頭銜太多了,所以要分類映射一下#這裡需要統計一共出現過多少個頭銜#然後要知道這些頭銜在國外代表什麼意思#最後將不同的頭銜映射為一樣的titleDict = { "Capt": "Officer", "Col": "Officer", "Major": "Officer", "Jonkheer": "Royalty", "Don": "Royalty", "Sir" : "Royalty", "Dr": "Officer", "Rev": "Officer", "the Countess":"Royalty", "Dona": "Royalty", "Mme": "Mrs", "Mlle": "Miss", "Ms": "Mrs", "Mr" : "Mr", "Mrs" : "Mrs", "Miss" : "Miss", "Master" : "Master", "Lady" : "Royalty" }#把每一個頭銜都映射一遍titiee[Title] = titiee[Title].map(titleDict)#再把頭銜變成onehot編碼titiee = pd.get_dummies(titiee[Title])titiee.head()

接下來從座位號中提取坐席類別,坐席類別就是座位號的首字母,假如為U的話則代表不知道。

seat = pd.DataFrame()seat[seat] = al[Cabin]#提取座位號首字母特徵seat.seat = seat.seat.map(lambda a: a[0])#onehot編碼seat = pd.get_dummies(seat.seat, prefix = Cabin)seat.head()

對船上每個乘客的家庭成員數量進行一個統計。

family = pd.DataFrame()family[family] = al.SibSp + al.Parch + 1family.head()

最後將原始數據複製一份,該修改的修改,該刪除的列刪除,變成一個清洗好的數據。

#把數據複製一份da = train.append(test, ignore_index = True)#做同樣的修改da.Age = da.Age.fillna(da.Age.mean())da.Fare = da.Fare.fillna(da.Fare.mean())da.Embarked = da.Embarked.fillna(S)da.Cabin = da.Cabin.fillna(U)#刪除不需要的列da = da.drop([Name,Pclass,Cabin, Sex, Parch, Embarked, SibSp, Ticket], axis =1)#合併修改後的列da = pd.concat([da, sex, pclass, embarked, titiee, seat, family], axis = 1)da.head()

現在,就把所有的數據清洗工作完成了。

四 模型建立

首先在整個數據中,我們要選擇能夠進入模型的特徵,也就是和乘客生還有關的因素。那麼我們首先簡單的來看一下數據間的相關係數,這一步其實在上一步驟中數據分析的過程中就應嘎可以提前進行的,即通過相關係數來確定最終數據的情況,這裡放到現在來做也是可以的。

import seaborn as snsimport matplotlib.pyplot as pltsns.heatmap(al.corr())plt.show()

圖3 相關係數圖

通過圖我們可以很直觀的看出,年齡和船票價格和是否倖存之間還是有著挺強的相關性的,所以在建立模型的時候要讓這兩個特徵進入,其他的是否一定要進入模型還有待考量。

#把訓練數據集切分出來source = da.loc[0:890, :]pred = da.loc[890:, :]source = source.drop([PassengerId], axis =1 )

開始建立模型,首先試試只有年齡和船票價格時候模型準確度怎麼樣。

#導入演算法from sklearn.linear_model import LogisticRegression#導入交叉驗證的包from sklearn.cross_validation import KFoldpredictors = [Age, Fare]#建立模型model = LogisticRegression()#做交叉驗證kf = KFold(source.shape[0], n_folds = 3, random_state = 1)for train, test in kf: train_predictors = (source[predictors].iloc[train, :]) train_target = source[Survived].iloc[train] model.fit(train_predictors, train_target)#測試一下這個模型的效果model.score(source[predictors].iloc[test, :],source[Survived].iloc[test] )0.69696969696969702

這個模型的效果太低,試試把所有的因素都加進去,看一看效果如何。

sources = source.drop([Survived], axis =1 )#導入演算法from sklearn.linear_model import LogisticRegression#導入交叉驗證的包from sklearn.cross_validation import KFold#建立模型model = LogisticRegression()#做交叉驗證kf = KFold(source.shape[0], n_folds = 3, random_state = 1)for train, test in kf: train_predictors = (sources.iloc[train, :]) train_target = source[Survived].iloc[train] model.fit(train_predictors, train_target)#測試一下這個模型的效果model.score(sources.iloc[test, :],source[Survived].iloc[test] )0.85521885521885521

這個模型的效果還可以,但是有沒有其他的模型了呢,也是有的。

我們現在用的是邏輯回歸模型,下面我們用隨機森林模型試一試會是怎麼樣的。

from sklearn.ensemble import RandomForestClassifierfrom sklearn import cross_validationmodel = RandomForestClassifier(random_state = 1, n_estimators = 100, min_samples_split = 4, min_samples_leaf = 2)kf = KFold(source.shape[0], n_folds = 3, random_state = 1)for train, test in kf: train_predictors = (sources.iloc[train, :]) train_target = source[Survived].iloc[train] model.fit(train_predictors, train_target) #看一下模型效果 model.score(sources.iloc[test, :],source[Survived].iloc[test] )0.84511784511784516

看起來邏輯回歸模型比較好,就用這個吧。

其實另外一個方法就是試一下這兩個模型結合在一起共同決定會不會預測準確率更高。

不過就留待以後了。

用邏輯回歸模型把結果預測出來並保存。

pred = pred.drop([Survived,PassengerId], axis =1 ) pred_Y = model.predict(pred)pred_Y = pred_Y.astype(int)passenger = al.loc[891:, PassengerId]#建立字典,把結果保存preddf = pd.DataFrame({PassengerId:passenger, Survived:pred_Y})preddf.to_csv(titanic.csv, index = False)

最好把結果上傳到kaggle中,可以看到結果並不是特別好,留待以後慢慢優化。

圖4 kaggle結果

機器學習的入門案例就是這樣了~


推薦閱讀:

關於不平衡數據集以及代價敏感學習的探討
關鍵詞提取Part1(A Quick Review)
《大演算:機器學習的終極演演算法將如何改變我們的未來,創造新紀元的文明》
基於NLP的股價預測

TAG:機器學習 |