国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何在 Titanic Kaggle Challenge 中獲得0.8134分

mist14 / 779人閱讀

摘要:船上每位旅客的身份證明乘客等級。簡單地用平均年齡或中位年齡替換它們可能不是最佳解決方案,因為年齡可能因乘客的類別和類別而不同。例如如果乘客是女性,則來自和來自王室,中位年齡為歲。失蹤的年齡已被取代。此函數(shù)將值替換為表示。

由 Kaggle 主持的泰坦尼克號生存挑戰(zhàn)賽是一項競賽,其目標是基于一組描述乘客的變量,例如他的年齡,性別或乘客在船上的等級,來預測特定乘客是生存或死亡。

我一直在玩 Titanic 數(shù)據(jù)集,我最近在公共排行榜上獲得了0.8134的準確度分數(shù)。當我寫這篇文章時,我在所有 Kagglers 中排名前4%。

這篇文章將分享我的解決方案。

為了使本教程更具“學術(shù)性”以便任何人都能從中受益,我將首先從探索性數(shù)據(jù)分析(EDA)開始,然后我將遵循特征工程并最終呈現(xiàn)我設(shè)置的預測模型。

在這個 jupyter 筆記本中,我將在每個級別的管道中使用 Python。

本教程涉及的主要庫是:

Pandas 用于數(shù)據(jù)操作和接入(ingestion)

Matplotlibseaborn 用于數(shù)據(jù)可視化

Numpy 用于多維數(shù)組計算

sklearn 用于機器學習和預測建模

安裝過程

安裝這些軟件包的一種非常簡單的方法是下載并安裝 Conda,它是將以上所有包封裝起來的發(fā)行版。此發(fā)行版適用于所有平臺(Windows,Linux 和 Mac OSX)。

特別注意

這是我作為博主和機器學習從業(yè)者的第一次嘗試。

如果您對我所做的代碼或假設(shè)有疑問,請不要猶豫,在下面的評論部分發(fā)表評論。

如果您對如何改進筆記本電腦也有建議,請聯(lián)系我。

本教程可在我的 github 帳戶中找到。

譯者注:本翻譯在 qiwihui 下。

希望你已經(jīng)在計算機上設(shè)置了所有內(nèi)容。讓我們開始吧。

I - 探索性數(shù)據(jù)分析

正如在不同的數(shù)據(jù)項目中,我們將首先開始深入研究數(shù)據(jù)并建立我們的第一個直覺。

在本節(jié)中,我們將做四件事。

數(shù)據(jù)提取:我們將加載數(shù)據(jù)集并首先查看它。

清潔:我們將填寫缺失值。

繪圖:我們將創(chuàng)建一些有趣的圖表,這些圖表(希望)可以發(fā)現(xiàn)數(shù)據(jù)中的相關(guān)性和隱藏的見解。

假設(shè):我們將從圖表中提出假設(shè)。

我們稍微調(diào)整了這款筆記本的風格,以便畫圖居中。

from IPython.core.display import HTML
HTML("""

""");

導入有用的包。

%matplotlib inline

import warnings
warnings.filterwarnings("ignore")
warnings.filterwarnings("ignore", category=DeprecationWarning)

import pandas as pd
pd.options.display.max_columns = 100

from matplotlib import pyplot as plt
import numpy as np

import seaborn as sns

import pylab as plot
params = {
    "axes.labelsize": "large",
    "xtick.labelsize": "x-large",
    "legend.fontsize": 20,
    "figure.dpi": 150,
    "figure.figsize": [25, 7]
}
plot.rcParams.update(params)

有兩個數(shù)據(jù)集:訓練集和測試集。
我們將使用訓練集來構(gòu)建我們的預測模型,用測試集來對其進行評分并生成輸出文件以在Kaggle評估系統(tǒng)上提交。

我們將在本文末尾看到這個過程是如何完成的。

現(xiàn)在讓我們開始加載訓練集。

data = pd.read_csv("./data/train.csv")
print data.shape
(891, 12)

我們得到:

891 行

12 列

Pandas 允許你鳥瞰數(shù)據(jù)。

data.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S

Survived 列是 目標變量。 如果 Survived 為 1,乘客幸免于難,否則他已經(jīng)死了。這是我們要預測的變量。

其他變量描述了乘客。 它們是 特征

PassengerId:船上每位旅客的身份證明

Pclass:乘客等級。 它有三個可能的值:1,2,3(第一,第二和第三類)

Name:Passeger的名字

Sex:性別

Age:年齡

SibSp:與乘客一起旅行的兄弟姐妹和配偶的數(shù)量

Parch:與乘客一起旅行的父母和孩子的數(shù)量

Ticket:船票號碼

Fare:票價

Cabin:船艙號碼

Embarked:這描述了人們登上的泰坦尼克號的三個可能區(qū)域。 三個可能的值 S,C,Q

Pandas 允許您對數(shù)字特征進行高級簡單的統(tǒng)計描述。
這可以使用 describe 方法完成。

data.describe()

PassengerId Survived Pclass Age SibSp Parch Fare
count 891.000000 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000
mean 446.000000 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208
std 257.353842 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429
min 1.000000 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000
25% 223.500000 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400
50% 446.000000 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200
75% 668.500000 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000
max 891.000000 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200

count 變量顯示 Age 列中缺少177個值。

一種解決方案是用中值年齡填充空值。我們也可以用平均年齡來估算,但中位數(shù)對異常值更為穩(wěn)健。

data["Age"] = data["Age"].fillna(data["Age"].median())

讓我們看一下結(jié)果。

data.describe()

PassengerId Survived Pclass Age SibSp Parch Fare
count 891.000000 891.000000 891.000000 891.000000 891.000000 891.000000 891.000000
mean 446.000000 0.383838 2.308642 29.361582 0.523008 0.381594 32.204208
std 257.353842 0.486592 0.836071 13.019697 1.102743 0.806057 49.693429
min 1.000000 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000
25% 223.500000 0.000000 2.000000 22.000000 0.000000 0.000000 7.910400
50% 446.000000 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200
75% 668.500000 1.000000 3.000000 35.000000 1.000000 0.000000 31.000000
max 891.000000 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200

完美。

我們現(xiàn)在制作一些圖表。讓我們根據(jù)性別來看待生存。

data["Died"] = 1 - data["Survived"]
data.groupby("Sex").agg("sum")[["Survived", "Died"]].plot(kind="bar", figsize=(25, 7),
                                                          stacked=True, colors=["g", "r"]);

看起來男性乘客更容易死亡。讓我們繪制相同的圖形,但用比例代替。

data.groupby("Sex").agg("mean")[["Survived", "Died"]].plot(kind="bar", figsize=(25, 7), 
                                                           stacked=True, colors=["g", "r"]);

性別變量似乎是一種歧視性特征。女性更有可能生存。

現(xiàn)在讓我們將生存與年齡變量聯(lián)系起來。

fig = plt.figure(figsize=(25, 7))
sns.violinplot(x="Sex", y="Age", 
               hue="Survived", data=data, 
               split=True,
               palette={0: "r", 1: "g"}
              );

正如我們在上面的圖表中看到并通過以下方式驗證:

女性的生存率高于男性,如較大的女性綠色直方圖所示

現(xiàn)在,我們看到:

年齡為男性乘客的生存:

年輕的男性傾向于生存

??* 20至40歲之間的大量乘客死亡

年齡似乎沒有對女性生存產(chǎn)生直接影響

以下小提琴情節(jié)證實,在遇到威脅的情況下,水手和船長遵守一條舊的行為準則:“婦女和兒童優(yōu)先!”。

對嗎?

現(xiàn)在讓我們關(guān)注每位乘客的票價,看看它如何影響生存。

figure = plt.figure(figsize=(25, 7))
plt.hist([data[data["Survived"] == 1]["Fare"], data[data["Survived"] == 0]["Fare"]], 
         stacked=True, color = ["g","r"],
         bins = 50, label = ["Survived","Dead"])
plt.xlabel("Fare")
plt.ylabel("Number of passengers")
plt.legend();

票價較低的乘客更容易死亡。
換句話說,擁有更昂貴門票,因此更重要的社會地位的乘客似乎首先獲救。

好的,這很好。 現(xiàn)在讓我們將年齡,票價和生存結(jié)合在一張圖表上。

plt.figure(figsize=(25, 7))
ax = plt.subplot()

ax.scatter(data[data["Survived"] == 1]["Age"], data[data["Survived"] == 1]["Fare"], 
           c="green", s=data[data["Survived"] == 1]["Fare"])
ax.scatter(data[data["Survived"] == 0]["Age"], data[data["Survived"] == 0]["Fare"], 
           c="red", s=data[data["Survived"] == 0]["Fare"]);

圓圈的大小與票價成正比。

在 x 軸上,我們有年齡,在 y 軸,我們考慮票價。

我們可以觀察不同的集群:

x = 20 和 x = 45 之間的大綠點:票價最高的成人

x = 10 和 x = 45 之間的小紅點,船上較低級別的成年人

x = 0 和 x = 7 之間的小密集點:這些是被保存的孩子

事實上,票價與我們在下面的圖表中看到的類別相關(guān)。

ax = plt.subplot()
ax.set_ylabel("Average fare")
data.groupby("Pclass").mean()["Fare"].plot(kind="bar", figsize=(25, 7), ax = ax);

現(xiàn)在讓我們看看登船地點如何影響生存。

fig = plt.figure(figsize=(25, 7))
sns.violinplot(x="Embarked", y="Fare", hue="Survived", data=data, split=True, palette={0: "r", 1: "g"});

似乎登船地點 C 的票價范圍更廣,因此支付最高價格的乘客是那些幸存的乘客。

我們也看到這種情況發(fā)生在登船地點 S 而不是登船地點 Q。

現(xiàn)在讓我們停止數(shù)據(jù)探索并切換到下一部分。

II - 特征工程

在前一部分中,我們調(diào)查了數(shù)據(jù)并發(fā)現(xiàn)了一些有趣的相關(guān)性。

在這一部分中,我們將看到如何處理和轉(zhuǎn)換這些變量,使數(shù)據(jù)變得可以通過機器學習算法進行管理。

我們還將創(chuàng)建或“設(shè)計”在構(gòu)建模型時有用的其他功能。

我們將在此過程中看到如何處理文本變量(如乘客姓名)并將此信息集成到我們的模型中。

為了更加清晰,我們將代碼分散在多帶帶的函數(shù)中。

但首先,讓我們定義一個打印函數(shù),斷言是否已經(jīng)處理了一個特征。

def status(feature):
    print "Processing", feature, ": ok"
加載數(shù)據(jù)

啟動機器學習問題的一個技巧是將訓練集一起附加到測試集。

我們將使用訓練集進行特征工程以防止信息泄漏。然后我們將這些變量添加到測試集中。

讓我們加載訓練集和測試集并將它們合在一起。

def get_combined_data():
    # reading train data
    train = pd.read_csv("./data/train.csv")

    # reading test data
    test = pd.read_csv("./data/test.csv")

    # extracting and then removing the targets from the training data 
    targets = train.Survived
    train.drop(["Survived"], 1, inplace=True)


    # merging train data and test data for future feature engineering
    # we"ll also remove the PassengerID since this is not an informative feature
    combined = train.append(test)
    combined.reset_index(inplace=True)
    combined.drop(["index", "PassengerId"], inplace=True, axis=1)

    return combined
combined = get_combined_data()

讓我們看一下數(shù)據(jù)的維度。

print combined.shape
(1309, 10)

訓練集和測試集被合并。您可能會注意到總行數(shù)(1309)是訓練集和測試集中行數(shù)的精確總和。

combined.head()

Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S

提取乘客稱謂

在查看乘客姓名時,人們可能想知道如何處理它們以提取有用的信息。

如果你仔細看看這些第一個例子:

Braund, Mr. Owen Harris

Heikkinen, Miss. Laina

Oliva y Ocana, Dona. Fermina

Peter, Master. Michael J

你會注意到每個名字都有一個稱謂!這可能是一個簡單的小姐(Miss.)或太太(Mrs.),但它有時可能像 Master,Sir 或 Dona 那樣更復雜。在這種情況下,我們可以通過簡單地解析稱謂并提取標題并轉(zhuǎn)換為二進制變量來引入有關(guān)社會地位的其他信息。

讓我們看看我們將如何在下面的函數(shù)中執(zhí)行此操作。

讓我們先來看看在訓練集中有什么不同的稱謂。

titles = set()
for name in data["Name"]:
    titles.add(name.split(",")[1].split(".")[0].strip())
print titles
set(["Sir", "Major", "the Countess", "Don", "Mlle", "Capt", "Dr", "Lady", "Rev", "Mrs", "Jonkheer", "Master", "Ms", "Mr", "Mme", "Miss", "Col"])
Title_Dictionary = {
    "Capt": "Officer",
    "Col": "Officer",
    "Major": "Officer",
    "Jonkheer": "Royalty",
    "Don": "Royalty",
    "Sir" : "Royalty",
    "Dr": "Officer",
    "Rev": "Officer",
    "the Countess":"Royalty",
    "Mme": "Mrs",
    "Mlle": "Miss",
    "Ms": "Mrs",
    "Mr" : "Mr",
    "Mrs" : "Mrs",
    "Miss" : "Miss",
    "Master" : "Master",
    "Lady" : "Royalty"
}

def get_titles():
    # we extract the title from each name
    combined["Title"] = combined["Name"].map(lambda name:name.split(",")[1].split(".")[0].strip())

    # a map of more aggregated title
    # we map each title
    combined["Title"] = combined.Title.map(Title_Dictionary)
    status("Title")
    return combined

此函數(shù)解析名稱并提取稱謂。 然后,它將稱謂映射到稱謂類別。
我們選擇:

Officer

Royalty

Mr

Mrs

Miss

Master

讓我們運行一下!

combined = get_titles()
Processing Title : ok
combined.head()

Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Title
0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S Mr
1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C Mrs
2 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S Miss
3 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S Mrs
4 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S Mr

讓我們檢查一下稱謂是否填寫正確。

combined[combined["Title"].isnull()]

Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Title
1305 1 Oliva y Ocana, Dona. Fermina female 39.0 0 0 PC 17758 108.9 C105 C NaN

在1305行中確實存在 NaN 值。實際上相應的名稱是 Oliva y Ocana, **Dona**. Fermina

在訓練數(shù)據(jù)集中沒有遇到這個標題。

很好,現(xiàn)在我們有一個名為 Title 的附加列來包含這些信息。

處理年齡(Age)

我們在第一部分中看到 Age 變量缺少177個值。這是一個很大的數(shù)字(約占數(shù)據(jù)集的13%)。簡單地用平均年齡或中位年齡替換它們可能不是最佳解決方案,因為年齡可能因乘客的類別和類別而不同。

為了理解原因,讓我們按性別(Sex),稱謂(Title)和乘客類(Pclass)對我們的數(shù)據(jù)集進行分組,并為每個子集計算中位數(shù)年齡。

為了避免測試集中的數(shù)據(jù)泄漏,我們使用訓練集填寫訓練中的缺失年齡,并且我們使用從訓練集計算的值來填充測試集中的年齡。

訓練級中缺少的年齡數(shù)

print combined.iloc[:891].Age.isnull().sum()
177

測試集中缺少的年齡數(shù)

print combined.iloc[891:].Age.isnull().sum()
86
grouped_train = combined.iloc[:891].groupby(["Sex","Pclass","Title"])
grouped_median_train = grouped_train.median()
grouped_median_train = grouped_median_train.reset_index()[["Sex", "Pclass", "Title", "Age"]]
grouped_median_train.head()

Sex Pclass Title Age
0 female 1 Miss 30.0
1 female 1 Mrs 40.0
2 female 1 Officer 49.0
3 female 1 Royalty 40.5
4 female 2 Miss 24.0

此 dataframe 將幫助我們根據(jù)不同的標準估算缺失的年齡值。

查看中位年齡列,看看這個值如何根據(jù) SexPclassTitle 組合在一起。

例如:

如果乘客是女性,則來自 Pclass 1 和來自王室(royalty),中位年齡為40.5歲。

如果乘客是男性,來自 Pclass 3,擁有 Mr 稱謂,則年齡中位數(shù)為26歲。

讓我們創(chuàng)建一個函數(shù),根據(jù)這些不同的屬性填充 組合 中的缺失年齡。

def fill_age(row):
    condition = (
        (grouped_median_train["Sex"] == row["Sex"]) & 
        (grouped_median_train["Title"] == row["Title"]) & 
        (grouped_median_train["Pclass"] == row["Pclass"])
    )
    return grouped_median_train[condition]["Age"].values[0]


def process_age():
    global combined
    # a function that fills the missing values of the Age variable
    combined["Age"] = combined.apply(lambda row: fill_age(row) if np.isnan(row["Age"]) else row["Age"], axis=1)
    status("age")
    return combined
combined = process_age()
Processing age : ok

完美。失蹤的年齡已被取代。

但是,我們注意到票價(Fare)中缺少1個值,登船位置(Embarked)有兩個缺失值,而船艙位置(Cabin)有很多缺失值。我們稍后會處理這些變量。

我們現(xiàn)在處理名字。

def process_names():
    global combined
    # we clean the Name variable
    combined.drop("Name", axis=1, inplace=True)

    # encoding in dummy variable
    titles_dummies = pd.get_dummies(combined["Title"], prefix="Title")
    combined = pd.concat([combined, titles_dummies], axis=1)

    # removing the title variable
    combined.drop("Title", axis=1, inplace=True)

    status("names")
    return combined

此函數(shù)會刪除 Name 列,我們不再使用它,因為我們創(chuàng)建了 Title 列。

然后我們使用虛擬編碼(dummy encoding)對稱謂值進行編碼。

您可以了解虛擬編碼以及如何在 Pandas 中輕松完成此操作。

combined = process_names()
Processing names : ok
combined.head()

Pclass Sex Age SibSp Parch Ticket Fare Cabin Embarked Title_Master Title_Miss Title_Mr Title_Mrs Title_Officer Title_Royalty
0 3 male 22.0 1 0 A/5 21171 7.2500 NaN S 0 0 1 0 0 0
1 1 female 38.0 1 0 PC 17599 71.2833 C85 C 0 0 0 1 0 0
2 3 female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 0 1 0 0 0 0
3 1 female 35.0 1 0 113803 53.1000 C123 S 0 0 0 1 0 0
4 3 male 35.0 0 0 373450 8.0500 NaN S 0 0 1 0 0 0

如你看到的 :

不再有名字特征。

出現(xiàn)了新的變量(Title_X)。這些特征是二進制的。

例如,如果 Title_Mr = 1,則相應的稱謂為 Mr。

處理票價(Fare)

讓我們通過在訓練集上計算的平均票價估算缺失的票價值。

def process_fares():
    global combined
    # there"s one missing fare value - replacing it with the mean.
    combined.Fare.fillna(combined.iloc[:891].Fare.mean(), inplace=True)
    status("fare")
    return combined

此函數(shù)用平均值替換一個缺失的票價(Fare)值。

combined = process_fares()
Processing fare : ok
處理登船位置(Embarked)
def process_embarked():
    global combined
    # two missing embarked values - filling them with the most frequent one in the train  set(S)
    combined.Embarked.fillna("S", inplace=True)
    # dummy encoding
    embarked_dummies = pd.get_dummies(combined["Embarked"], prefix="Embarked")
    combined = pd.concat([combined, embarked_dummies], axis=1)
    combined.drop("Embarked", axis=1, inplace=True)
    status("embarked")
    return combined

此函數(shù)用最常用的 Embarked 值替換了兩個缺失的 Embarked 值。

combined = process_embarked()
Processing embarked : ok
combined.head()

Pclass Sex Age SibSp Parch Ticket Fare Cabin Title_Master Title_Miss Title_Mr Title_Mrs Title_Officer Title_Royalty Embarked_C Embarked_Q Embarked_S
0 3 male 22.0 1 0 A/5 21171 7.2500 NaN 0 0 1 0 0 0 0 0 1
1 1 female 38.0 1 0 PC 17599 71.2833 C85 0 0 0 1 0 0 1 0 0
2 3 female 26.0 0 0 STON/O2. 3101282 7.9250 NaN 0 1 0 0 0 0 0 0 1
3 1 female 35.0 1 0 113803 53.1000 C123 0 0 0 1 0 0 0 0 1
4 3 male 35.0 0 0 373450 8.0500 NaN 0 0 1 0 0 0 0 0 1

處理船艙位置(Cabin)
train_cabin, test_cabin = set(), set()

for c in combined.iloc[:891]["Cabin"]:
    try:
        train_cabin.add(c[0])
    except:
        train_cabin.add("U")

for c in combined.iloc[891:]["Cabin"]:
    try:
        test_cabin.add(c[0])
    except:
        test_cabin.add("U")
print train_cabin
set(["A", "C", "B", "E", "D", "G", "F", "U", "T"])
print test_cabin
set(["A", "C", "B", "E", "D", "G", "F", "U"])

我們在測試集中沒有任何不存在于訓練集中的船艙位置字母。

def process_cabin():
    global combined
    # replacing missing cabins with U (for Uknown)
    combined.Cabin.fillna("U", inplace=True)

    # mapping each Cabin value with the cabin letter
    combined["Cabin"] = combined["Cabin"].map(lambda c: c[0])

    # dummy encoding ...
    cabin_dummies = pd.get_dummies(combined["Cabin"], prefix="Cabin")
    combined = pd.concat([combined, cabin_dummies], axis=1)

    combined.drop("Cabin", axis=1, inplace=True)
    status("cabin")
    return combined

此函數(shù)將 NaN 值替換為 U(表示 Unknow )。 然后它將每個 Cabin 值映射到第一個字母。
然后它再次使用虛擬編碼對艙位值進行編碼。

combined = process_cabin()
Processing cabin : ok

好了,沒有缺失值了。

combined.head()

Pclass Sex Age SibSp Parch Ticket Fare Title_Master Title_Miss Title_Mr Title_Mrs Title_Officer Title_Royalty Embarked_C Embarked_Q Embarked_S Cabin_A Cabin_B Cabin_C Cabin_D Cabin_E Cabin_F Cabin_G Cabin_T Cabin_U
0 3 male 22.0 1 0 A/5 21171 7.2500 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
1 1 female 38.0 1 0 PC 17599 71.2833 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0
2 3 female 26.0 0 0 STON/O2. 3101282 7.9250 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
3 1 female 35.0 1 0 113803 53.1000 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0
4 3 male 35.0 0 0 373450 8.0500 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1

處理性別(Sex)
def process_sex():
    global combined
    # mapping string values to numerical one
    combined["Sex"] = combined["Sex"].map({"male":1, "female":0})
    status("Sex")
    return combined

此函數(shù)將字符串值 malefemale 分別映射到1和0。

combined = process_sex()
Processing Sex : ok
處理乘客等級(Pclass)
def process_pclass():

    global combined
    # encoding into 3 categories:
    pclass_dummies = pd.get_dummies(combined["Pclass"], prefix="Pclass")

    # adding dummy variable
    combined = pd.concat([combined, pclass_dummies],axis=1)

    # removing "Pclass"
    combined.drop("Pclass",axis=1,inplace=True)

    status("Pclass")
    return combined

此函數(shù)使用虛擬編碼對 Pclass(1,2,3)的值進行編碼。

combined = process_pclass()
Processing Pclass : ok
處理船票號碼(Ticket)

讓我們首先看看我們的數(shù)據(jù)集中不同的船票號碼前綴

def cleanTicket(ticket):
    ticket = ticket.replace(".", "")
    ticket = ticket.replace("/", "")
    ticket = ticket.split()
    ticket = map(lambda t : t.strip(), ticket)
    ticket = list(filter(lambda t : not t.isdigit(), ticket))
    if len(ticket) > 0:
        return ticket[0]
    else:
        return "XXX"
tickets = set()
for t in combined["Ticket"]:
    tickets.add(cleanTicket(t))
print len(tickets)
37
def process_ticket():

    global combined

    # a function that extracts each prefix of the ticket, returns "XXX" if no prefix (i.e the ticket is a digit)
    def cleanTicket(ticket):
        ticket = ticket.replace(".","")
        ticket = ticket.replace("/","")
        ticket = ticket.split()
        ticket = map(lambda t : t.strip(), ticket)
        ticket = filter(lambda t : not t.isdigit(), ticket)
        if len(ticket) > 0:
            return ticket[0]
        else:
            return "XXX"


    # Extracting dummy variables from tickets:

    combined["Ticket"] = combined["Ticket"].map(cleanTicket)
    tickets_dummies = pd.get_dummies(combined["Ticket"], prefix="Ticket")
    combined = pd.concat([combined, tickets_dummies], axis=1)
    combined.drop("Ticket", inplace=True, axis=1)

    status("Ticket")
    return combined
combined = process_ticket()
Processing Ticket : ok
處理家庭

這部分包括根據(jù)家庭的大小創(chuàng)建新變量(大小是我們創(chuàng)建的另一個變量)。

這種新變量的創(chuàng)建是在一個現(xiàn)實的假設(shè)下完成的:大家庭聚集在一起,因此他們比多帶帶旅行的人更有可能獲救。

def process_family():

    global combined
    # introducing a new feature : the size of families (including the passenger)
    combined["FamilySize"] = combined["Parch"] + combined["SibSp"] + 1

    # introducing other features based on the family size
    combined["Singleton"] = combined["FamilySize"].map(lambda s: 1 if s == 1 else 0)
    combined["SmallFamily"] = combined["FamilySize"].map(lambda s: 1 if 2 <= s <= 4 else 0)
    combined["LargeFamily"] = combined["FamilySize"].map(lambda s: 1 if 5 <= s else 0)

    status("family")
    return combined

此函數(shù)引入了4個新特征:

FamilySize:包括乘客(他/她)自己在內(nèi)的親屬總數(shù)。

Sigleton:描述 size = 1 的家庭的布爾變量

SmallFamily:一個布爾變量,描述 2 <= size <= 4 的家庭

LargeFamily:一個布爾變量,描述 5 < size 的家庭

combined = process_family()
Processing family : ok
print combined.shape
(1309, 67)

最后我們得到了67個特征。

combined.head()

Sex Age SibSp Parch Fare Title_Master Title_Miss Title_Mr Title_Mrs Title_Officer Title_Royalty Embarked_C Embarked_Q Embarked_S Cabin_A Cabin_B Cabin_C Cabin_D Cabin_E Cabin_F Cabin_G Cabin_T Cabin_U Pclass_1 Pclass_2 Pclass_3 Ticket_A Ticket_A4 Ticket_A5 Ticket_AQ3 Ticket_AQ4 Ticket_AS Ticket_C Ticket_CA Ticket_CASOTON Ticket_FC Ticket_FCC Ticket_Fa Ticket_LINE Ticket_LP Ticket_PC Ticket_PP Ticket_PPP Ticket_SC Ticket_SCA3 Ticket_SCA4 Ticket_SCAH Ticket_SCOW Ticket_SCPARIS Ticket_SCParis Ticket_SOC Ticket_SOP Ticket_SOPP Ticket_SOTONO2 Ticket_SOTONOQ Ticket_SP Ticket_STONO Ticket_STONO2 Ticket_STONOQ Ticket_SWPP Ticket_WC Ticket_WEP Ticket_XXX FamilySize Singleton SmallFamily LargeFamily
0 1 22.0 1 0 7.2500 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0
1 0 38.0 1 0 71.2833 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0
2 0 26.0 0 0 7.9250 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0
3 0 35.0 1 0 53.1000 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 1 0
4 1 35.0 0 0 8.0500 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0

III - 模型

在這一部分中,我們根據(jù)我們創(chuàng)建的特征建立統(tǒng)計模型。您可以將此模型視為一個盒子,它可以處理任何新乘客的信息,并決定他是否能夠幸存。

有各種各樣的模型可供使用,從邏輯回歸到?jīng)Q策樹,以及更復雜的模型,如隨機森林和梯度提升樹。

我們將使用隨機森林。Random Froests 在 Kaggle 比賽中證明了很高的有效性。

有關(guān)為什么集合方法表現(xiàn)良好的更多詳細信息,您可以參考這些帖子:

http://mlwave.com/kaggle-ense...

http://www.overkillanalytics....

回到我們的問題,我們現(xiàn)在必須:

1.將組合數(shù)據(jù)集分成訓練集和測試集。
2.使用訓練集建立預測模型。
3.使用訓練集評估模型。
4.使用測試集測試模型,并生成并輸出提交文件。

請記住,我們必須重復 2 和 3 直到達到可接受的評估分數(shù)。

讓我們首先導入需要用到的函數(shù)包。

from sklearn.pipeline import make_pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble.gradient_boosting import GradientBoostingClassifier
from sklearn.feature_selection import SelectKBest
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression, LogisticRegressionCV

為了評估我們的模型,我們將使用5折交叉驗證(5-fold cross validation),因為它是在比賽排行榜中使用的指標。

為此,我們將定義一個小的評分函數(shù)。

def compute_score(clf, X, y, scoring="accuracy"):
    xval = cross_val_score(clf, X, y, cv = 5, scoring=scoring)
    return np.mean(xval)

從組合數(shù)據(jù)集中恢復訓練集和測試集是一項簡單的任務。

def recover_train_test_target():
    global combined

    targets = pd.read_csv("./data/train.csv", usecols=["Survived"])["Survived"].values
    train = combined.iloc[:891]
    test = combined.iloc[891:]

    return train, test, targets
train, test, targets = recover_train_test_target()
特征選擇

到目前為止,我們已經(jīng)提出了30多個特征。這個數(shù)字非常大。

在完成特征工程時,我們通常傾向于通過選擇捕獲基本特征的“正確”數(shù)量的特征來減少維度。

事實上,特征選擇帶來許多好處:

它減少了數(shù)據(jù)之間的冗余

它加快了訓練過程

它減少過擬合

基于樹的估算器可用于計算特征重要性,而這些重要性又可用于丟棄不相關(guān)的特征。

clf = RandomForestClassifier(n_estimators=50, max_features="sqrt")
clf = clf.fit(train, targets)

讓我們看看每個特征的重要性。

features = pd.DataFrame()
features["feature"] = train.columns
features["importance"] = clf.feature_importances_
features.sort_values(by=["importance"], ascending=True, inplace=True)
features.set_index("feature", inplace=True)
features.plot(kind="barh", figsize=(25, 25))

正如您可能注意到的那樣,與 Title_MrAgeFareSex 相關(guān)聯(lián)非常重要。

Passenger_Id 也有重要的相關(guān)性。

現(xiàn)在讓我們將我們的訓練集和測試集轉(zhuǎn)換為更緊湊的數(shù)據(jù)集。

model = SelectFromModel(clf, prefit=True)
train_reduced = model.transform(train)
print train_reduced.shape
(891, 12)
test_reduced = model.transform(test)
print test_reduced.shape
(418, 12)

好極了! 現(xiàn)在我們的特征減少了很多。

我們將看看我們是否會使用訓練集的減少版或完整版。

讓我們嘗試不同的基礎(chǔ)模型
logreg = LogisticRegression()
logreg_cv = LogisticRegressionCV()
rf = RandomForestClassifier()
gboost = GradientBoostingClassifier()

models = [logreg, logreg_cv, rf, gboost]
for model in models:
    print "Cross-validation of : {0}".format(model.__class__)
    score = compute_score(clf=model, X=train_reduced, y=targets, scoring="accuracy")
    print "CV score = {0}".format(score)
    print "****"
Cross-validation of : 
CV score = 0.818195097715
****
Cross-validation of : 
CV score = 0.81818240172
****
Cross-validation of : 
CV score = 0.808183171282
****
Cross-validation of : 
CV score = 0.824917697684
****
超參數(shù)調(diào)整

正如建模部分的開頭所提到的,我們將使用隨機森林模型。它可能不是這項任務的最佳模型,但我們將展示如何調(diào)整。這項工作可以應用于不同的模型。

隨機森林非常方便。然而,它們會帶有一些參數(shù)進行調(diào)整,以便為預測任務獲得最佳模型。

要了解有關(guān)隨機森林的更多信息,請參閱此 鏈接。

此外,我們將使用全部訓練集。

# turn run_gs to True if you want to run the gridsearch again.
run_gs = False

if run_gs:
    parameter_grid = {
                 "max_depth" : [4, 6, 8],
                 "n_estimators": [50, 10],
                 "max_features": ["sqrt", "auto", "log2"],
                 "min_samples_split": [2, 3, 10],
                 "min_samples_leaf": [1, 3, 10],
                 "bootstrap": [True, False],
                 }
    forest = RandomForestClassifier()
    cross_validation = StratifiedKFold(n_splits=5)

    grid_search = GridSearchCV(forest,
                               scoring="accuracy",
                               param_grid=parameter_grid,
                               cv=cross_validation,
                               verbose=1
                              )

    grid_search.fit(train, targets)
    model = grid_search
    parameters = grid_search.best_params_

    print("Best score: {}".format(grid_search.best_score_))
    print("Best parameters: {}".format(grid_search.best_params_))

else:
    parameters = {"bootstrap": False, "min_samples_leaf": 3, "n_estimators": 50,
                  "min_samples_split": 10, "max_features": "sqrt", "max_depth": 6}

    model = RandomForestClassifier(**parameters)
    model.fit(train, targets)

現(xiàn)在通過掃描超參數(shù)的幾個組合來構(gòu)建模型,我們可以生成一個輸出文件以在 Kaggle 上提交。

output = model.predict(test).astype(int)
df_output = pd.DataFrame()
aux = pd.read_csv("./data/test.csv")
df_output["PassengerId"] = aux["PassengerId"]
df_output["Survived"] = output
df_output[["PassengerId","Survived"]].to_csv("./predictions/gridsearch_rf.csv", index=False)
[BONUS] 混合不同模型

我沒有親自上傳基于模型混合的提交,但這是你可以這么做:

trained_models = []
for model in models:
    model.fit(train, targets)
    trained_models.append(model)

predictions = []
for model in trained_models:
    predictions.append(model.predict_proba(test)[:, 1])

predictions_df = pd.DataFrame(predictions).T
predictions_df["out"] = predictions_df.mean(axis=1)
predictions_df["PassengerId"] = aux["PassengerId"]
predictions_df["out"] = predictions_df["out"].map(lambda s: 1 if s >= 0.5 else 0)

predictions_df = predictions_df[["PassengerId", "out"]]
predictions_df.columns = ["PassengerId", "Survived"]
predictions_df.to_csv("./predictions/blending_base_models.csv", index=False)

為了獲得良好的混合提交,基本模型應該是不同的,并且它們的相關(guān)性是不相關(guān)的。

IV - 結(jié)論

在本文中,我們探討了 Kaggle 帶給我們的一個有趣的數(shù)據(jù)集。

我們?yōu)g覽了數(shù)據(jù)科學管道的基本要點:

數(shù)據(jù)探索和可視化:制定假設(shè)的第一步

數(shù)據(jù)清理

特征工程

特征選擇

超參數(shù)調(diào)整

提交

混合

如果您想測試和使用它,可以將此博客下載為筆記本:我的 github repo

譯者注:此中文翻譯地址為: qiwihui 的 github repo

關(guān)于這一挑戰(zhàn)的文章很多,所以顯然還有改進的余地。

以下是我建議的后續(xù)步驟:

挖掘更多數(shù)據(jù)并最終構(gòu)建新特征。

嘗試不同的模型:邏輯回歸,Gradient Boosted Tree,XGboost 等。

嘗試集成學習技巧(堆疊)

運行 auto-ML 框架

如果你能找到改善我的解決方案的方法,我會非常高興。這可以讓我更新文章,絕對給你信任。所以請隨時發(fā)表評論。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/43161.html

相關(guān)文章

  • Kaggle案例——用python從進網(wǎng)站到獲得評測結(jié)果

    摘要:訓練集是用來訓練你的機器學習模型的。但機器學習,你也要教它一些事實,比如長得像圖片的就是狗,長得像圖片的就是貓。好了,這樣我們整體的一個機器學習的簡單項目就完成,但我們還是要看一下效果。 最近寫了Kaggle的一個playground項目——預測科比投籃是否命中https://www.kaggle.com/c/kobe...,主要使用python的pandas和sklearn包。 這里...

    Crazy_Coder 評論0 收藏0
  • 人工智能/數(shù)據(jù)科學比賽匯總 2019.6

    摘要:內(nèi)容來自,人工智能數(shù)據(jù)科學比賽整理平臺。大賽面向全球高校在校生開放,旨在提升高校學生對數(shù)據(jù)分析與處理的算法研究與技術(shù)應用能力,探索大數(shù)據(jù)的核心科學與技術(shù)問題,嘗試創(chuàng)新大數(shù)據(jù)技術(shù),推動大數(shù)據(jù)的產(chǎn)學研用,本次大賽鼓勵高校教師參與指導。 內(nèi)容來自 DataSciComp,人工智能/數(shù)據(jù)科學比賽整理平臺。Github:iphysresearch/DataSciComp 本項目由 ApacheC...

    gyl_coder 評論0 收藏0
  • 人工智能/數(shù)據(jù)科學比賽匯總 2019.5

    摘要:內(nèi)容來自,人工智能數(shù)據(jù)科學比賽整理平臺。本項目由強力支持。每篇文章識別最多三個核心實體,并分別判斷文章對上述核心實體的情感傾向積極中立消極三種。 Special Sponsors showImg(https://segmentfault.com/img/remote/1460000018907426?w=1760&h=200); 內(nèi)容來自 DataSciComp,人工智能/數(shù)據(jù)科學比賽...

    bovenson 評論0 收藏0
  • 人工智障也刷題!Kaggle 入門之實戰(zhàn)泰坦尼克號

    showImg(https://segmentfault.com/img/bVbkB4E?w=800&h=400); 背景 關(guān)于 Kaggle https://www.kaggle.com/ 這是一個為你提供完美數(shù)據(jù),為你提供實際應用場景,可以與小伙伴在數(shù)據(jù)挖掘領(lǐng)域 high 的不要不要的的地方啊!!! Kaggle 是一個用來學習、分享和競賽的線上數(shù)據(jù)實驗平臺,有點類似 KDD—CUP(國際...

    bergwhite 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<