kaggle——泰坦尼克之災1

泰坦尼克之災是kaggle的一個入門案例,以下是這個比賽的一些記錄:

1、jupyter notebook的安裝

相比之前使用的pycharm,jupyter notebook的優(yōu)點是允許把代碼寫入獨立的cell中,然后單獨執(zhí)行。這樣做意味著我們可以在測試項目時單獨測試特定代碼塊,無需從頭開始執(zhí)行代碼。
安裝教程參考https://blog.csdn.net/dream_an/article/details/50464940
使用教程參考https://blog.csdn.net/lee_j_r/article/details/52791228

2、泰坦尼克之災比賽

根據(jù)以下流程解釋并貼出相應的代碼:
1、數(shù)據(jù)準備和了解:下載數(shù)據(jù)并了解數(shù)據(jù)的屬性
2、數(shù)據(jù)清洗:即數(shù)據(jù)預處理,對缺失值進行補充或者把機器學習不能處理的數(shù)值類型轉(zhuǎn)化為可以處理的int型
3、特征工程:提煉出新特征并進行特征選擇來提高模型準確率
4、基準模型:跑幾個基礎(chǔ)模型。我選擇了線性回歸、邏輯回歸、隨機森林這三個,并通過交叉驗證查看準確率
5、融合模型:我選擇融合隨機森林和邏輯回歸模型

2.1數(shù)據(jù)準備和了解

首先,在kaggle上下載數(shù)據(jù):https://www.kaggle.com/c/titanic/data


各個屬性的含義如下:

PassengerId:乘客ID
Survived:是否獲救
Pclass:乘客票務艙,1表示最高級
Name:乘客姓名
Sex:性別
Age:年齡
SibSp:堂兄弟妹個數(shù)
Parch:父母與小孩個數(shù)
Ticket:船票信息
Fare:票價
Cabin:客艙
Embarked:登船港口

再者,導入數(shù)據(jù)并對各個屬性進行大致統(tǒng)計

"""查看數(shù)據(jù)""" 
import pandas as pd
titanic = pd.read_csv('train.csv')
# titanic.head(3)
print(titanic.describe())
print(titanic.info())

輸出結(jié)果為

     PassengerId    Survived      Pclass         Age       SibSp  \
count   891.000000  891.000000  891.000000  714.000000  891.000000   
mean    446.000000    0.383838    2.308642   29.699118    0.523008   
std     257.353842    0.486592    0.836071   14.526497    1.102743   
min       1.000000    0.000000    1.000000    0.420000    0.000000   
25%     223.500000    0.000000    2.000000   20.125000    0.000000   
50%     446.000000    0.000000    3.000000   28.000000    0.000000   
75%     668.500000    1.000000    3.000000   38.000000    1.000000   
max     891.000000    1.000000    3.000000   80.000000    8.000000   

            Parch        Fare  
count  891.000000  891.000000  
mean     0.381594   32.204208  
std      0.806057   49.693429  
min      0.000000    0.000000  
25%      0.000000    7.910400  
50%      0.000000   14.454200  
75%      0.000000   31.000000  
max      6.000000  512.329200
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
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
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB
None

可以初步發(fā)現(xiàn),Age這一列的count只有714,說明需要進行缺失值填充;Sex、Embarked、Name等屬性都是object類型,要將其轉(zhuǎn)化為機器學習能處理的類型。這都是數(shù)據(jù)預處理的內(nèi)容,無論哪個案例都需要數(shù)據(jù)預處理。

2.2數(shù)據(jù)清洗

數(shù)據(jù)清洗即數(shù)據(jù)預處理,包括對缺失值進行填充把機器學習不能處理的數(shù)值類型轉(zhuǎn)化為可以處理的int型。
缺失值填充一般用到fillna()函數(shù),分兩種情況:
1.如果是數(shù)值類型,用平均值或中位數(shù)取代
2.如果是分類數(shù)據(jù),用最常見的類別取代
具體應用如下:

Age這一列有缺失值,用中位數(shù)填充(或平均值)

"""數(shù)據(jù)預處理"""
# 用中值填補缺失值
titanic['Age'] = titanic['Age'].fillna(titanic['Age'].median())

Sex這一列的值male、female不能直接處理,分別將其轉(zhuǎn)化為0、1

print(titanic['Sex'].unique())
# titanic.loc[0]表示第0行的樣本
# titanic.loc[0, 'PassengerId']表示行為0,列為PassengerId的值
titanic.loc[titanic['Sex'] == 'male', 'Sex'] = 0
titanic.loc[titanic['Sex'] == 'female', 'Sex'] = 1

Embarked這一列有缺失值,用最常見的類別即‘S’填充,然后再將數(shù)據(jù)轉(zhuǎn)化為int型

