Резюме проекта

В этом проекте я исследовал Titanic Data с помощью библиотек Python, таких как NumPy, Pandas, Seaborn, Matplotlib, SciPy и Scikit-learn.

Информация о наборе данных или словаре данных и примечания к переменным

Неудачная гибель крупнейшего корабля под названием «Великий Титаник» является одним из крупнейших кораблекрушений в мировой истории. Во время плавания кораблей 15 апреля 1912 года Титаник затонул после столкновения с огромным айсбергом, в результате чего погибли 1502 из 2224 членов экипажа и пассажиров. Эта сенсационная трагедия потрясла мировую общественность, что привело к улучшению проверок безопасности и правил для новых судов.

Основная причина, по которой в результате кораблекрушения погибло так много людей, заключалась в том, что не хватило спасательных шлюпок для пассажиров и экипажа. Это произошло из-за неправильного прогнозирования и планирования инцидентов или несчастных случаев.

Некоторым из них посчастливилось выжить в тот день из-за поддержки всеми возможными способами, очень немногие из них имели больше шансов выжить, чем остальные, такие как дети, женщины и высший класс.

Прогнозы выживания Титаника

Рохан РК

Прогноз выживания корабля «Титаник» — один из известных проектов для начинающих, в котором мы будем изучать методы и процедуры для нахождения понимания и открытия новых фактов и прогнозов на основе этого и моделей Ml.

  • Содержание:
  1. Импорт необходимых библиотек
  2. Читайте и исследуйте данные
  3. Анализ данных
  4. Визуализация данных
  5. Очистка данных
  6. Выбор лучшей модели
  7. Создание файла отправки

Любая обратная связь приветствуется!

1) Импорт необходимых библиотек

Во-первых, нам нужно импортировать несколько библиотек Python, таких как numpy, pandas, matplotlib и seaborn.

In [2]:

#data analysis libraries 
import numpy as np
import pandas as pd
#visualization libraries
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
#ignore warnings
import warnings
warnings.filterwarnings('ignore')

2) Читайте и исследуйте данные

Пришло время прочитать наши данные обучения и тестирования с помощью pd.read_csv и впервые взглянуть на данные обучения с помощью функции describe().

In [3]:

#import train and test CSV files
train = pd.read_csv("train.csv")  # train = pd.read_csv(r"c:Desktop/File_Address/train.csv")
test = pd.read_csv("test.csv")
#take a look at the training data
train.describe(include="all")

Выход[3]:

PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedcount891.000000891.000000891.000000891891714.000000891.000000891.000000891.000000891891.000000204889uniqueNaNNa NNaN8912NaNNaNNaN681NaN1473topNaNNaNNaNБиван, мистер Уильям ТомасмалеNaNNaNNaNCA. 2343NaNG6SfreqNaNNaNNaN1577NaNNaNNaN7NaN4644mean446.0000000.3838382.308642NaNNaN29.6991180.5230080.381594NaN32.204208NaNNaNstd257.353 8420.4865920.836071NaNNaN14.5264971.1027430.806057NaN49.693429NaNNaNmin1.0000000.0000001.000000NaNNaN0.4200000.0000000.000000NaN 0.000000NaNNaN25%223.5000000.0000002.000000NaNNaN20.1250000.0000000.000000NaN7.910400NaNNaN50%446.0000000.0000003.000000NaNNaN2 8.0000000.0000000. 000000NaN14.454200NaNNaN75%668.5000001.0000003.000000NaNNaN38.0000001.0000000.000000NaN31.000000NaNNaNmax891.0000001.0000003.0 00000NaNNaN80.0000008.0000006.000000NaN512.329200NaNNaN

Выход[3]:

PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedcount891.000000891.000000891.000000891891714.000000891.000000891.000000891.000000891891.000000204889uniqueNaNNa NNaN8912NaNNaNNaN681NaN1473topNaNNaNNaNБиван, мистер Уильям ТомасмалеNaNNaNNaNCA. 2343NaNG6SfreqNaNNaNNaN1577NaNNaNNaN7NaN4644mean446.0000000.3838382.308642NaNNaN29.6991180.5230080.381594NaN32.204208NaNNaNstd257.353 8420.4865920.836071NaNNaN14.5264971.1027430.806057NaN49.693429NaNNaNmin1.0000000.0000001.000000NaNNaN0.4200000.0000000.000000NaN 0.000000NaNNaN25%223.5000000.0000002.000000NaNNaN20.1250000.0000000.000000NaN7.910400NaNNaN50%446.0000000.0000003.000000NaNNaN2 8.0000000.0000000. 000000NaN14.454200NaNNaN75%668.5000001.0000003.000000NaNNaN38.0000001.0000000.000000NaN31.000000NaNNaNmax891.0000001.0000003.0 00000NaNNaN80.0000008.0000006.000000NaN512.329200NaNNaN

