В этой записной книжке мы рассмотрим предварительные процессы создания высокопроизводительной модели, чтобы предсказать, выжил ли пассажир на Титанике, на основе личной информации, такой как цена билета, возраст и пол. В этом блокноте показано, как:

  1. Выполнение исследовательского анализа данных
  2. Попробуйте следующие различные архитектуры моделей и интерпретируйте их производительность:
    - Наивный байесовский метод
    - Сеть прямого распространения
    - Дерево решений
    - Ближайшие соседи

Мы используем набор данных от Kaggle (находится здесь https://www.kaggle.com/competitions/titanic/data). У нас есть данные, хранящиеся локально в этом репозитории.

Изучение данных

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

Некоторые основные вещи, которые мы будем искать, включают:

  • Наблюдение за категориальными признаками возможных значений
  • Убедитесь, что значения данных имеют смысл (например, Age — это положительное целое/число с плавающей запятой, которое не является безумно высоким, родственное число SibSp — это неотрицательное целое число, которое не является безумно высоким и т. д.)
  • Проверка на отсутствие записей

Некоторые более подробные вещи, которые мы рассмотрим, это

  • Распределения каждой функции
  • Корреляции между функциями

Быстрый просмотр

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

Давайте также искать недостающие данные

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

Построение распределения признаков

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

  • у мужчин гораздо меньше шансов выжить

P(выжившие|пол = мужчины) = 18,9%
P(выжившие|пол = женщины) = 74,2%
P(женщины|выжившие) = 68,1%
P(мужчины|выжившие) = 31,9%

  • пассажиры в возрасте 20–30 лет имеют самые низкие показатели выживаемости, в то время как пассажиры в возрасте до 10 лет имеют самые высокие показатели выживаемости.
  • пассажиры с низкими тарифами на билеты и низким социальным классом имеют значительно более низкие показатели выживаемости.
  • Пассажиры, которые отправились из Саутгемптона (S), имели значительно более низкие показатели выживаемости, в то время как пассажиры, которые отправились из Шербура ©, имели самый высокий уровень выживаемости.

Эти данные указывают на то, что «Титаник» сначала следовал процедуре эвакуации женщин и детей, а затем — ценных пассажиров.

P(survived|sex = male) = 18.9%
P(survived|sex = female) = 74.2%
P(female|survived) = 68.1%
P(male|survived) = 31.9%

Давайте также построим корреляцию выживания для каждого из числовых признаков. Здесь мы видим:

  • Сильная корреляция класса и стоимости проезда с выживаемостью.
  • Корреляция количества родителей на борту и возраста с выживаемостью.

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

  • Самая высокая выживаемость мужчин была среди детей.
  • Коэффициент выживаемости положительно коррелирует с социальным классом и стоимостью проезда.

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

Установление базовых показателей

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

  1. Наивная байесовская оценка
  2. Сеть прямого распространения
  3. Древо решений
  4. Ближайшие соседи

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

Наивная байесовская оценка

Мы увидим, как наивный байесовский алгоритм работает, когда мы делаем следующее:

  1. Посмотрите только на функцию Sex в нашей наивной байесовской оценке.
  2. Используйте все функции в нашей оценке

Наивная оценка секса

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

Naive Sex Accuracy = 78.68%

Предварительная обработка данных

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

  1. Обычно кодируют пол и встали локации.
  2. Разбейте тарифы и возрасты на порядковые векторы.

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

Сначала заполняем недостающие данные. Мы заполним пропущенные возрасты средним возрастом, а пропущенные места посадки — наиболее распространенным местом посадки «S».

Теперь мы создаем наши массивы numpy, с которыми мы будем работать. Мы начинаем только со столбцов SibSp, Parch и Pclass, так как они не изменятся при нашей предварительной обработке.

Теперь мы добавляем encode и каждый из закодированных столбцов в наш массив X.

['male' 'S'] encoded as [1. 2.]
['female' 'C'] encoded as [0. 0.]
['female' 'S'] encoded as [0. 2.]
['female' 'S'] encoded as [0. 2.]
['male' 'S'] encoded as [1. 2.]
bin edges for age = [0.42, 18.0, 24.0, 29.0, 29.69911764705882, 33.0, 43.0, 80.0]
bin edges for fare = [0.0, 7.75, 8.05, 12.475, 19.2583, 27.9, 56.9292, 512.3292]
[22.    7.25] encoded as [1. 0.]
[38.     71.2833] encoded as [5. 6.]
[26.     7.925] encoded as [2. 1.]
[35.  53.1] encoded as [5. 5.]
[35.    8.05] encoded as [5. 2.]

Наивный байесовский анализ данных

Мы будем использовать scikit-learns реализацию наивного Байеса.

from sklearn.naive_bayes import CategoricalNB
nb = CategoricalNB()
0.7631874298540965

На самом деле мы получаем более низкую точность, чем наивная оценка пола. Вероятно, это можно объяснить высокой корреляцией между некоторыми функциями, такими как:

  1. Социальный класс и стоимость проезда.
  2. Количество братьев и сестер и количество родителей на лодке.

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

Сеть прямого распространения

Теперь давайте попробуем простую сеть прямой связи. Мы сделаем следующее:

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

Мы будем использовать keras для реализации этой модели.

Предварительная обработка данных

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

  1. Горячее кодирование вставших локаций.
  2. Один горячий кодирует социальный класс.
  3. Обычно кодируют пол.
  4. Объедините века в один горячий вектор.

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

Сначала мы создаем наши массивы numpy, с которыми мы будем работать. Мы начинаем только со столбца Fare, так как он не изменится в нашей предварительной обработке.

Теперь мы добавляем encode и каждый из закодированных столбцов в наш массив X.

[3 'S'] encoded as [0. 0. 1. 0. 0. 1.]
[1 'C'] encoded as [1. 0. 0. 1. 0. 0.]
[3 'S'] encoded as [0. 0. 1. 0. 0. 1.]
[1 'S'] encoded as [1. 0. 0. 0. 0. 1.]
[3 'S'] encoded as [0. 0. 1. 0. 0. 1.]
['male'] encoded as [1.]
['female'] encoded as [0.]
['female'] encoded as [0.]
['female'] encoded as [0.]
['male'] encoded as [1.]
bin edges = [0.42, 18.0, 24.0, 29.0, 29.69911764705882, 33.0, 43.0, 80.0]
[22.] encoded as [0. 1. 0. 0. 0. 0. 0.]
[38.] encoded as [0. 0. 0. 0. 0. 1. 0.]
[26.] encoded as [0. 0. 1. 0. 0. 0. 0.]
[35.] encoded as [0. 0. 0. 0. 0. 1. 0.]
[35.] encoded as [0. 0. 0. 0. 0. 1. 0.]

Определение архитектуры модели

Мы будем использовать keras для реализации этой модели.

Мы строим кривую потерь, чтобы убедиться, что модель закончила обучение:

С помощью этого наивного персептрона мы достигаем точности около 81 % тестовых данных — ненамного лучше, чем наивная гендерная оценка.

Perceptron accuracy = 79.91%

Поиск гиперпараметров

Теперь мы выполняем поиск гиперпараметров для оптимальной одноуровневой сети с прямой связью, используя 4-кратную перекрестную проверку. Мы выполним поиск по сетке:

  1. Скорость обучения.
  2. Количество узлов в скрытом слое.

Мы будем использовать реализацию KFold от scikit-learn для разделения данных для перекрестной проверки.

from sklearn.model_selection import KFold

Здесь мы завершаем процесс проверки kfold следующей функцией.

Теперь мы выполняем поиск по сетке по скорости обучения и количеству узлов в скрытом слое (в коде он называется dense_layer).

running lr = 0.0001, dense_layer = 30
running lr = 0.0001, dense_layer = 40
running lr = 0.0001, dense_layer = 50
running lr = 0.0001, dense_layer = 60
running lr = 0.0005, dense_layer = 30
running lr = 0.0005, dense_layer = 40
running lr = 0.0005, dense_layer = 50
running lr = 0.0005, dense_layer = 60
running lr = 0.001, dense_layer = 30
running lr = 0.001, dense_layer = 40
running lr = 0.001, dense_layer = 50
running lr = 0.001, dense_layer = 60
running lr = 0.003, dense_layer = 30
running lr = 0.003, dense_layer = 40
running lr = 0.003, dense_layer = 50
running lr = 0.003, dense_layer = 60

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

Теперь мы печатаем наши лучшие результаты. Обратите внимание на следующее:

  1. Мы не сильно улучшили точность проверки выше 81%.
  2. Увеличение количества узлов (сложности модели) выше 50, похоже, не улучшило производительность модели. Это указывает на то, что добавление слоев или другой сложности модели может быть не очень продуктивным занятием.
best validation accuracy 81.04% achieved with hyperparameters (('lr', 0.003), ('dense_layer', 30))

Деревья решений

Теперь попробуем использовать модель дерева решений. Мы выполним поиск гиперпараметров по глубине дерева. Мы будем использовать реализацию scikit-learn деревьев решений и перекрестной проверки.

Предварительная обработка данных

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

Поиск по глубине дерева

Теперь мы выполняем поиск гиперпараметров по глубине дерева и 4-кратную перекрестную проверку.

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

best accuracy = 0.8170625782733406

Ближайший сосед

Мы будем использовать scikit для изучения реализации KNeighborsClassifier. Мы выполним поиск гиперпараметров по количеству соседей, используя 4-кратную проверку.

Предварительная обработка данных

Методы ближайших соседей работают только с числовыми данными, поэтому мы будем использовать только две числовые функции Fare и Age.

Отображение данных

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

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

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

Заключение

Для каждого из подходов требовалось очень мало для переобучения данных:

  1. Наивный Байес, использующий только функцию Sex, работал исключительно хорошо. Многие из более сложных моделей изо всех сил пытались достичь даже 3% большей точности проверки.
  2. Для однослойной сети с прямой связью увеличение размера скрытого слоя свыше 40 не повысило точность проверки.
  3. Для дерева решений всегда существовал значительный разрыв между точностью обучения и проверки со значительным переоснащением с глубиной дерева более 5.

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

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