print(titanic['Embarked'].describe())
print(titanic['Embarked'].unique())
titanic['Embarked'] = titanic['Embarked'].fillna('S')
titanic.loc[titanic['Embarked'] == 'S', 'Embarked'] = 0
titanic.loc[titanic['Embarked'] == 'C', 'Embarked'] = 1
titanic.loc[titanic['Embarked'] == 'Q', 'Embarked'] = 2

2.3特征工程

“數(shù)據(jù)決定了機器學習的上限,而算法只是盡可能逼近這個上限”,這里的數(shù)據(jù)指的就是經(jīng)過特征工程得到的數(shù)據(jù)。特征工程指的是把原始數(shù)據(jù)轉(zhuǎn)變?yōu)槟P偷挠柧殧?shù)據(jù)的過程,它的目的就是獲取更好的訓練數(shù)據(jù)特征,使得機器學習模型逼近這個上限。特征工程學習參考https://www.cnblogs.com/wxquare/p/5484636.html
案例中,通過提煉新特征并進行特征選擇可以提高模型準確率。

提煉的3個新特征為FamilySize:SibSp和Parch的人數(shù)相加,看看是否家庭人數(shù)越多獲救幾率越大;NameLength:名字長度,外國名字越長地位越高;Title:在Name里提取的,類似Mr、Mrs、Dr表示性別職業(yè)

re.search():掃描整個字符串并返回第一個成功的匹配,沒有就返回none
關(guān)于正則表達式:https://www.jb51.net/article/15707.htm

# 提煉新特征
titanic['FamilySize'] = titanic['SibSp'] + titanic['Parch']
titanic['NameLength'] = titanic['Name'].apply(lambda x: len(x))
import re
import pandas as pd
def get_title(name):
    title_search = re.search(' ([A-Za-z]+)\.', name)
    
    if title_search:
        return title_search.group(1)
    return ''
titles = titanic['Name'].apply(get_title)
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Dr": 5, "Rev": 6, "Major": 7, "Col": 8, "Mlle": 9,
                 "Mme": 10, "Don": 11, "Lady": 12, "Countess": 13, "Jonkheer": 14, "Sir": 15, "Capt": 16, "Ms": 17
                 }
for k, v in title_mapping.items():
    titles[titles == k] = v
print(pd.value_counts(titles))
titanic['Title'] = titles

SelectKBest():https://blog.csdn.net/sunshunli/article/details/82051138

# 特征選擇
import numpy as np
from sklearn.feature_selection import SelectKBest, f_classif
import matplotlib.pyplot as plt
predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked", 
"FamilySize", "NameLength", "Title"]
selector = SelectKBest(f_classif, k=5)# 方差分析,計算方差分析(ANOVA)的F值 (組間均方 / 組內(nèi)均方),選取前5個特征
selector.fit(titanic[predictors], titanic['Survived'])
scores = -np.log10(selector.pvalues_)
plt.bar(range(len(predictors)), scores)
plt.xticks(range(len(predictors)), predictors, rotation='vertical')
plt.show()

可以發(fā)現(xiàn)“Pclass”、 "Sex"、“Fare”、"NameLength"和“Title”這5個特征比較重要

2.4基準模型

線性回歸是機器學習最基礎(chǔ)的算法,邏輯回歸相比線性回歸,代碼更加簡潔、而隨機森林是集成學習,也不容易過擬合,所以我選擇這三個模型,并通過交叉驗證將初始樣本分為3份,每次2份用作訓練集,剩下1份作為測試集,這樣可以有3次訓練,得到3次訓練結(jié)果,平均之后得到最后結(jié)果。

2.4.1線性回歸

"""線性回歸"""
from sklearn.linear_model import LinearRegression
from sklearn.cross_validation import KFold
from sklearn import metrics
# 選擇特征
predictors = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
# 導入線性回歸
alg = LinearRegression()
# 將樣本分為3份進行交叉驗證
kf = KFold(titanic.shape[0], n_folds=3, random_state=1)
predictions = []
for train_index, test_index in kf:
    # 用于訓練的特征數(shù)據(jù)
    train_predictors = titanic[predictors].iloc[train_index, :]
    # 特征數(shù)據(jù)的label(即是否獲救)
    train_target = titanic['Survived'].iloc[train_index]  # train_target = titanic['Survived'][train_index]
    # 訓練線性回歸模型
    alg.fit(train_predictors, train_target)    test_predictions = alg.predict(titanic[predictors].iloc[test_index, :])
    predictions.append(test_predictions)
# 線性回歸得到的結(jié)果是在[0,1],轉(zhuǎn)化為類別
import numpy as np
predictions = np.concatenate(predictions, axis=0)# predictions = np.hstack(predictions)
predictions[predictions > .5] = 1
predictions[predictions <= .5] = 0
# predictions = np.where(predictions > .5, 1, 0)
# 線性模型準確率
accuracy = sum(predictions == titanic['Survived']) / len(predictions)
print(accuracy)