3) Анализ данных

Мы собираемся рассмотреть функции в наборе данных и их полноту.

In [5]:

#get a list of the features within the dataset
print(train.columns)
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
       'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
      dtype='object')
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
       'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
      dtype='object')

In [6]:

#see a sample of the dataset to get an idea of the variables
train.sample(5)
# train.head(10)

Выход[6]:

PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked33633701Pears, Mr. Thomas Clintonmale29.01011377666.6000C2S13013103Drazenoic, Mr. Jozefmale33.0003492417.8958NaNC34935003Di mic, Mr. Jovanmale42.0003150888.6625NaNS11011101Porter, Mr. Walter Chamberlainmale47.00011046552.0000C110S28728803Naidenoff, Mr. Penkomale22.0003492067.8958NaNS

Выход[6]:

PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked33633701Pears, Mr. Thomas Clintonmale29.01011377666.6000C2S13013103Drazenoic, Mr. Jozefmale33.0003492417.8958NaNC34935003Di mic, Mr. Jovanmale42.0003150888.6625NaNS11011101Porter, Mr. Walter Chamberlainmale47.00011046552.0000C110S28728803Naidenoff, Mr. Penkomale22.0003492067.8958NaNS

  • Числовые характеристики: возраст (непрерывный), тариф (непрерывный), SibSp (дискретный), Parch (дискретный)
  • Категорические характеристики: выжили, пол, отправились на посадку, класс класса
  • Буквенно-цифровые функции: билет, каюта

Каковы типы данных для каждой функции?

  • Выжил: инт
  • Pкласс: интервал
  • Имя: строка
  • Пол: строка
  • Возраст: поплавок
  • СибСп: инт
  • Парч: инт
  • Билет: строка
  • Тариф: плавающий
  • Кабина: струнная
  • Принято: строка

Теперь, когда у нас есть представление о том, с какими функциями мы работаем, мы можем увидеть, сколько информации у нас есть о каждой из них.

In [7]:

#see a summary of the training dataset
train.describe(include = "all")
#train.describe()

Выход[7]:

PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedcount891.000000891.000000891.000000891891714.000000891.000000891.000000891.000000891891.000000204889uniqueNaNNa NNaN8912NaNNaNNaN681NaN1473topNaNNaNNaNБиван, мистер Уильям ТомасмалеNaNNaNNaNCA. 2343NaNG6SfreqNaNNaNNaN1577NaNNaNNaN7NaN4644mean446.0000000.3838382.308642NaNNaN29.6991180.5230080.381594NaN32.204208NaNNaNstd257.353 8420.4865920.836071NaNNaN14.5264971.1027430.806057NaN49.693429NaNNaNmin1.0000000.0000001.000000NaNNaN0.4200000.0000000.000000NaN 0.000000NaNNaN25%223.5000000.0000002.000000NaNNaN20.1250000.0000000.000000NaN7.910400NaNNaN50%446.0000000.0000003.000000NaNNaN2 8.0000000.0000000. 000000NaN14.454200NaNNaN75%668.5000001.0000003.000000NaNNaN38.0000001.0000000.000000NaN31.000000NaNNaNmax891.0000001.0000003.0 00000NaNNaN80.0000008.0000006.000000NaN512.329200NaNNaN

Выход[7]:

PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedcount891.000000891.000000891.000000891891714.000000891.000000891.000000891.000000891891.000000204889uniqueNaNNa NNaN8912NaNNaNNaN681NaN1473topNaNNaNNaNБиван, мистер Уильям ТомасмалеNaNNaNNaNCA. 2343NaNG6SfreqNaNNaNNaN1577NaNNaNNaN7NaN4644mean446.0000000.3838382.308642NaNNaN29.6991180.5230080.381594NaN32.204208NaNNaNstd257.353 8420.4865920.836071NaNNaN14.5264971.1027430.806057NaN49.693429NaNNaNmin1.0000000.0000001.000000NaNNaN0.4200000.0000000.000000NaN 0.000000NaNNaN25%223.5000000.0000002.000000NaNNaN20.1250000.0000000.000000NaN7.910400NaNNaN50%446.0000000.0000003.000000NaNNaN2 8.0000000.0000000. 000000NaN14.454200NaNNaN75%668.5000001.0000003.000000NaNNaN38.0000001.0000000.000000NaN31.000000NaNNaNmax891.0000001.0000003.0 00000NaNNaN80.0000008.0000006.000000NaN512.329200NaNNaN

