Исследовательский анализ данных и прогноз выживаемости с помощью алгоритма CatBoost.

Привет, энтузиаст науки о данных. В этом сообщении в блоге я расскажу, как Kaggle представил набор данных Titanic. Мы выполним EDA для титанического набора данных, используя некоторые часто используемые инструменты и методы в Python. А затем создайте несколько моделей машинного обучения, чтобы предсказать целевые функции. Хотите пересмотреть, что такое EDA? Вот моя статья Введение в EDA.

В одной из моих первоначальных статей Построение моделей линейной регрессии я объяснил, как моделировать и прогнозировать различные алгоритмы линейной регрессии. В этом случае набор данных, который я использовал, имел все функции в числовой форме. Но большая часть набора реальных данных содержит множество нечисловых характеристик. Мы должны преобразовать эти нечисловые характеристики в числовые значения. Та же проблема возникает в этом наборе данных Titanic, поэтому мы сделаем здесь несколько преобразований данных. Без дальнейших обсуждений, давайте сначала загрузим данные. Вот ссылка на набор данных Titanic от Kaggle.

Импортируйте все необходимые нам зависимости:

Вы можете получить некоторую ошибку, сообщив вам о некоторых библиотеках, которых у вас, возможно, нет. В таком случае вы должны установить его. Пока я выполнял эту задачу, вдохновленный статьей Дэниела Бурка, мне сначала пришлось установить missingo и catboost на свой ноутбук jupyter.

#import dependencies
%matplotlib inline
#start python imports
import math, time, random, datetime
#data manupilation
import numpy as np
import pandas as pd
#visualization
import matplotlib.pyplot as plt
import missingno
import seaborn as sns
plt.style.use('seaborn-whitegrid')
# preprocessing
from sklearn.preprocessing import OneHotEncoder,LabelEncoder, label_binarize
#Machine Learning
import catboost
from sklearn.model_selection import train_test_split
from sklearn import model_selection, tree, preprocessing, metrics, linear_model
from sklearn.svm import LinearSVC
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LinearRegression, LogisticRegression, SGDClassifier
from catboost import CatBoostClassifier, Pool, cv
#ignore warnings for now
import warnings
warnings.filterwarnings('ignore')

Загрузка набора данных:

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

# Import train and test data
train= pd.read_csv('data/train.csv')
test=pd.read_csv('data/test.csv')
gender_submission=pd.read_csv('data/gender_submission.csv') # example of what a submission should look like

Просмотрите первые 15 строк в наборе данных поезда.

# view the tranning data
train.head(15)

Посмотрим количество пассажиров в разных возрастных группах.

train.Age.plot.hist()

Просмотрите первые 5 строк в тестовом наборе данных.

#view the test data same as train data 
test.head()

Теперь первые 5 строк набора данных gender_submission. Это пример фрейма данных для нашего окончательного фрейма данных.

#view the example submission dataframe
gender_submission.head()

Описание данных:

Вы должны были прочитать описание данных при загрузке набора данных из Kaggle. Если нет, то вот что представляет каждая функция.

Выживание: 0 = нет, 1 = да

pclass (класс билета): 1 = 1-й, 2 = 2-й, 3 = 3-й

пол: Секс

Возраст: Возраст в годах

sibsp: количество братьев и сестер / супругов на борту Титаника

parch: количество родителей / детей на борту Титаника.

билет: Номер билета

тариф: Пассажирский тариф

каюта: Номер каюты

Посадка: порт посадки, C = Шербур, Q = Квинстаун, S = Саутгемптон

Я настоятельно рекомендую вам зайти на сайт Kaggle и внимательно прочитать описание набора данных. Понимание данных необходимо перед обработкой и анализом.

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

#data discription
train.describe()

Проверить недостающие значения:

Прежде чем проводить какой-либо анализ, давайте проверим, есть ли у нас какие-либо пропущенные значения.

# plot graphic of missing values
missingno.matrix(train, figsize=(30,10))

