2017年7月12日 星期三

[Toolkit] Keras - 鐵達尼號旅客資料及介紹

Source From Here (Ch11-12) 
Preface 
鐵達尼號的沉沒是歷史悲劇. 1912 年 4 月 15 日 鐵達尼在首航時撞上冰山沉沒, 乘客和船員共 2224 人, 造成 1502 人死亡. 這場悲劇震撼國際社會並未船舶制定了更好的安全規章. 鐵達尼號旅客資料完整保留下來. 這裡將利用 MLP (Multiple Layer Perception) 訓練模型來預測每一位乘客的存活率. 

下載鐵達尼號旅客資料集 
資料可以 這裡 下載. 這邊下載後分為以下兩個檔案並置放於目錄 datas 下: 
titan_train.csv: 訓練資料
titan_test.csv: 測試資料

STEP1. 使用 Pnadas dataframe 讀取資料 
這邊使用 pandas 的 API:read_csv 讀入資料: 
- ch11_1.py 
  1. import numpy as np  
  2. import pandas as pd  
  3.   
  4. TRAIN_FILE_PATH='datas/titan_train.csv'  
  5. TEST_FILE_PATH='datas/titan_test.csv'  
  6.   
  7. train_df = pd.read_csv(TRAIN_FILE_PATH)  
  8. test_df = pd.read_csv(TEST_FILE_PATH)  
接著我們可以如下檢視資料: 
>>> from ch11_1 import *
>>> train_df.info()

RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId 891 non-null int64

Survived 891 non-null int64 // 是否生存? 0=否; 1=是
Pclass 891 non-null int64 // 艙等. 1=頭等艙; 2=二等艙; 3=三等艙
Name 891 non-null object // 姓名
Sex 891 non-null object // 性別. female/male
Age 714 non-null float64 // 年齡
SibSp 891 non-null int64 // 手足或配偶也在船上人數
Parch 891 non-null int64 // 雙親或子女也在船上人數
Ticket 891 non-null object // 車票號碼
Fare 891 non-null float64 // 旅客費用
Cabin 204 non-null object // 艙位號碼
Embarked 889 non-null object // 登船港口. C=Cherbourg, Q=Queenstown, S=Southampton
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB

STEP2. 進行資料前處理 
底下透過 DataFrame 上的 [] 運算子取出有興趣的欄位: 
  1. # Headers: PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked  
  2. # Filter out 'Ticket''PassengerId' and 'Cabin' columns  
  3. cols = ['Survived','Pclass','Name','Sex','Age','SibSp','Parch','Fare','Embarked']  
  4. train_df = train_df[cols]  
  5.   
  6. # Show top 2 records  
  7. print("\t[Info] Show top 2 records:")  
  8. pprint(train_df.as_matrix()[:2])  
  9. print("")  
以上欄位還有以下問題, 必須進行前處理: 
* Name: 姓名欄位在預測階段會使用, 但是訓練時不需要, 要移除.
* Age: 有幾筆資料是 null 值, 這邊會將 null 改為平均值.
* Sex: 欄位是文字. 會將轉換成 0, 1 值表示.
* Embarked: 欄位是文字, 這邊會使用 Onehot Encoding 進行轉換.

轉換過程如下: 
  1. # Remove column 'Name'  
  2. train_df.drop(['Name'], axis=1)  
  3.   
  4. # Show number of rows with null value  
  5. print("\t[Info] Show number of rows with null value:")  
  6. print(train_df.isnull().sum())  
  7. print("")  
  8.   
  9. # Fill null with age mean value on 'Age' column  
  10. print("\t[Info] Handle null value of Age column...")  
  11. age_mean = train_df['Age'].mean()  
  12. train_df['Age'] = train_df['Age'].fillna(age_mean)  
  13.   
  14. # Show number of rows with null value  
  15. print("\t[Info] Show number of rows with null value:")  
  16. print(train_df.isnull().sum())  
  17. print("")  
  18.   
  19. print("\t[Info] Translate value of column Sex into (0,1)...")  
  20. train_df['Sex'] = train_df['Sex'].map({'female':0'male':0}).astype(int)  
  21.   
  22. print("\t[Info] OneHot Encoding on column Embarked...")  
  23. train_df = pd.get_dummies(data=train_df, columns=['Embarked'])  
  24.   
  25. # Show top 2 records  
  26. print("\t[Info] Show top 2 records:")  
  27. pprint(train_df.as_matrix()[:2])  
  28. print("")  