Некоторые наблюдения:

  • Всего в нашей обучающей выборке 891 пассажир.
  • В функции «Возраст» отсутствует примерно 19,8% значений. Я предполагаю, что функция «Возраст» очень важна для выживания, поэтому нам, вероятно, следует попытаться заполнить эти пробелы.
  • В функции «Кабина» отсутствует примерно 77,1% значений. Поскольку многие функции отсутствуют, было бы трудно заполнить недостающие значения. Мы, вероятно, удалим эти значения из нашего набора данных.
  • У функции Embarked отсутствует 0,22% ее значений, что должно быть относительно безвредным.

In [8]:

#check for any other unusable values
print(pd.isnull(train).sum())
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64

Мы видим, что, за исключением вышеупомянутых отсутствующих значений, значений NaN не существует.

Некоторые прогнозы:

  • Пол: у самок больше шансов выжить.
  • SibSp/Parch: У людей, путешествующих в одиночку, больше шансов выжить.
  • Возраст: у маленьких детей больше шансов выжить.
  • Pclass: Люди более высокого социально-экономического класса имеют больше шансов выжить.

4) Визуализация данных

Пришло время визуализировать наши данные, чтобы мы могли увидеть, были ли наши прогнозы точными!

секс функция

In [9]:

#draw a bar plot of survival by sex
sns.barplot(x="Sex", y="Survived", data=train)
#print percentages of females vs. males that survive
print("Percentage of females who survived:", train["Survived"][train["Sex"] == 'female'].value_counts(normalize = True)[1]*100)
print("Percentage of males who survived:", train["Survived"][train["Sex"] == 'male'].value_counts(normalize = True)[1]*100)
Percentage of females who survived: 74.20382165605095
Percentage of males who survived: 18.890814558058924
Percentage of females who survived: 74.20382165605095
Percentage of males who survived: 18.890814558058924

Как и предполагалось, у самок гораздо больше шансов выжить, чем у самцов. Половая характеристика имеет важное значение в наших прогнозах.

Функция P-класса

In [10]:

#draw a bar plot of survival by Pclass
sns.barplot(x="Pclass", y="Survived", data=train)
#print percentage of people by Pclass that survived
print("Percentage of Pclass = 1 who survived:", train["Survived"][train["Pclass"] == 1].value_counts(normalize = True)[1]*100)
print("Percentage of Pclass = 2 who survived:", train["Survived"][train["Pclass"] == 2].value_counts(normalize = True)[1]*100)
print("Percentage of Pclass = 3 who survived:", train["Survived"][train["Pclass"] == 3].value_counts(normalize = True)[1]*100)

Как и предполагалось, люди с более высоким социально-экономическим классом имели более высокий уровень выживания. (62,9% против 47,3% против 24,2%)

СибСп Особенность

In [11]:

#draw a bar plot for SibSp vs. survival
sns.barplot(x="SibSp", y="Survived", data=train)
#I won't be printing individual percent values for all of these.
print("Percentage of SibSp = 0 who survived:", train["Survived"][train["SibSp"] == 0].value_counts(normalize = True)[1]*100)
print("Percentage of SibSp = 1 who survived:", train["Survived"][train["SibSp"] == 1].value_counts(normalize = True)[1]*100)
print("Percentage of SibSp = 2 who survived:", train["Survived"][train["SibSp"] == 2].value_counts(normalize = True)[1]*100)
Percentage of SibSp = 0 who survived: 34.53947368421053
Percentage of SibSp = 1 who survived: 53.588516746411486
Percentage of SibSp = 2 who survived: 46.42857142857143
Percentage of SibSp = 0 who survived: 34.53947368421053
Percentage of SibSp = 1 who survived: 53.588516746411486
Percentage of SibSp = 2 who survived: 46.42857142857143