Здесь вы можете ясно увидеть некоторые недостающие значения. Столбец "Кабина" имеет наибольшее количество пропущенных значений. Кроме того, в столбцах "Возраст" довольно много пропущенных значений.
Важно заранее визуализировать недостающие значения, чтобы вы знали, где в вашем наборе данных находятся основные дыры. И тогда вы можете решить, какие очистка и предварительная обработка данных лучше подходят для заполнения этих дыр.

Вот альтернативный способ поиска пропущенных значений.

# alternatively you can see the number of missing values like this
train.isnull().sum()

Похоже, что у нас мало данных в поле Embarked и много в поле Age and Cabin. Мы выясним, какой метод вменения данных для этих функций будет наилучшим.
Чтобы выполнить анализ данных, давайте создадим новые фреймы данных. Мы добавим столбец функций в этот фрейм данных, поскольку сделаем эти столбцы применимыми для последующего моделирования.

df_new =pd.DataFrame()

Сначала давайте посмотрим, каковы разные типы данных разных столбцов в наборе данных нашего поезда.

# different data types in the dataset
train.dtypes

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

Изучите каждую из этих функций по отдельности:

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

train.head()

Целевая особенность: выжил

Описание: выжил пассажир или нет.

Ключ: 0 = не выжил, 1 = выжил

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

# how many people survived?
fig = plt.figure(figsize=(20,1))
sns.countplot(y='Survived', data=train);
print(train.Survived.value_counts())

Давайте добавим это в наш новый фрейм данных подмножества df_new.

df_new['Survived'] = train['Survived']
df_new.head()

Особенность: Pclass

Описание: Класс билета пассажира.

Ключ: 1 = 1-й, 2 = 2-й, 3 = 3-й

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

# Let's plot the distribution of Pclass
sns.distplot(train.Pclass)

Похоже, для каждого существующего значения существует 1,2 или 3 класса Pclass. Этот столбец функций выглядит числовым, но на самом деле он категориальный. Каждое значение в этой функции относится к типу Pclass, и ни одно из них не представляет собой числовую оценку. Здесь Pclass 3 имеет самую высокую частоту. Теперь посмотрим, не пропущено ли у этой функции какое-либо значение.

# How many missing variables does Pclass have?
train.Pclass.isnull().sum()

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

df_new['Pclass']= train['Pclass']

Особенность: Имя

Описание: Имя пассажира.

Сначала давайте узнаем, сколько существует разных имен?

train.Name.value_counts()

Здесь длина train.Name.value_counts () равна 891, что совпадает с количеством строк. Таким образом, кажется, что каждая строка имеет уникальное имя. Это затрудняет поиск какой-либо закономерности в имени человека, выжившего. Давайте не будем включать это название функции в новый фрейм данных подмножества.

Особенность: Секс

Давайте посмотрим на распределение по полу.

plt.figure(figsize=(20, 5))
sns.countplot(y="Sex", data=train);

Есть ли пропущенные значения в столбце «Пол»?

train.Sex.isnull().sum()

Эта строка кода выше возвращает 0. Итак, давайте добавим эту функцию двоичной переменной в новый фрейм данных подмножества.

# add Sex to the subset dataframe
df_new['Sex'] = train['Sex']
# first five row of df_new
df_new.head()

давайте закодируем переменную пола с помощью кодировщика меток, чтобы преобразовать эту категориальную переменную в числовую.

df_new['Sex']=LabelEncoder().fit_transform(df_new['Sex'])
df_new.head()

Как выглядит переменная «Пол» по сравнению с «Выживанием»? Мы можем это видеть, потому что оба они бинарные.

fig = plt.figure(figsize=(8,8))
sns.distplot(df_new.loc[df_new['Survived'] == 1]['Sex'], kde_kws={'bw': 0.1,"label": "Survived"});
sns.distplot(df_new.loc[df_new['Survived'] == 0]['Sex'], kde_kws={'bw': 0.1,"label": "Did not Survived"});

Особенность: Возраст

Мы уже видели, что в столбце «Возраст» много пропущенных значений. Давай еще раз посмотрим на это число.

train.Age.isnull().sum()

Эта строка кода выше возвращает 177, что составляет почти четверть набора данных.

