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

沒有留言:

張貼留言

[ Py DS ] Ch1 - IPython: Beyond Normal Python

Source From  Here   Keyboard Shortcuts in the IPython Shell   If you spend any amount of time on the computer, you’ve probably found a u...