輸出線性回歸準確率為

0.783389450056

得到的準確率有點低,我們嘗試下邏輯回歸模型

2.4.2邏輯回歸

函數(shù):cross_val_score(model_name, X,y, cv=k)
參數(shù):1、模型函數(shù)名,如 LogisticRegression()2、訓練集 3、測試屬性 4、K折交叉驗證
作用:驗證某個模型在某個訓練集上的穩(wěn)定性,輸出k個預測精度。

"""邏輯回歸"""
from sklearn import cross_validation
from sklearn.linear_model import LogisticRegression
alg = LogisticRegression(random_state=1)
scores = cross_validation.cross_val_score(alg, titanic[predictors], titanic['Survived'], cv=3)
print(scores)
print(scores.mean())

輸出邏輯回歸準確率為

[ 0.78451178  0.78787879  0.79124579]
0.787878787879

準確率提高了一點

2.4.3隨機森林

隨機森林的隨機體現(xiàn)在兩點:1、取樣本是隨機的,且是有放回的 2、特征的選擇是隨機的,不一定所有的屬性特征都要用到。森林表示生成多個決策樹

函數(shù):RandomForestClassifier()
參數(shù)解釋:random_state = 1 表示此處代碼多運行幾次得到的隨機值都是一樣的,如果不設置,兩次執(zhí)行的隨機值是不一樣的;n_estimators=50 表示有50棵決策樹;樹的分裂的條件是: min_samples_split =4代表樣本不停的分裂,某一個節(jié)點上的樣本如果只有4個了 ,就不再繼續(xù)分裂了;min_samples_leaf =2表示葉子節(jié)點的最小個數(shù)為2

"""隨機森林"""
from sklearn import cross_validation
from sklearn.ensemble import RandomForestClassifier
alg = RandomForestClassifier(random_state=1, n_estimators=50, min_samples_split=4, min_samples_leaf=2)
kf = cross_validation.KFold(titanic.shape[0], n_folds=3, random_state=1)
scores = cross_validation.cross_val_score(alg, titanic[predictors], titanic['Survived'], cv=kf)
print(scores.mean())

輸出隨機森林準確率為

0.81593714927

準確率超過了81%。后續(xù)還可以通過調(diào)整隨機森林模型的參數(shù)看是否能繼續(xù)提高準確率,但不是越高越好,可能會導致過擬合

2.5混合模型

混合模型是在競賽中常用的辦法:集成多個模型,得出每個模型的結(jié)果,并賦予每個模型權(quán)重,求出最后的平均結(jié)果。上面跑基準模型發(fā)現(xiàn)邏輯回歸和隨機森林效果更好,所以我集成了這兩種模型。如果發(fā)現(xiàn)某個模型更好,權(quán)重可以更高(案例中隨機森林權(quán)重是2,邏輯回歸的是1)

predict_proba():https://blog.csdn.net/m0_37870649/article/details/79549142

# 混合模型
from sklearn.ensemble import GradientBoostingClassifier
import numpy as np
algorithms = [
    [RandomForestClassifier(random_state=1, n_estimators=20, min_samples_split=4, min_samples_leaf=2),
     ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'FamilySize', 'NameLength', 'Title']],
    [LogisticRegression(random_state=1),
     ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'FamilySize', 'NameLength', 'Title']]
]
kf = KFold(titanic.shape[0], n_folds=11, random_state=1)
predictions = []
for train, test in kf:
    train_target = titanic['Survived'].iloc[train]
    full_test_prediction = []
    for alg, predictors in algorithms:
        alg.fit(titanic[predictors].iloc[train, :], train_target)
        test_prediction = alg.predict_proba(titanic[predictors].iloc[test, :].astype(float))[:, 1]
        full_test_prediction.append(test_prediction)
    test_predictions = (full_test_prediction[0] * 2 + full_test_prediction[1]) / 3
    test_predictions[test_predictions > .5] = 1
    test_predictions[test_predictions <= .5] = 0
    predictions.append(test_predictions)
predictions = np.concatenate(predictions, axis=0)
accuracy = sum(predictions == titanic['Survived']) / len(predictions)
print(accuracy)

輸出混合模型結(jié)果為

0.832772166105

總結(jié):對于一般的簡單機器學習,先進行數(shù)據(jù)探索,了解屬性;再將原始數(shù)據(jù)經(jīng)過預處理之后得到完整可處理的數(shù)據(jù)即數(shù)據(jù)清洗;再進行特征工程,得到重要特征;然后跑基準模型看看效果;復雜的數(shù)據(jù)可以嘗試混合模型集成學習,具體情況具體分析。

參考視頻
代碼點這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容