監督學習應用--Titanic數據建模

監督學習建模流程

監督學習包括數據採集、數據處理、模型搭建及訓練、模型測試、參數調優等階段。這是一個不斷反饋不斷循環的過程。
這裏寫圖片描述

本文我們利用Titanic數據進行建模,分析乘客各種信息與是否獲救之間的規律,從來對我們的測試集進行預測。(是否獲救就是標籤,乘客其他信息就是特徵。)
*數據來源*
Titanic數據是機器學習競賽平臺Kaggle平臺入門最好的數據,記錄了沉船的泰坦尼克各種乘客信息以及最終是否獲救的情況。導入數據:

`df=pd.read_csv('../p1_demo/titanic_dataset.csv',na_values='NULL')

這裏寫圖片描述
*可視化分析*
在數據處理之前可通過對數據進行可視化分析,對數據有個很好的瞭解和把握。

##可視化獲救與沒被獲救的比例
df['survived'].hist()

這裏寫圖片描述

###不同船艙級別的獲救情況
pd.crosstab(df['pclass'],df['survived']).plot(kind='bar')
pd.crosstab(df['pclass'],df['survived'])

可視化船艙等級對是否獲救的影響
*數據處理*
包括異常值處理、缺失值填充、噪音數據過濾、數據形式轉換、特徵提取等操作。
以上Titanic數據算法不能直接識別,並且像年齡費用爲連續型數據,我們需要處理成和其他特徵一致的離散性特徵。所以我們進行如下處理:
這裏寫圖片描述
詳細處理代碼如下:

##姓名的處理
df['Name_length']=df['name'].apply(len)

##兄弟姐妹與配偶、父母小孩
df['FamilySize']=df['sibsp']+df['parch']+1
df['IsAlone']=0
df.loc[df['FamilySize']==1,'IsAlone']=1

##費用的處理
df['fare']=df['fare'].fillna(df['fare'].median())
df['categoricalFare']=pd.cut(df['fare'],4)
#print(train)

##年齡
age_avg=df['age'].mean()
age_std=df['age'].std()
age_null_count=df['age'].isnull().sum()
age_null_random_list=np.random.randint(age_avg-age_std,age_avg+age_std,size=age_null_count)
df['age'][np.isnan(df['age'])]=age_null_random_list
df['age'] = df['age'].astype(int)
df['categoricalage'] = pd.cut(df['age'], 5)


##對姓名的處理
def get_title(name):
    title_search = re.search('([A-Za-z]+)\.', name)  ##匹配出頭銜(Miss,Master 等等)
    # If the title exists, extract and return it.
    if title_search:
        return title_search.group(1)
    return ""

df['Title'] = df['name'].apply(get_title)
df['Title'] = df['Title'].replace(['Lady', 'Countess','Capt', 'Col','Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')
df['Title'] = df['Title'].replace('Mlle', 'Miss')
df['Title'] = df['Title'].replace('Ms', 'Miss')
df['Title'] = df['Title'].replace('Mme', 'Mrs')


# 將頭銜映射到0,1,2,3,4,5
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
df['Title'] = df['Title'].map(title_mapping)
df['Title'] = df['Title'].fillna(0)

# Mapping Sex
df['sex'] = df['sex'].map({'female': 0, 'male': 1} ).astype(int)

# Mapping Fare
df.loc[ df['fare'] <= 7.91, 'fare'] = 0
df.loc[(df['fare'] > 7.91) & (df['fare'] <= 14.454), 'fare'] = 1
df.loc[(df['fare'] > 14.454) & (df['fare'] <= 31), 'fare']   = 2
df.loc[ df['fare'] > 31, 'fare']  = 3
df['fare'] = df['fare'].astype(int)

# Mapping Age
df.loc[ df['age'] <= 16, 'age']  = 0
df.loc[(df['age'] > 16) & (df['age'] <= 32), 'age'] = 1
df.loc[(df['age'] > 32) & (df['age'] <= 48), 'age'] = 2
df.loc[(df['age'] > 48) & (df['age'] <= 64), 'age'] = 3
df.loc[ df['age'] > 64, 'age'] = 4 ;

*數據拆分*
簡單拆分:將數據拆分爲訓練數據和測試數據。訓練數據用來給算法進行訓練學習,測試數據用來對訓練好的模型進行測試。
k折交叉驗證拆分:在簡單拆分的基礎上,對訓練數據繼續拆分成k份,每次拿出一份,剩下的k-1份拿來給算法進行訓練,得到k個模型,通過對k個模型同時對測試集進行測試,並得到最終的預測結果。
這裏寫圖片描述
拆分代碼:

##將數據轉換成算法識別的數據,array的形式。

x=df[["pclass","sex","age","fare","Name_length","FamilySize","IsAlone","Title"]].values
y=df["survived"].values
PassengerId=list(df.index)
print(x.shape)
from sklearn.cross_validation import KFold

###訓練集:測試集合=1200:109
train_x=x[:1200]
train_y=y[:1200]
###print(train_x.shape)
test_x=x[1200:]
test_y=y[1200:]

test_PassengerId=PassengerId[1200:]

###獲取訓練數據量大小,測試數據量大小
ntrain=train_x.shape[0]
ntest=test_x.shape[0]

###交叉驗證數據的分類,5折交叉驗證
NFOLDS = 5 
SEED=0
kf = KFold(ntrain, n_folds= NFOLDS, random_state=SEED)
##print(train_x)  

*算法選擇與模型訓練*
sklearn包含了各種常用的機器學習算法。直接通過一個函數就可以調用。比如選擇邏輯迴歸:

from sklearn.linear_model import LogisticRegression
clf=LogisticRegression()

交叉驗證訓練過程:

###交叉驗證
def get_oof(clf, train_x, train_y, test_x):
    """初始化
    oof_train: 訓練數據結果
    oof_test: 測試數據結果
    oof_test_skf: 儲存5次交叉訓練模型對測試數據的預測結果"""
    oof_train = np.zeros((ntrain,))
    oof_test = np.zeros((ntest,))
    oof_test_skf = np.empty((NFOLDS, ntest))  ##生成一個NFOLDS*ntest的空數組。

    ##根據每次切分數據進行訓練並對測試數據進行預測
    for i, (train_index, test_index) in enumerate(kf):
        x_tr = train_x[train_index]
        y_tr = train_y[train_index]
        x_te = train_x[test_index]

        clf.fit(x_tr, y_tr)

        oof_train[test_index] = clf.predict(x_te)
        oof_test_skf[i, :] = clf.predict(test_x)

    ##按第0維求平均,得到5次預測的平均。
    oof_test[:] = oof_test_skf.mean(axis=0)  

    ###返回驗證集合、測試集合的預測結果。
    return oof_train.reshape(-1, 1), oof_test.reshape(-1, 1)

*用模型對測試集進行預測*

oof_train, oof_test = get_oof(clf,train_x, train_y, test_x)
def process_pre(pre_y):
    for i in range(pre_y.shape[0]):
        if pre_y[i][0]>0.5:
            pre_y[i][0]=1
        else:
            pre_y[i][0]=0
    pre_y=pre_y.ravel()
    return pre_y

##模型在測試集合的預測結果
pre_y=process_pre(oof_test)

*模型性能分析*
1、通過直觀地展示預測結果與實際的對比

plt.figure(figsize=(15,5))
plt.scatter(test_PassengerId,pre_y,color='green')
plt.scatter(test_PassengerId,test_y,color='blue')
plt.title('Predicted value VS True value')

2、用度量指標對模型進行性能分析
1. 準確率:所有樣本中預測正確的佔比
針對我們感興趣的類別:
2. 精度(查準率):預測結果中預測正確的能力。
3. 召回率(查全率):從實際類別中找到某一類別的能力。
4. F1-score=:平衡精度與召回率的度量指標。

from sklearn.metrics import classification_report,confusion_matrix

n_classes=2
##準確率
accuracy=np.mean(pre_y==test_y)
print('accuracy:'+str(accuracy))
##混淆矩陣
cmx=confusion_matrix(test_y,pre_y)
print(cmx)
##精度和召回率
performance=classification_report(test_y,pre_y,labels=range(n_classes))
print('Performance :'+'\n'+str(performance))

這裏寫圖片描述

最後說明:在數據量這麼少的情況下,準確率能達到80%以上已經非常好了。雖然Kaggle平臺上很多很好的能到100%。那是因爲用了很多特殊的技巧,這種技巧需要根據具體數據、業務、環境下才能使用,我們本文的目的是讓大家對整個建模流程有個瞭解和把握。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章