В целом ясно, что люди, у которых на борту было больше братьев, сестер или супругов, имели меньше шансов выжить. Однако, вопреки ожиданиям, у людей без братьев, сестер или супругов было меньше шансов выжить, чем у тех, у кого был один или два. (34,5% против 53,4% против 46,4%)

Парч

In [12]:

#draw a bar plot for Parch vs. survival
sns.barplot(x="Parch", y="Survived", data=train)
plt.show()

У людей с менее чем четырьмя родителями или детьми на борту больше шансов выжить, чем у тех, у кого четверо или более. Опять же, у людей, путешествующих в одиночку, меньше шансов выжить, чем у тех, у кого есть 1–3 родителей или детей.

Возраст

In [13]:

#sort the ages into logical categories
train["Age"] = train["Age"].fillna(-0.5)
test["Age"] = test["Age"].fillna(-0.5)
bins = [-1, 0, 5, 12, 18, 24, 35, 60, np.inf]
labels = ['Unknown', 'Baby', 'Child', 'Teenager', 'Student', 'Young Adult', 'Adult', 'Senior']
train['AgeGroup'] = pd.cut(train["Age"], bins, labels = labels)
test['AgeGroup'] = pd.cut(test["Age"], bins, labels = labels)
#draw a bar plot of Age vs. survival
sns.barplot(x="AgeGroup", y="Survived", data=train)
plt.show()

Младенцы имеют больше шансов выжить, чем любая другая возрастная группа.

Особенности кабины

Я думаю, что идея здесь в том, что люди с зарегистрированными номерами кабин принадлежат к более высокому социально-экономическому классу и, следовательно, имеют больше шансов выжить. Спасибо за советы, @salvus82 и Daniel Ellis!

In [14]:

train["CabinBool"] = (train["Cabin"].notnull().astype('int'))
test["CabinBool"] = (test["Cabin"].notnull().astype('int'))
#calculate percentages of CabinBool vs. survived
print("Percentage of CabinBool = 1 who survived:", train["Survived"][train["CabinBool"] == 1].value_counts(normalize = True)[1]*100)
print("Percentage of CabinBool = 0 who survived:", train["Survived"][train["CabinBool"] == 0].value_counts(normalize = True)[1]*100)
#draw a bar plot of CabinBool vs. survival
sns.barplot(x="CabinBool", y="Survived", data=train)
plt.show()
Percentage of CabinBool = 1 who survived: 66.66666666666666
Percentage of CabinBool = 0 who survived: 29.985443959243085
Percentage of CabinBool = 1 who survived: 66.66666666666666
Percentage of CabinBool = 0 who survived: 29.985443959243085

На самом деле у людей с записанным номером каюты больше шансов выжить. (66,6% против 29,9%)

5) Очистка данных

Пришло время очистить наши данные от пропущенных значений и ненужной информации!

Глядя на тестовые данные

Давайте посмотрим, как выглядят наши тестовые данные!

In [15]:

test.describe(include="all")

Исход[15]:

PassengerIdPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedAgeGroupCabinBoolcount418.000000418.000000418418418.000000418.000000418.000000418417.00000091418418418.000 000uniqueNaNNaN4182NaNNaNNaN363NaN7638NaNtopNaNNanSincock, Miss MaudemaleNaNNaNNaNPC 17608NaNB57 B59 B63 B66SYoung AdultNaNfreqNaNNaN1266NanNaNNaN5NaN327096NaNmean1100 .5000002.265550NaNNaN23.9413880.4473680.392344NaN35.627188NaNNaNNaN0.217703std120.8104580.841838NaNNaN17.7410800.8967600.981429N АН55.907576НАННАННАН0.413179мин892.0000001.000000НАННАН-0.5000000.0000000.000000НАН0.000000НАНННАНН0 .00000025%996.2500001.000000NaNNaN9.0000000.0000000.000000NaN7.895800NaNNaNNaN0.00000050%1100.5000003.000000NaNNaN24.0000000. 0000000.000000NaN14.454200NaNNaNNaN0.00000075%1204.7500003.000000NaNNaN35.7500001.0000000.000000NaN31.500000NaNNaNNaN0.000000max13 09.0000003.000000NaNNaN76.0000008.0000009.000000NaN512.329200NaNNaN1.000000

Исход[15]:

PassengerIdPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedAgeGroupCabinBoolcount418.000000418.000000418418418.000000418.000000418.000000418417.00000091418418418.000 000uniqueNaNNaN4182NaNNaNNaN363NaN7638NaNtopNaNNanSincock, Miss MaudemaleNaNNaNNaNPC 17608NaNB57 B59 B63 B66SYoung AdultNaNfreqNaNNaN1266NanNaNNaN5NaN327096NaNmean1100 .5000002.265550NaNNaN23.9413880.4473680.392344NaN35.627188NaNNaNNaN0.217703std120.8104580.841838NaNNaN17.7410800.8967600.981429N АН55.907576НАННАННАН0.413179мин892.0000001.000000НАННАН-0.5000000.0000000.000000НАН0.000000НАНННАНН0 .00000025%996.2500001.000000NaNNaN9.0000000.0000000.000000NaN7.895800NaNNaNNaN0.00000050%1100.5000003.000000NaNNaN24.0000000. 0000000.000000NaN14.454200NaNNaNNaN0.00000075%1204.7500003.000000NaNNaN35.7500001.0000000.000000NaN31.500000NaNNaNNaN0.000000max13 09.0000003.000000NaNNaN76.0000008.0000009.000000NaN512.329200NaNNaN1.000000

  • Всего у нас 418 пассажиров.
  • Отсутствует 1 значение функции «Тариф».
  • Около 20,5% функции «Возраст» отсутствуют, нам нужно будет это заполнить.

Особенности кабины

In [16]:

#we'll start off by dropping the Cabin feature since not a lot more useful information can be extracted from it.
train = train.drop(['Cabin'], axis = 1)
test = test.drop(['Cabin'], axis = 1)

Функция билета

In [17]:

#we can also drop the Ticket feature since it's unlikely to yield any useful information
train = train.drop(['Ticket'], axis = 1)
test = test.drop(['Ticket'], axis = 1)

Начатая функция

In [18]:

#now we need to fill in the missing values in the Embarked feature
print("Number of people embarking in Southampton (S):")
southampton = train[train["Embarked"] == "S"].shape[0]
print(southampton)
print("Number of people embarking in Cherbourg (C):")
cherbourg = train[train["Embarked"] == "C"].shape[0]
print(cherbourg)
print("Number of people embarking in Queenstown (Q):")
queenstown = train[train["Embarked"] == "Q"].shape[0]
print(queenstown)
Number of people embarking in Southampton (S):
644
Number of people embarking in Cherbourg (C):
168
Number of people embarking in Queenstown (Q):
77
Number of people embarking in Southampton (S):
644
Number of people embarking in Cherbourg (C):
168
Number of people embarking in Queenstown (Q):
77

Понятно, что большинство людей отправились в Саутгемптоне (S). Давайте продолжим и заполним пропущенные значения буквой S.

In [20]:

#replacing the missing values in the Embarked feature with S
train = train.fillna({"Embarked": "S"})

Возраст

Далее мы заполним недостающие значения в функции «Возраст». Поскольку отсутствует более высокий процент значений, было бы нелогично заполнять их все одним и тем же значением (как мы сделали с Embarked). Вместо этого давайте попробуем найти способ предсказать пропущенный возраст.

In [22]:

#create a combined group of both datasets
combine = [train, test]
#extract a title for each Name in the train and test datasets
for dataset in combine:
    dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+)\.', expand=False)
pd.crosstab(train['Title'], train['Sex'])

Вышли[22]:

SexfemalemaleTitleCapt01Col02Countess10Don01Dr16Jonkheer01Lady10Major02Master040Miss1820Mlle20Mme10Mr0517Mrs1250Ms10Rev06Sir01

Вышли[22]:

SexfemalemaleTitleCapt01Col02Countess10Don01Dr16Jonkheer01Lady10Major02Master040Miss1820Mlle20Mme10Mr0517Mrs1250Ms10Rev06Sir01

In [23]:

#replace various titles with more common names
for dataset in combine:
    dataset['Title'] = dataset['Title'].replace(['Lady', 'Capt', 'Col',
    'Don', 'Dr', 'Major', 'Rev', 'Jonkheer', 'Dona'], 'Rare')
    
    dataset['Title'] = dataset['Title'].replace(['Countess', 'Lady', 'Sir'], 'Royal')
    dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
    dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
    dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
train[['Title', 'Survived']].groupby(['Title'], as_index=False).mean()

Вышли[23]:

ТитулВыжил0Мастер0,5750001Мисс0,7027032Мастер0,1566733Миссис0,7936514Редкий0,2857145Королевский1,000000

Вышли[23]:

ТитулВыжил0Мастер0,5750001Мисс0,7027032Мастер0,1566733Миссис0,7936514Редкий0,2857145Королевский1,000000

In [24]:

#map each of the title groups to a numerical value
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Royal": 5, "Rare": 6}
for dataset in combine:
    dataset['Title'] = dataset['Title'].map(title_mapping)
    dataset['Title'] = dataset['Title'].fillna(0)
train.head()

Вышли[24]:

PassengerIdSurvivedPclassNameSexAgeSibSpParchFareEmbarkedAgeGroupCabinBoolTitle0103Braund, Mr. Owen Harrismale22.0107.2500SStudent011211Cumings, Mrs. John Bradley (Florence Briggs Th…female38.01071.2833CAdult132313He ikkinen, Miss. Lainaженщина26.0007.9250SМолодой взрослый023411Futrelle, Mrs. Jacques Heath (Lily May Peel)женщина35.01053.1000SМолодой взрослый134503Allen, Mr. William Генримейл35.0008.0500SМолодой Взрослый01

Вышли[24]:

PassengerIdSurvivedPclassNameSexAgeSibSpParchFareEmbarkedAgeGroupCabinBoolTitle0103Braund, Mr. Owen Harrismale22.0107.2500SStudent011211Cumings, Mrs. John Bradley (Florence Briggs Th…female38.01071.2833CAdult132313He ikkinen, Miss. Lainaженщина26.0007.9250SМолодой взрослый023411Futrelle, Mrs. Jacques Heath (Lily May Peel)женщина35.01053.1000SМолодой взрослый134503Allen, Mr. William Генримейл35.0008.0500SМолодой Взрослый01

Код, который я использовал выше, исследован и получен от Kaggle и GitHub. Далее мы попытаемся предсказать отсутствующие значения возраста по наиболее распространенному возрасту для их титула.

In [25]:

# fill missing age with mode age group for each title
mr_age = train[train["Title"] == 1]["AgeGroup"].mode() #Young Adult
miss_age = train[train["Title"] == 2]["AgeGroup"].mode() #Student
mrs_age = train[train["Title"] == 3]["AgeGroup"].mode() #Adult
master_age = train[train["Title"] == 4]["AgeGroup"].mode() #Baby
royal_age = train[train["Title"] == 5]["AgeGroup"].mode() #Adult
rare_age = train[train["Title"] == 6]["AgeGroup"].mode() #Adult
age_title_mapping = {1: "Young Adult", 2: "Student", 3: "Adult", 4: "Baby", 5: "Adult", 6: "Adult"}
#I tried to get this code to work with using .map(), but couldn't.
#I've put down a less elegant, temporary solution for now.
#train = train.fillna({"Age": train["Title"].map(age_title_mapping)})
#test = test.fillna({"Age": test["Title"].map(age_title_mapping)})
for x in range(len(train["AgeGroup"])):
    if train["AgeGroup"][x] == "Unknown":
        train["AgeGroup"][x] = age_title_mapping[train["Title"][x]]
        
for x in range(len(test["AgeGroup"])):
    if test["AgeGroup"][x] == "Unknown":
        test["AgeGroup"][x] = age_title_mapping[test["Title"][x]]

Теперь, когда мы ввели пропущенные значения хотя бы несколько точно (я буду работать над лучшим способом прогнозирования отсутствующих значений возраста), пришло время сопоставить каждую возрастную группу с числовым значением.

In [26]:

#map each Age value to a numerical value
age_mapping = {'Baby': 1, 'Child': 2, 'Teenager': 3, 'Student': 4, 'Young Adult': 5, 'Adult': 6, 'Senior': 7}
train['AgeGroup'] = train['AgeGroup'].map(age_mapping)
test['AgeGroup'] = test['AgeGroup'].map(age_mapping)
train.head()
#dropping the Age feature for now, might change
train = train.drop(['Age'], axis = 1)
test = test.drop(['Age'], axis = 1)

Имя

Теперь, когда мы извлекли заголовки, мы можем отказаться от имени.

In [27]:

#drop the name feature since it contains no more useful information.
train = train.drop(['Name'], axis = 1)
test = test.drop(['Name'], axis = 1)

секс функция

In [28]:

#map each Sex value to a numerical value
sex_mapping = {"male": 0, "female": 1}
train['Sex'] = train['Sex'].map(sex_mapping)
test['Sex'] = test['Sex'].map(sex_mapping)
train.head()

Вышли[28]:

PassengerIdSurvivedPclassSexSibSpParchFareEmbarkedAgeGroupCabinBoolTitle01030107.2500S4.001121111071.2833C6.01323131007.9250S5.002341111053.1000S5.01345030008.0 500С5.001

Вышли[28]:

PassengerIdSurvivedPclassSexSibSpParchFareEmbarkedAgeGroupCabinBoolTitle01030107.2500S4.001121111071.2833C6.01323131007.9250S5.002341111053.1000S5.01345030008.0 500С5.001

Начатая функция

In [29]:

#map each Embarked value to a numerical value
embarked_mapping = {"S": 1, "C": 2, "Q": 3}
train['Embarked'] = train['Embarked'].map(embarked_mapping)
test['Embarked'] = test['Embarked'].map(embarked_mapping)
train.head()

Вышли[29]:

PassengerIdSurvivedPclassSexSibSpParchFareEmbarkedAgeGroupCabinBoolTitle01030107.250014.001121111071.283326.01323131007.925015.002341111053.100015.01345030008.0 50015.001

Вышли[29]:

PassengerIdSurvivedPclassSexSibSpParchFareEmbarkedAgeGroupCabinBoolTitle01030107.250014.001121111071.283326.01323131007.925015.002341111053.100015.01345030008.0 50015.001

Функция тарифа

Пришло время разделить значения тарифов на несколько логических групп, а также заполнить единственное отсутствующее значение в тестовом наборе данных.

In [30]:

#fill in missing Fare value in test set based on mean fare for that Pclass 
for x in range(len(test["Fare"])):
    if pd.isnull(test["Fare"][x]):
        pclass = test["Pclass"][x] #Pclass = 3
        test["Fare"][x] = round(train[train["Pclass"] == pclass]["Fare"].mean(), 4)
        
#map Fare values into groups of numerical values
train['FareBand'] = pd.qcut(train['Fare'], 4, labels = [1, 2, 3, 4])
test['FareBand'] = pd.qcut(test['Fare'], 4, labels = [1, 2, 3, 4])
#drop Fare values
train = train.drop(['Fare'], axis = 1)
test = test.drop(['Fare'], axis = 1)

In [31]:

#check train data
train.head()

Вышел[31]:

PassengerIdSurvivedPclassSexSibSpParchEmbarkedAgeGroupCabinBoolTitleFareBand010301014.0011121111026.0134231310015.0022341111015.0134450300015.0012

Вышел[31]:

PassengerIdSurvivedPclassSexSibSpParchEmbarkedAgeGroupCabinBoolTitleFareBand010301014.0011121111026.0134231310015.0022341111015.0134450300015.0012

In [32]:

#check test data
test.head()

Исход[32]:

PassengerIdPclassSexSibSpParchEmbarkedAgeGroupCabinBoolTitleFareBand0892300035.00111893311016.00312894200037.00123895300015.00124896311114.0032

Исход[32]:

PassengerIdPclassSexSibSpParchEmbarkedAgeGroupCabinBoolTitleFareBand0892300035.00111893311016.00312894200037.00123895300015.00124896311114.0032

6) Выбор лучшей модели

Разделение обучающих данных

Мы будем использовать часть наших обучающих данных (в данном случае 22%), чтобы проверить точность наших различных моделей.

In [33]:

from sklearn.model_selection import train_test_split
predictors = train.drop(['Survived', 'PassengerId'], axis=1)
target = train["Survived"]
x_train, x_val, y_train, y_val = train_test_split(predictors, target, test_size = 0.22, random_state = 0)

Тестирование различных моделей

Я буду тестировать следующие модели на своих обучающих данных (список взят отсюда):

  • Гауссовский наивный байесовский метод
  • Логистическая регрессия
  • Опорные векторные машины
  • Персептрон
  • Классификатор дерева решений
  • Случайный лесной классификатор
  • KNN или k-ближайшие соседи
  • Стохастический градиентный спуск
  • Классификатор повышения градиента

Для каждой модели мы устанавливаем модель, подгоняем ее под 80% наших обучающих данных, прогнозируем для 20% обучающих данных и проверяем точность.

In [34]:

# Gaussian Naive Bayes
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score
gaussian = GaussianNB()
gaussian.fit(x_train, y_train)
y_pred = gaussian.predict(x_val)
acc_gaussian = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_gaussian)
78.68
78.68