STEP3. 將 dataframe 轉換為 array 
  1. ndarray = train_df.values  
  2. print("\t[Info] Translate into ndarray(%s) with shape=%s" % (ndarray.__class__, str(ndarray.shape)))  
  3. print("\t[Info] Show top 2 records:\n%s\n" % (ndarray[:2]))  
  4.   
  5. # Separate labels with features  
  6. Label = ndarray[:,0]  
  7. Features = ndarray[:,1:]  
STEP4. 將 ndarray 特徵欄位進行標準化 
我們將使用 sklearn 的 preprocessing 模組進行特徵值標準化: 
  1. # Normalized features  
  2. print("\t[Info] Normalized features...")  
  3. from sklearn import preprocessing  
  4. minmax_scale = preprocessing.MinMaxScaler(feature_range=(01))  
  5. scaledFeatures = minmax_scale.fit_transform(Features)  
  6. print("\t[Info] Show top 2 records:\n%s\n" % (scaledFeatures[:2]))  
STEP5. 切分資料為訓練資料與測試資料 
我們將以 8:2 比例切分訓練資料與測試資料: 
  1. # Splitting data into training/testing part  
  2. print("\t[Info] Split data into training/testing part")  
  3. msk = np.random.rand(len(scaledFeatures)) < 0.8  
  4. trainFeatures = scaledFeatures[msk]  
  5. trainLabels = Label[msk]  
  6. testFeatures = scaledFeatures[~msk]  
  7. testLabels = Label[~msk]  
  8. print("\t[Info] Total %d training instances; %d testing instances!" % (trainFeatures.shape[0], testFeatures.shape[0]))  
STEP6. 包裝前處理流程為函式 preprocessData: 
  1. def preprocessData(data_df, sRatio=None):  
  2.     r'''  
  3.     Preprocess data frame  
  4.   
  5.     @param data_df(DataFrame):  
  6.         Training DataFrame  
  7.   
  8.     @param sRatio(float):  
  9.         if splitRation is not None:  
  10.             (train_data, train_label, test_data, test_label)  
  11.         else:  
  12.             (train_data, train_label)  
  13.     '''  
  14.     # Remove column 'Name'  
  15.     data_df = data_df.drop(['Name'], axis=1)  
  16.   
  17.     # Show number of rows with null value  
  18.     print("\t[Info] Show number of rows with null value:")  
  19.     print(data_df.isnull().sum())  
  20.     print("")  
  21.   
  22.     # Fill null with age mean value on 'Age' column  
  23.     print("\t[Info] Handle null value of Age column...")  
  24.     age_mean = data_df['Age'].mean()  
  25.     data_df['Age'] = data_df['Age'].fillna(age_mean)  
  26.   
  27.     # Show number of rows with null value  
  28.     print("\t[Info] Show number of rows with null value:")  
  29.     print(data_df.isnull().sum())  
  30.     print("")  
  31.   
  32.     print("\t[Info] Translate value of column Sex into (0,1)...")  
  33.     data_df['Sex'] = data_df['Sex'].map({'female':0'male':0}).astype(int)  
  34.   
  35.     print("\t[Info] OneHot Encoding on column Embarked...")  
  36.     data_df = pd.get_dummies(data=data_df, columns=['Embarked'])  
  37.   
  38.     # Show top 2 records  
  39.     print("\t[Info] Show top 2 records:")  
  40.     pprint(data_df.as_matrix()[:2])  
  41.     print("")  
  42.   
  43.     ndarray = data_df.values  
  44.     print("\t[Info] Translate into ndarray(%s) with shape=%s" % (ndarray.__class__, str(ndarray.shape)))  
  45.     print("\t[Info] Show top 2 records:\n%s\n" % (ndarray[:2]))  
  46.   
  47.     # Separate labels with features  
  48.     Label = ndarray[:,0]  
  49.     Features = ndarray[:,1:]  
  50.   
  51.     # Normalized features  
  52.     print("\t[Info] Normalized features...")  
  53.     from sklearn import preprocessing  
  54.     minmax_scale = preprocessing.MinMaxScaler(feature_range=(01))  
  55.     scaledFeatures = minmax_scale.fit_transform(Features)  
  56.     print("\t[Info] Show top 2 records:\n%s\n" % (scaledFeatures[:2]))  
  57.   
  58.     if sRatio:  
  59.         # Splitting data into training/testing part  
  60.         print("\t[Info] Split data into training/testing part")  
  61.         msk = np.random.rand(len(scaledFeatures)) < sRatio  
  62.         trainFeatures = scaledFeatures[msk]  
  63.         trainLabels = Label[msk]  
  64.         testFeatures = scaledFeatures[~msk]  
  65.         testLabels = Label[~msk]  
  66.         print("\t[Info] Total %d training instances; %d testing instances!" % (trainFeatures.shape[0], testFeatures.shape[0]))  
  67.         return (trainFeatures, trainLabels, testFeatures, testLabels)  
  68.     else:  
  69.         return (scaledFeatures, Label)  
