機器學習(入門練習):Kaggle和泰坦尼克號預測
一、機器學習、雲計算、大數據和機器學習演算法
機器學習最重要的前提:雲計算、大數據和機器學習演算法。
- 人工智慧可以分為三層:
- 雲計算和大數據結合的案例:
- 機器學習的步驟:
1、提出問題:生活和工作中遇到的問題
2、理解數據:採集數據(根據問題來採集)、導入數據(Excel或者資料庫中)、查看數據集信息(大概了解和認識)
3、數據清洗:預處理(類型轉化、缺失),特徵工程
4、構建模型:將訓練數據提取的特徵放入演算法中
5、模型評估:測試數據來評估,看看預測結果如何
6、方案實施:將分析結果來撰寫數據分析報告
二、泰坦尼克號案例:
2.1 研究的問題是:什麼樣的人在泰坦尼克號中更容易存活?
泰坦尼克號的航行路線
2.2 採集數據
# 忽略警告提示import warningswarnings.filterwarnings(ignore)#導入處理數據包import numpy as npimport pandas as pd#導入數據#訓練數據集train = pd.read_csv("./train.csv")#測試數據集test = pd.read_csv("./test.csv")#這裡要記住訓練數據集有891條數據,方便後面從中拆分出測試數據集用於提交Kaggle結果print (訓練數據集:,train.shape,測試數據集:,test.shape)rowNum_train=train.shape[0]rowNum_test=test.shape[0]print(kaggle訓練數據集有多少行數據:,rowNum_train, ,kaggle測試數據集有多少行數據:,rowNum_test,)#合併數據集,方便同時對兩個數據集進行清洗full = train.append( test , ignore_index = True )print (合併後的數據集:,full.shape)
2.3 查看數據集信息
#查看數據full.head()#獲取數據類型列的描述統計信息full.describe()# 查看每一列的數據類型,和數據總數full.info()
2.4 數據清洗
2.4.1 數據預處理
在前面,理解數據階段,我們發現數據總共有1309行。 其中數據類型列:年齡(Age)、船艙號(Cabin)裡面有缺失數據。 字元串列:登船港口(Embarked)、船艙號(Cabin)裡面有缺失數據。
這為我們下一步數據清洗指明了方向,只有知道哪些數據缺失數據,我們才能有針對性的處理。
很多機器學習演算法為了訓練模型,要求所傳入的特徵中不能有空值。
如果是數值類型,用平均值取代
如果是分類數據,用最常見的類別取代
使用模型預測缺失值,例如:K-NN
我們發現數據總共有1309行。其中數據類型列:年齡(Age)、船艙號(Cabin)裡面有缺失數據:1)年齡(Age)裡面數據總數是1046條,缺失了1309-1046=263,缺失率263/1309=20%2)船票價格(Fare)裡面數據總數是1308條,缺失了1條數據對於數據類型,處理缺失值最簡單的方法就是用平均數來填充缺失值print(處理前:)full.info()#年齡(Age)full[Age]=full[Age].fillna( full[Age].mean() )#船票價格(Fare)full[Fare] = full[Fare].fillna( full[Fare].mean() )print(處理紅後:)full.info()#檢查數據處理是否正常full.head()總數據是1309字元串列:1)登船港口(Embarked)裡面數據總數是1307,只缺失了2條數據,缺失比較少2)船艙號(Cabin)裡面數據總數是295,缺失了1309-295=1014,缺失率=1014/1309=77.5%,缺失比較大#登船港口(Embarked):查看裡面數據長啥樣出發地點:S=英國南安普頓Southampton途徑地點1:C=法國 瑟堡市Cherbourg途徑地點2:Q=愛爾蘭 昆士敦Queenstownfull[Embarked].head()分類變數Embarked,看下最常見的類別,用其填充full[Embarked].value_counts()從結果來看,S類別最常見。我們將缺失值填充為最頻繁出現的值:S=英國南安普頓Southamptonfull[Embarked] = full[Embarked].fillna( S )#船艙號(Cabin):查看裡面數據長啥樣full[Cabin].head()#缺失數據比較多,船艙號(Cabin)缺失值填充為U,表示未知(Uknow) full[Cabin] = full[Cabin].fillna( U )#查看最終缺失值處理情況,記住生成情況(Survived)這裡一列是我們的標籤,用來做機器學習預測的,不需要處理這一列full.info()
2.4.2 特徵提取
- 查看數據類型,分為3種數據類型。並對類別(超過兩個類別)數據處理:用數值代替類別,對於超過兩類別的數據進行One-hot編碼
- 特徵工程:
業界流傳: 數據和特徵決定機器學習的上限, 模型和演算法只是逼近機器學習的上限
- 案例中涉及的數據類型如下:
- Python中特徵提取中用到的兩個函數:
map 對pandas中一維數據series中的每個數據應用自定義的函數進行計算
get-dummies進行one-hot編碼。
1.數值類型:乘客編號(PassengerId),年齡(Age),船票價格(Fare),同代直系親屬人數(SibSp),不同代直系親屬人數(Parch)2.時間序列:無3.分類數據:1)有直接類別的乘客性別(Sex):男性male,女性female登船港口(Embarked):出發地點S=英國南安普頓Southampton,途徑地點1:C=法國 瑟堡市Cherbourg,出發地點2:Q=愛爾蘭 昆士敦Queenstown客艙等級(Pclass):1=1等艙,2=2等艙,3=3等艙2)字元串類型:可能從這裡面提取出特徵來,也歸到分類數據中乘客姓名(Name)客艙號(Cabin)船票編號(Ticket)full.info()
- 案例中的分類數據:有直接類別的
乘客性別(Sex): 男性male,女性female
登船港口(Embarked):出發地點S=英國南安普頓Southampton,途徑地點1:C=法國 瑟堡市Cherbourg,出發地點2:Q=愛爾蘭 昆士敦Queenstown
客艙等級(Pclass):1=1等艙,2=2等艙,3=3等艙
1)性別
#查看性別數據這一列full[Sex].head()將性別的值映射為數值男(male)對應數值1,女(female)對應數值0sex_mapDict={male:1, female:0}#map函數:對Series每個數據應用自定義的函數計算full[Sex]=full[Sex].map(sex_mapDict)full.head()
2)登船港口
登船港口(Embarked)的值是:出發地點:S=英國南安普頓Southampton途徑地點1:C=法國 瑟堡市Cherbourg途徑地點2:Q=愛爾蘭 昆士敦Queenstown#查看該類數據內容full[Embarked].head()#存放提取後的特徵embarkedDf = pd.DataFrame()使用get_dummies進行one-hot編碼,產生虛擬變數(dummy variables),列名前綴是EmbarkedembarkedDf = pd.get_dummies( full[Embarked] , prefix=Embarked )embarkedDf.head()#添加one-hot編碼產生的虛擬變數(dummy variables)到泰坦尼克號數據集full?full = pd.concat([full,embarkedDf],axis=1)因為已經使用登船港口(Embarked)進行了one-hot編碼產生了它的虛擬變數(dummy variables)所以這裡把登船港口(Embarked)刪掉full.drop(Embarked,axis=1,inplace=True)full.head()
3)客艙等級
客艙等級(Pclass):1=1等艙,2=2等艙,3=3等艙#存放提取後的特徵pclassDf = pd.DataFrame()#使用get_dummies進行one-hot編碼,列名前綴是PclasspclassDf = pd.get_dummies( full[Pclass] , prefix=Pclass )pclassDf.head()#添加one-hot編碼產生的虛擬變數(dummy variables)到泰坦尼克號數據集fullfull = pd.concat([full,pclassDf],axis=1)#刪掉客艙等級(Pclass)這一列full.drop(Pclass,axis=1,inplace=True)full.head()
- 分類數據:字元串類型
字元串類型:可能從這裡面提取出特徵來,也歸到分類數據中,這裡數據有:
- 乘客姓名(Name)
- 客艙號(Cabin)
- 船票編號(Ticket)
1)從姓名中提取頭銜
查看姓名這一列長啥樣注意到在乘客名字(Name)中,有一個非常顯著的特點:乘客頭銜每個名字當中都包含了具體的稱謂或者說是頭銜,將這部分信息提取出來後可以作為非常有用一個新變數,可以幫助我們進行預測。例如:Braund, Mr. Owen HarrisHeikkinen, Miss. LainaOliva y Ocana, Dona. FerminaPeter, Master. Michael Jfull[ Name ].head()定義函數:從姓名中獲取頭銜def getTitle(name): str1=name.split( , )[1] #Mr. Owen Harris str2=str1.split( . )[0]#Mr #strip() 方法用於移除字元串頭尾指定的字元(默認為空格) str3=str2.strip() return str3#存放提取後的特徵titleDf = pd.DataFrame()#map函數:對Series每個數據應用自定義的函數計算titleDf[Title] = full[Name].map(getTitle)titleDf.head()定義以下幾種頭銜類別:Officer政府官員Royalty王室(皇室)Mr已婚男士Mrs已婚婦女Miss年輕未婚女子Master有技能的人/教師#姓名中頭銜字元串與定義頭銜類別的映射關係title_mapDict = { "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" }#map函數:對Series每個數據應用自定義的函數計算titleDf[Title] = titleDf[Title].map(title_mapDict)#使用get_dummies進行one-hot編碼titleDf = pd.get_dummies(titleDf[Title])titleDf.head()#添加one-hot編碼產生的虛擬變數(dummy variables)到泰坦尼克號數據集fullfull = pd.concat([full,titleDf],axis=1)#刪掉姓名這一列full.drop(Name,axis=1,inplace=True)full.head()
2)從客艙號中提取客艙類別
客艙號的首字母是客艙的類別#查看客艙號的內容full[Cabin].head()#存放客艙號信息cabinDf = pd.DataFrame()客場號的類別值是首字母,例如:C85 類別映射為首字母Cfull[ Cabin ] = full[ Cabin ].map( lambda c : c[0] )##使用get_dummies進行one-hot編碼,列名前綴是CabincabinDf = pd.get_dummies( full[Cabin] , prefix = Cabin )cabinDf.head()#添加one-hot編碼產生的虛擬變數(dummy variables)到泰坦尼克號數據集fullfull = pd.concat([full,cabinDf],axis=1)#刪掉客艙號這一列full.drop(Cabin,axis=1,inplace=True)full.head()
3)建立家庭人數和家庭類別
#存放家庭信息familyDf = pd.DataFrame()家庭人數=同代直系親屬數(Parch)+不同代直系親屬數(SibSp)+乘客自己(因為乘客自己也是家庭成員的一個,所以這裡加1)familyDf[ FamilySize ] = full[ Parch ] + full[ SibSp ] + 1家庭類別:小家庭Family_Single:家庭人數=1中等家庭Family_Small: 2<=家庭人數<=4大家庭Family_Large: 家庭人數>=5#if 條件為真的時候返回if前面內容,否則返回0familyDf[ Family_Single ] = familyDf[ FamilySize ].map( lambda s : 1 if s == 1 else 0 )familyDf[ Family_Small ] = familyDf[ FamilySize ].map( lambda s : 1 if 2 <= s <= 4 else 0 )familyDf[ Family_Large ] = familyDf[ FamilySize ].map( lambda s : 1 if 5 <= s else 0 )familyDf.head()#添加one-hot編碼產生的虛擬變數(dummy variables)到泰坦尼克號數據集fullfull = pd.concat([full,familyDf],axis=1)full.head()#目前數據集中的特徵個數:full.shape
2.4.3 特徵選擇
選擇哪些對數據模型有影響的特徵。本案例選擇的方法為相關係數法
1)相關係數法:計算各個特徵的相關係數
#相關性矩陣corrDf = full.corr() corrDf查看各個特徵與生成情況(Survived)的相關係數,ascending=False表示按降序排列corrDf[Survived].sort_values(ascending =False)
根據各個特徵與生成情況(Survived)的相關係數大小,我們選擇了這幾個特徵作為模型的輸入:
頭銜(前面所在的數據集titleDf)、客艙等級(pclassDf)、家庭大小(familyDf)、船票價格(Fare)、船艙號(cabinDf)、登船港口(embarkedDf)、性別(Sex)
#特徵選擇full_X = pd.concat( [titleDf,#頭銜 pclassDf,#客艙等級 familyDf,#家庭大小 full[Fare],#船票價格 cabinDf,#船艙號 embarkedDf,#登船港口 full[Sex]#性別 ] , axis=1 )full_X.head()
2.5 構建模型
用訓練數據和某個機器學習演算法得到機器學習模型,用測試數據評估模型
- 建立訓練數據集和測試數據集
1)坦尼克號測試數據集因為是我們最後要提交給Kaggle的,裡面沒有生存情況的值,所以不能用於評估模型。我們將Kaggle泰坦尼克號項目給我們的測試數據,叫做預測數據集(記為pred,也就是預測英文單詞predict的縮寫)。也就是我們使用機器學習模型來對其生存情況就那些預測。2)我們使用Kaggle泰坦尼克號項目給的訓練數據集,做為我們的原始數據集(記為source),從這個原始數據集中拆分出訓練數據集(記為train:用於模型訓練)和測試數據集(記為test:用於模型評估)。#原始數據集有891行sourceRow=891sourceRow是我們在最開始合併數據前知道的,原始數據集有總共有891條數據從特徵集合full_X中提取原始數據集提取前891行數據時,我們要減去1,因為行號是從0開始的。#原始數據集:特徵source_X = full_X.loc[0:sourceRow-1,:]#原始數據集:標籤source_y = full.loc[0:sourceRow-1,Survived] #預測數據集:特徵pred_X = full_X.loc[sourceRow:,:]確保這裡原始數據集取的是前891行的數據,不然後面模型會有錯誤#原始數據集有多少行print(原始數據集有多少行:,source_X.shape[0])#預測數據集大小print(原始數據集有多少行:,pred_X.shape[0])從原始數據集(source)中拆分出訓練數據集(用於模型訓練train),測試數據集(用於模型評估test)train_test_split是交叉驗證中常用的函數,功能是從樣本中隨機的按比例選取train data和test datatrain_data:所要劃分的樣本特徵集train_target:所要劃分的樣本結果test_size:樣本佔比,如果是整數的話就是樣本的數量from sklearn.cross_validation import train_test_split #建立模型用的訓練數據集和測試數據集train_X, test_X, train_y, test_y = train_test_split(source_X , source_y, train_size=.8)#輸出數據集大小print (原始數據集特徵:,source_X.shape, 訓練數據集特徵:,train_X.shape , 測試數據集特徵:,test_X.shape)print (原始數據集標籤:,source_y.shape, 訓練數據集標籤:,train_y.shape , 測試數據集標籤:,test_y.shape)
- 選擇機器學習演算法及訓練模型
#第1步:導入演算法from sklearn.linear_model import LogisticRegression#第2步:創建模型:邏輯回歸(logisic regression)model = LogisticRegression()#第3步:訓練模型model.fit( train_X , train_y )
2.6 評估模型
# 分類問題,score得到的是模型的正確率model.score(test_X , test_y )
2.7 方案實施
使用預測數據集到底預測結果,並保存到csv文件中。
#使用機器學習模型,對預測數據集中的生存情況進行預測pred_Y = model.predict(pred_X)生成的預測值是浮點數(0.0,1,0)但是Kaggle要求提交的結果是整型(0,1)所以要對數據類型進行轉換pred_Y=pred_Y.astype(int)#乘客idpassenger_id = full.loc[sourceRow:,PassengerId]#數據框:乘客id,預測生存情況的值predDf = pd.DataFrame( { PassengerId: passenger_id , Survived: pred_Y } )predDf.shapepredDf.head()#保存結果predDf.to_csv( titanic_pred.csv , index = False )
總結:
結合泰坦尼克號案例總結機器學習的步驟
推薦閱讀:
※開始做一件事情的最好時刻,是現在
※20180226上周文章更新匯總
※霍金已逝,這些物理學家也慢慢被淡忘了
※數據分析師入門
※沒有比腳更長的路,沒有比人更高的山