Что бы вы сделали с этими недостающими значениями? Могли бы их заменить на средний возраст? Каковы плюсы и минусы этого?
Или вы бы полностью избавились от них?
Мы не ответим на эти вопросы в нашем первоначальном EDA, но это то, к чему мы вернемся позже. А пока давайте пропустим эту функцию.

Функция для создания визуализаций подсчета и распределения

def plot_count_dist(data, label_column, target_column, figsize=(20, 5)):
    fig = plt.figure(figsize=figsize)
    plt.subplot(1, 2, 1)
    sns.countplot(y=target_column, data=data);
    plt.subplot(1, 2, 2)
    sns.distplot(data.loc[data[label_column] == 1][target_column], 
                     kde_kws={'bw': 0.2,"label": "Survived"});
    sns.distplot(data.loc[data[label_column] == 0][target_column], 
                     kde_kws={'bw': 0.2,"label": "Did not survive"});

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

Описание: Количество братьев и сестер / супругов у пассажира на борту Титаника.

Сколько пропущенных значений у SibSp?

train.SibSp.isnull().sum()

Эта строка кода выше возвращает 0. Давайте посмотрим количество уникальных значений в этом столбце и их распределение.

train.SibSp.value_counts()

# Visualise the counts of SibSp and the distribution of SibSp #against Survival
plot_count_dist(train,label_column='Survived',target_column='SibSp', figsize=(20,10))

Давайте добавим функцию SibSp в наш новый фрейм данных подмножества.

#Add SibSp to new dataframe
df_new['SibSp'] = train['SibSp']

Фасон сиденья: Перчин

Описание: Количество родителей / детей у пассажира на борту Титаника.

Поскольку эта функция аналогична SibSp, мы проведем аналогичный анализ.

Сколько пропущенных значений у Парча?

train.Parch.isnull().sum()

Эта строка кода выше возвращает 0. Давайте посмотрим количество уникальных значений в этом столбце и их распределение.

train.SibSp.value_counts()

#Visualize the counts of Parch and distribution of values against #Survival
plot_count_dist(train,label_column='Survived',target_column='Parch',figsize=(20,10))

Особенность: Билет

Описание: Номер билета посадочного пассажира.

Сколько пропущенных значений у билетов?

train.Ticket.isnull().sum()

Эта строка кода выше возвращает 0. Давайте посмотрим на количество уникальных значений в этом столбце.

train.Ticket.value_counts()

Здесь длина train.Ticket.value_counts () равна 681, что на данный момент слишком много уникальных значений. Не будем включать эту функцию в новый фрейм данных подмножества.

Особенность: тариф

Описание: Сколько стоит билет.

Сколько пропущенных значений у Fare? Что это за переменная?

train.Fare.isnull().sum()
train.Fare.dtype

Строки кода выше возвращают 0 пропущенных значений и тип данных «float64». давайте посмотрим, сколько существует видов стоимости проезда?

train.Fare.value_counts()

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

df_new['Fare']= train['Fare']

Особенность: Кабина

Описание: Номер каюты, в которой остановился пассажир.

Сколько пропущенных значений в Cabin?

train.Cabin.isnull().sum()

Приведенный выше код возвращает 687. похоже, что в функции Cabin пропущено 1/3 числа. Поэтому, пока у нас не будет совета эксперта, мы не заполняем недостающие значения, а не используем его для модели прямо сейчас. Перейдем к следующей функции.

Особенность: встал

Описание: Порт, в котором пассажир сел на Титаник.

Обозначения: C = Шербур, Q = Квинстаун, S = Саутгемптон.

Сколько пропущенных значений у Embarked?

train.Embarked.isnull().sum()

В столбце Embarked 2 пропущенных значения. Посмотрим, какие ценности есть в Embarked.

train.Embarked.value_counts()

Похоже, что Embarked является категориальной переменной и имеет три категориальных варианта. Посчитаем и сюжет.

sns.countplot(y='Embarked', data=train);

Есть несколько способов справиться с пропущенными значениями. Поскольку из 891 пропущено только 2 значения, что очень мало, давайте уменьшим эти две строки с пропущенным значением. Но сначала добавьте этот исходный столбец во фрейм данных подмножества.