In [36]:

# Logistic Regression
from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression()
logreg.fit(x_train, y_train)
y_pred = logreg.predict(x_val)
acc_logreg = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_logreg)
79.7
79.7

In [37]:

# Support Vector Machines
from sklearn.svm import SVC
svc = SVC()
svc.fit(x_train, y_train)
y_pred = svc.predict(x_val)
acc_svc = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_svc)
82.74
82.74

In [38]:

# Linear SVC
from sklearn.svm import LinearSVC
linear_svc = LinearSVC()
linear_svc.fit(x_train, y_train)
y_pred = linear_svc.predict(x_val)
acc_linear_svc = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_linear_svc)
78.68
78.68

In [39]:

# Perceptron
from sklearn.linear_model import Perceptron
perceptron = Perceptron()
perceptron.fit(x_train, y_train)
y_pred = perceptron.predict(x_val)
acc_perceptron = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_perceptron)
78.68
78.68

In [40]:

#Decision Tree
from sklearn.tree import DecisionTreeClassifier
decisiontree = DecisionTreeClassifier()
decisiontree.fit(x_train, y_train)
y_pred = decisiontree.predict(x_val)
acc_decisiontree = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_decisiontree)
80.2
80.2

In [41]:

# Random Forest
from sklearn.ensemble import RandomForestClassifier
randomforest = RandomForestClassifier()
randomforest.fit(x_train, y_train)
y_pred = randomforest.predict(x_val)
acc_randomforest = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_randomforest)
83.76
83.76