建立模型與訓練 
我們接下來程式碼將建立 MLP (Multiple Layer Perception) 包括: 輸入層 (9 個神經元); 隱藏層一 (40 個神經元); 隱藏層二 (30 個神經元); 輸出層 (1 個神經元) 

STEP1. 建立模型 
  1. # Building model  
  2. print("\t[Info] Building MLP model")  
  3. from keras.models import Sequential  
  4. from keras.layers import Dense,Dropout  
  5.   
  6. model = Sequential()  
  7. model.add(Dense(units=40, input_dim=9, kernel_initializer='uniform', activation='relu'))  
  8. model.add(Dense(units=30, kernel_initializer='uniform', activation='relu'))  
  9. model.add(Dense(units=1, kernel_initializer='uniform', activation='sigmoid'))  
  10. print("\t[Info] Show model summary...")  
  11. model.summary()  
  12. print("")  
STEP2. 進行訓練 
  1. # Training  
  2. print("\t[Info] Start training...")  
  3. model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])  
  4. train_history = model.fit(x=train_data, y=train_label, validation_split=0.1, epochs=50, batch_size=30, verbose=2)  
STEP3. 顯示訓練結果 
  1. # Show Training result  
  2. from utils import *  
  3. if isDisplayAvl():  
  4.     show_train_history(train_history, 'acc''val_acc')  
  5.     show_train_history(train_history, 'loss''val_loss')  

加入鐵達尼號電影 Jack 與 Rose 的資料 
在鐵達尼電影中男女主角 Jack 與 Rose 是虛擬人物, 我們希望透過剛剛訓練的模型來預測男女主角的生存機率. 以下是根據電影情節所構想的資料: 
* Jack 是 3 等艙; Rose 是頭等艙.
* Jack 是男性; Rose 是女性
* 票價 Jack 是 5; Rose 是 100
* 年齡 Jack 是 23; Rose 是 20

STEP1. 建立 Jack 與 Rose 的資料 
使用 pandas.Series 建立 Jack 與 Rose 資料如下: 
  1. Jack = pd.Series([0'Jack'3'male'23105.0'S'])  
  2. Rose = pd.Series([1'Rose'1'female'2810100.0'S'])  
  3. JR_df = pd.DataFrame([list(Jack), list(Rose)], columns=['Survived','Name''Pclass','Sex','Age','SibSp','Parch','Fare','Embarked'])  
  4.   
  5. all_df = pd.concat([train_df, JR_df])  
  6. print("\t[Info] Show last two records:\n%s\n" % (all_df[-2:]))  
STEP2. 進行預測與顯示結果 
  1. print("\t[Info] Making prediction...")  
  2. features, labels = preprocessData(all_df)  
  3. all_probability = model.predict(features)  
  4. all_df.insert(len(all_df.columns), 'probability', all_probability)  
  5. print("\t[Info] The prediction of last two records:\n%s\n" % (all_df[-2:]))  
  6. print("")  
執行結果: 

完整代碼連結如下: 
ch11_1.py:


Supplement 
Apply one-hot encoding to a pandas DataFrame

沒有留言:

張貼留言

[Git 文章收集] Differences between git merge and git rebase

Source From  Here Preface Merging and rebasing are the two most popular way to applying changes from one branch into another one. They bot...