# Add Embarked to new data frame
df_new['Embarked'] = train['Embarked']
# Remove Embarked rows which are missing values
print(len(df_new))
df_new = df_new.dropna(subset=['Embarked'])
print(len(df_new))

Приведенный выше блок кода вернет 891 перед удалением строк и 889 после.

Кодировка функции:

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

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

Давайте посмотрим на исходный фрейм данных df_new.

df_new.head()

# One hot encode the categorical columns
df_embarked_one_hot = pd.get_dummies(df_new['Embarked'], 
                                     prefix='embarked')
df_sex_one_hot = pd.get_dummies(df_new['Sex'], 
                                prefix='sex')
df_plcass_one_hot = pd.get_dummies(df_new['Pclass'], 
                                   prefix='pclass')

Теперь объедините столбцы one_hot с «df_new».

# Combine the one hot encoded columns with df_con_enc
df_new_enc = pd.concat([df_new, 
                        df_embarked_one_hot, 
                        df_sex_one_hot, 
                        df_plcass_one_hot], axis=1)
# Drop the original categorical columns (because now they've been one hot encoded)
df_new_enc = df_new_enc.drop(['Pclass', 'Sex', 'Embarked'], axis=1)

Давайте посмотрим на "df_new_enc".

df_new_enc.head(10)

Начать создание моделей машинного обучения:

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

Выберем данные

# Seclect the dataframe we want to use for predictions
selected_df = df_new_enc
selected_df.head()

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

# Split the dataframe into data and labels
X_train = selected_df.drop('Survived', axis=1) # data
y_train = selected_df.Survived # labels

Определите функцию, подходящую для алгоритмов машинного обучения:

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

# Function that runs the requested algorithm and returns the accuracy metrics
def fit_ml_algo(algo, X_train, y_train, cv):
    
    # One Pass
    model = algo.fit(X_train, y_train)
    acc = round(model.score(X_train, y_train) * 100, 2)
    
    # Cross Validation 
    train_pred = model_selection.cross_val_predict(algo, 
                                                  X_train, 
                                                  y_train, 
                                                  cv=cv, 
                                                  n_jobs = -1)
    # Cross-validation accuracy metric
    acc_cv = round(metrics.accuracy_score(y_train, train_pred) * 100, 2)
    
    return train_pred, acc, acc_cv

В приведенной выше функции мы получаем как точность обучения, так и точность перекрестной проверки как «acc» и «acc_cv». Перекрестная проверка - мощная профилактическая мера против переобучения. Поэтому мы рассмотрим ошибку перекрестной проверки при доработке алгоритма прогнозирования выживаемости.

Логистическая регрессия

# Logistic Regression
start_time = time.time()
train_pred_log, acc_log, acc_cv_log = fit_ml_algo(LogisticRegression(), 
                                                               X_train, 
                                                               y_train, 
                                                                    10)
log_time = (time.time() - start_time)
print("Accuracy: %s" % acc_log)
print("Accuracy CV 10-Fold: %s" % acc_cv_log)
print("Running Time: %s" % datetime.timedelta(seconds=log_time))

Выход:

Accuracy: 79.98
Accuracy CV 10-Fold: 79.42
Running Time: 0:00:43.517223

K-ближайшие соседи

# k-Nearest Neighbours
start_time = time.time()
train_pred_knn, acc_knn, acc_cv_knn = fit_ml_algo(KNeighborsClassifier(), 
                                                  X_train, 
                                                  y_train, 
                                                  10)
knn_time = (time.time() - start_time)
print("Accuracy: %s" % acc_knn)
print("Accuracy CV 10-Fold: %s" % acc_cv_knn)
print("Running Time: %s" % datetime.timedelta(seconds=knn_time))

Выход:

Accuracy: 83.46
Accuracy CV 10-Fold: 76.72
Running Time: 0:00:02.552968

Наивный Байес по Гауссу

# Gaussian Naive Bayes
start_time = time.time()
train_pred_gaussian, acc_gaussian, acc_cv_gaussian = fit_ml_algo(GaussianNB(), 
                                                                      X_train, 
                                                                      y_train, 
                                                                           10)
gaussian_time = (time.time() - start_time)
print("Accuracy: %s" % acc_gaussian)
print("Accuracy CV 10-Fold: %s" % acc_cv_gaussian)
print("Running Time: %s" % datetime.timedelta(seconds=gaussian_time))

Выход:

Accuracy: 78.52
Accuracy CV 10-Fold: 77.95
Running Time: 0:00:00.197989

Машины линейных опорных векторов (SVC)

# Linear SVC
start_time = time.time()
train_pred_svc, acc_linear_svc, acc_cv_linear_svc = fit_ml_algo(LinearSVC(),
                                                                X_train, 
                                                                y_train, 
                                                                10)
linear_svc_time = (time.time() - start_time)
print("Accuracy: %s" % acc_linear_svc)
print("Accuracy CV 10-Fold: %s" % acc_cv_linear_svc)
print("Running Time: %s" % datetime.timedelta(seconds=linear_svc_time))

Выход:

Accuracy: 75.93
Accuracy CV 10-Fold: 78.4
Running Time: 0:00:01.417908

Стохастический градиентный спуск

# Stochastic Gradient Descent
start_time = time.time()
train_pred_sgd, acc_sgd, acc_cv_sgd = fit_ml_algo(SGDClassifier(), 
                                                  X_train, 
                                                  y_train,
                                                  10)
sgd_time = (time.time() - start_time)
print("Accuracy: %s" % acc_sgd)
print("Accuracy CV 10-Fold: %s" % acc_cv_sgd)
print("Running Time: %s" % datetime.timedelta(seconds=sgd_time))

Выход:

Accuracy: 78.18
Accuracy CV 10-Fold: 67.72
Running Time: 0:00:00.485966

Классификатор дерева решений

# Decision Tree Classifier
start_time = time.time()
train_pred_dt, acc_dt, acc_cv_dt = fit_ml_algo(tree.DecisionTreeClassifier(), 
                                                                X_train, 
                                                                y_train,
                                                                10)
dt_time = (time.time() - start_time)
print("Accuracy: %s" % acc_dt)
print("Accuracy CV 10-Fold: %s" % acc_cv_dt)
print("Running Time: %s" % datetime.timedelta(seconds=dt_time))

Выход:

Accuracy: 92.46
Accuracy CV 10-Fold: 80.65
Running Time: 0:00:01.056698

Деревья усиления градиента

# Gradient Boosting Trees
start_time = time.time()
train_pred_gbt, acc_gbt, acc_cv_gbt = fit_ml_algo(GradientBoostingClassifier(), 
                                                                       X_train, 
                                                                       y_train,
                                                                       10)
gbt_time = (time.time() - start_time)
print("Accuracy: %s" % acc_gbt)
print("Accuracy CV 10-Fold: %s" % acc_cv_gbt)
print("Running Time: %s" % datetime.timedelta(seconds=gbt_time))

Выход:

Accuracy: 86.61
Accuracy CV 10-Fold: 80.65
Running Time: 0:00:02.261205

Алгоритм CatBoost

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

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

Анна Вероника Дорогуш, руководитель тимбилдинга библиотеки CatBoost, предлагает не выполнять одно горячее кодирование явно для категориальных столбцов перед ее использованием, потому что алгоритм автоматически выполнит требуемое кодирование для категориальных функций.
В моей записной книжке jupyter это сообщение в блоге, я также использовал CatBoost для набора данных перед одним горячим кодированием. И вы можете увидеть разницу в точности. В этом случае разница в точности перекрестной проверки составила 0,22, поэтому я буду использовать тот же кодированный фрейм данных, который я использовал для более ранних моделей на данный момент.

# View the data for the CatBoost model
X_train.head()

# View the labels for the CatBoost model
y_train.head()

# Define the categorical features for the CatBoost model
cat_features = np.where(X_train.dtypes != np.float)[0]
cat_features

Выход:

array([ 0,  1,  3,  4,  5,  6,  7,  8,  9, 10], dtype=int64)

Это означает, что Catboost понял, что все переменные, кроме Fare, можно рассматривать как категориальные.

# Use the CatBoost Pool() function to pool together the training data and categorical feature labels
train_pool = Pool(X_train, 
                  y_train,
                  cat_features)

Ранее мы импортировали CatBoostClassifier, Pool, cv из catboost. Здесь функция Pool () объединяет обучающие данные и категориальные метки функций. Теперь давайте поместим алгоритм CatBoostClassifier () в train_pool и построим график обучения.

# CatBoost model definition
catboost_model = CatBoostClassifier(iterations=1000,
                                    custom_loss=['Accuracy'],
                                    loss_function='Logloss')
# Fit CatBoost model
catboost_model.fit(train_pool,
                   plot=True)
# CatBoost accuracy
acc_catboost = round(catboost_model.score(X_train, y_train) * 100, 2)

На обучение этой модели в моем блокноте jupyter у меня ушло больше часа, а в лаборатории Google - всего 53 секунды. Для обучения модели кросс-валидации снова потребовалось больше часа, а в лаборатории Google - всего 6 минут 18 секунд.

Затем выполните перекрестную проверку CatBoost.

Мы провели кроссвиладу в каждой из вышеперечисленных моделей. Так что теперь давайте займемся CatBoost.

# How long will this take?
start_time = time.time()
# Set params for cross-validation as same as initial model
cv_params = catboost_model.get_params()
# Run the cross-validation for 10-folds (same as the other models)
cv_data = cv(train_pool,
             cv_params,
             fold_count=10,
             plot=True)
# How long did it take?
catboost_time = (time.time() - start_time)
# CatBoost CV results save into a dataframe (cv_data), let's withdraw the maximum accuracy score
acc_cv_catboost = round(np.max(cv_data['test-Accuracy-mean']) * 100, 2)

А затем распечатайте метрики модели CatBoost.

# Print out the CatBoost model metrics
print("---CatBoost Metrics---")
print("Accuracy: {}".format(acc_catboost))
print("Accuracy cross-validation 10-Fold: {}".format(acc_cv_catboost))
print("Running Time: {}".format(datetime.timedelta(seconds=catboost_time)))

Выход:

---CatBoost Metrics---
Accuracy: 83.91
Accuracy cross-validation 10-Fold: 81.32
Running Time: 1:06:01.208055

Результаты модели:

Какая модель имела лучшую точность перекрестной проверки?

Примечание. Мы больше всего заботимся о показателях перекрестной проверки, потому что показатели, которые мы получаем из .fit (), могут случайным образом иметь более высокий балл, чем обычно.

Обычные показатели точности

models = pd.DataFrame({
    'Model': ['KNN', 'Logistic Regression', 'Naive Bayes', 
              'Stochastic Gradient Decent', 'Linear SVC', 
              'Decision Tree', 'Gradient Boosting Trees',
              'CatBoost'],
    'Score': [
        acc_knn, 
        acc_log,  
        acc_gaussian, 
        acc_sgd, 
        acc_linear_svc, 
        acc_dt,
        acc_gbt,
        acc_catboost
    ]})
print("---Reuglar Accuracy Scores---")
models.sort_values(by='Score', ascending=False)

Выход:

Показатели точности перекрестной проверки

cv_models = pd.DataFrame({
    'Model': ['KNN', 'Logistic Regression', 'Naive Bayes', 
              'Stochastic Gradient Decent', 'Linear SVC', 
              'Decision Tree', 'Gradient Boosting Trees',
              'CatBoost'],
    'Score': [
        acc_cv_knn, 
        acc_cv_log,      
        acc_cv_gaussian, 
        acc_cv_sgd, 
        acc_cv_linear_svc, 
        acc_cv_dt,
        acc_cv_gbt,
        acc_cv_catboost
    ]})
print('---Cross-validation Accuracy Scores---')
cv_models.sort_values(by='Score', ascending=False)

Выход:

Как видно из таблиц, модель CatBoost показала наилучшие результаты. Получение чуть менее 82% - это неплохо, учитывая, что угадывание приведет к точности около 50% (0 или 1).

Мы уделим больше внимания показателю перекрестной проверки.

Перекрестная проверка более надежна, чем просто модели .fit (), поскольку она выполняет несколько проходов по данным вместо одного.

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

Подчинение

Итак, мы используем модель CatBoost, чтобы сделать прогноз на основе тестового набора данных, а затем отправить наши прогнозы в Kaggle.

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

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

# We need our test dataframe to look like this one
X_train.head()

# Our test dataframe has some columns our model hasn't been trained on
test.head()

Давайте сделаем одно горячее кодирование в соответствующих функциях.

test_embarked_one_hot = pd.get_dummies(test['Embarked'], 
                                       prefix='embarked')
test_sex_one_hot = pd.get_dummies(test['Sex'], 
                                prefix='sex')
test_plcass_one_hot = pd.get_dummies(test['Pclass'], 
                                   prefix='pclass')

Затем объедините тестовые столбцы с горячим кодированием с тестом.

test = pd.concat([test, 
                  test_embarked_one_hot, 
                  test_sex_one_hot, 
                  test_plcass_one_hot], axis=1)
# Let's look at test, it should have one hot encoded columns now
test.head()

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

test.columns

Выход:

Index(['PassengerId', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp', 'Parch','Ticket', 'Fare', 'Cabin', 'Embarked', 'embarked_C', 'embarked_Q','embarked_S', 'sex_female', 'sex_male', 'pclass_1', 'pclass_2','pclass_3'],dtype='object')

Столбцы в X_train:

X_train.columns

Выход:

Index(['SibSp', 'Parch', 'Fare', 'embarked_C', 'embarked_Q', 'embarked_S','sex_0', 'sex_1', 'pclass_1', 'pclass_2', 'pclass_3'],
 dtype='object')

Вы можете видеть, что имена новых столбцов для пустышек столбцов пола отличаются. давайте переименуем "test.columns" в название.

test.rename(columns={"sex_female": "sex_0", "sex_male": "sex_1"},inplace=True)

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

# Create a list of columns to be used for the predictions
wanted_test_columns = X_train.columns
wanted_test_columns

Выход:

Index(['SibSp', 'Parch', 'Fare', 'embarked_C', 'embarked_Q', 'embarked_S','sex_0', 'sex_1', 'pclass_1', 'pclass_2', 'pclass_3'],
dtype='object')

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

predictions = catboost_model.predict(test[wanted_test_columns])
# Our predictions array is comprised of 0's and 1's (Survived or Did Not Survive)
predictions[:20]

Выход:

array([0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1])

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

# Create a submisison dataframe and append the relevant columns
submission = pd.DataFrame()
submission['PassengerId'] = test['PassengerId']
submission['Survived'] = predictions # our model predictions on the test dataset
submission.head()

# What does our submission have to look like?
gender_submission.head()

if len(submission) == len(test):
    print("Submission dataframe is the same length as test ({} rows).".format(len(submission)))
else:
    print("Dataframes mismatched, won't be able to submit to Kaggle.")

Выход:

Submission dataframe is the same length as test (418 rows).

Преобразуйте фрейм данных отправки в csv для отправки в csv для отправки Kaggle.

submission.to_csv('../catboost_submission.csv', index=False)
print('Submission CSV is ready!')

Выход:

Submission CSV is ready!

Вы уже должны быть авторизованы на Kaggle.com. Для подачи заявки перейдите на страницу Титаник: Машинное обучение от катастрофы и перейдите на вкладку Мои материалы.

Нажмите «Отправить прогноз», загрузите файл submission.csv и напишите несколько слов о своей отправке.
Подождите несколько секунд, и вы увидите общедоступную оценку своего прогноза.

Поздравляю! Вы сделали это.

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

Учить больше

Классификационная тетрадь Sklearn, Даниэль Фурассо

Кодирование категориальных функций в сообщении блога Python от Practical Python Business

Учебник CatBoost Python на GitHub

использованная литература

Практический исследовательский анализ данных с использованием Python, Суреш Кумар Мухия, Усман Ахмед, 2020, Публикация PACKT

Твое-первое-тупое-подчинение »Даниэля Бурка

Учебники по CatBoost

Спасибо, что разместили это сообщение в блоге. Предлагаю вам взглянуть на мою записную книжку jupyter в этом репозитории github. Здесь я проделал еще немного работы по анализу важности функций.

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

Продолжайте учиться.

[email protected]