In [42]:

# KNN or k-Nearest Neighbors
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier()
knn.fit(x_train, y_train)
y_pred = knn.predict(x_val)
acc_knn = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_knn)
77.66
77.66

In [43]:

# Stochastic Gradient Descent
from sklearn.linear_model import SGDClassifier
sgd = SGDClassifier()
sgd.fit(x_train, y_train)
y_pred = sgd.predict(x_val)
acc_sgd = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_sgd)
78.68
78.68

In [44]:

# Gradient Boosting Classifier
from sklearn.ensemble import GradientBoostingClassifier
gbk = GradientBoostingClassifier()
gbk.fit(x_train, y_train)
y_pred = gbk.predict(x_val)
acc_gbk = round(accuracy_score(y_pred, y_val) * 100, 2)
print(acc_gbk)
84.77
84.77

Давайте сравним точность каждой модели!

In [45]:

models = pd.DataFrame({
    'Model': ['Support Vector Machines', 'KNN', 'Logistic Regression', 
              'Random Forest', 'Naive Bayes', 'Perceptron', 'Linear SVC', 
              'Decision Tree', 'Stochastic Gradient Descent', 'Gradient Boosting Classifier'],
    'Score': [acc_svc, acc_knn, acc_logreg, 
              acc_randomforest, acc_gaussian, acc_perceptron,acc_linear_svc, acc_decisiontree,
              acc_sgd, acc_gbk]})
models.sort_values(by='Score', ascending=False)

Вышли[45]:

ModelScore9Классификатор с повышением градиента84,773Случайный лес83,760Машины опорных векторов82,747Дерево решений80,202Логистическая регрессия79,704Наивный байесовский метод78,685Перцептрон78,686Линейный SVC78,688Стохастический градиентный спуск78,681KNN77,66

Вышли[45]:

ModelScore9Классификатор с повышением градиента84,773Случайный лес83,760Машины опорных векторов82,747Дерево решений80,202Логистическая регрессия79,704Наивный байесовский метод78,685Перцептрон78,686Линейный SVC78,688Стохастический градиентный спуск78,681KNN77,66

Я решил использовать модель Gradient Boosting Classifier для данных тестирования.

7) Создание файла отправки

Пришло время создать файл submit.csv для загрузки на конкурс Kaggle!

In [46]:

#set ids as PassengerId and predict survival 
ids = test['PassengerId']
predictions = gbk.predict(test.drop('PassengerId', axis=1))
#set the output as a dataframe and convert to csv file named submission.csv
output = pd.DataFrame({ 'PassengerId' : ids, 'Survived': predictions })
output.to_csv('submission.csv', index=False)

Если вы зашли так далеко, поздравляем и спасибо за чтение!

Если вы используете какую-либо часть этой записной книжки в опубликованном ядре, мы будем очень признательны за упоминание (вы можете просто дать ссылку здесь). :)

Источники:

Любая обратная связь приветствуется!

In [ ]: