Набор данных: «Титаник» — машинное обучение после катастрофы
В этой статье мы исследуем практическую реализацию алгоритма дерева решений с использованием scikit-learn. Мы рассмотрим различные важные концепции, связанные с решением типичной задачи машинного обучения, включая обучение и настройку модели.
Если вы еще этого не сделали, обязательно ознакомьтесь с первой частью серии статей, где мы обсуждаем важные этапы предварительной обработки данных и выбора функций.
Терминология с использованием аналогии с кухней
Прежде чем двигаться дальше, я хочу прояснить некоторые термины, связанные с машинным обучением, используя аналогию с кухней.

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

Во-первых, мы разделяем предоставленные данные на
- Исследование данных. Мы используем эти данные для построения хорошей модели, обучая ее и корректируя определенные параметры (гиперпараметры).
- Тестовые данные. Мы не трогаем их, пока не убедимся, что наша модель хорошо работает с исследовательскими данными. Мы можем использовать эти данные, чтобы предоставить объективную оценку производительности нашей модели.
Далее мы разделяем исследовательские данные еще дальше.
- Данные для обучения. Мы используем эти данные для обучения нашей модели. Именно здесь модель учится на данных, чтобы делать точные прогнозы.
- Проверочные данные. Мы используем их для сравнения различных моделей и выбора их гиперпараметров и выбора наиболее эффективных из них.
Просто полагаться на точность модели на всем наборе обучающих данных может ввести в заблуждение. Пробуя разные модели и гиперпараметры и оценивая их эффективность на проверочном наборе, мы можем выбрать модель, которая работает лучше всего.
from sklearn.model_selection import train_test_split
# Split the columns into features (X) and target variable (y)
X = train_data_p.loc[:, train_data_p.columns != 'Survived']
y = train_data_p['Survived']
# Split the train data into training, validation and test datasets
# Original train data = 80% exploratory + 20% test
# Exploratory data = 70% training + 30% validation
X_explore, X_test, y_explore, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_explore, y_explore, test_size=0.3, random_state=42)
print("Original dataset: ", X.shape, y.shape)
print("Training dataset: ", X_train.shape, y_train.shape)
print("Validation dataset: ", X_val.shape, y_val.shape)
print("Test dataset: ", X_test.shape, y_test.shape)

Шаг 5: Обучение
В этой статье я буду использовать алгоритм дерева решений для обучения. Посмотрите видео ниже, чтобы понять, как алгоритм работает внутри, объясненный простым способом.
Давайте приступим к реализации классификатора дерева решений с использованием библиотеки scikit-learn.
from sklearn import tree from sklearn import metrics # Create a decision tree classifier object clf = tree.DecisionTreeClassifier(random_state=42) # Train the decision tree on the training dataset (X_train, y_train) clf.fit(X_train, y_train) # Predict the survival outcomes on the validation dataset (X_val) y_val_pred = clf.predict(X_val)
Чтобы визуализировать дерево решений, вы можете использовать приведенный ниже код. Регулируя параметр max_depth, вы можете управлять глубиной дерева. Удалите max_depth из кода ниже, чтобы увидеть полное дерево, построенное моделью.
tree.plot_tree(clf, feature_names=X_train.columns, max_depth=1)

Наконец, мы можем оценить точность классификатора дерева решений как на данных обучения, так и на данных проверки.
print("Accuracy of decision tree classifier on training data: ", clf.score(X_train, y_train))
print("Accuracy of decision tree classifier on validation data: ", clf.score(X_val, y_val))
print("Max depth of decision tree classifier : ", format(clf.tree_.max_depth))

Шаг 6: Настройка гиперпараметров
Из приведенных выше значений точности мы видим, что модель переоснащает данные обучения с высокой точностью 1,0 для данных обучения, но с меньшей точностью 0,73 для данных проверки.
Чтобы решить эту проблему, мы можем настроить гиперпараметры классификатора дерева решений, такие как max_depth и min_samples_split, чтобы найти оптимальные значения.
max_depth: максимальная глубина дерева. Если None, то узлы расширяются до тех пор, пока все листья не станут чистыми или пока все листья не будут содержать менееmin_samples_splitвыборок.min_samples_split: минимальное количество выборок, необходимое для разделения внутреннего узла. Значение по умолчанию — 2.
Другие параметры см. в документации ниже.
Если мы не укажем значения гиперпараметров, алгоритм дерева решений будет продолжать увеличивать дерево до тех пор, пока не сможет точно предсказать все значения обучающего набора. Это может привести к переоснащению, когда модель слишком зациклена на обучающих данных и не так хорошо предсказывает новые, невидимые данные.
Мы можем попробовать разные значения для max_depth и построить показатели точности как для обучающего, так и для проверочного набора данных.
max_depths_tuning = [3,4,5,6,7,8]
clfs = []
for max_depth in max_depths_tuning:
clf = tree.DecisionTreeClassifier(random_state=42, max_depth=max_depth)
clf.fit(X_train, y_train)
clfs.append(clf)
# plot the accuracy score on training and validation datasets for different max_depth values
train_scores = [clf.score(X_train, y_train) for clf in clfs]
val_scores = [clf.score(X_val, y_val) for clf in clfs]
fig, ax = plt.subplots()
ax.plot(max_depths_tuning, train_scores, marker='o', label='train', drawstyle='steps-post')
ax.plot(max_depths_tuning, val_scores, marker='o', label='val', drawstyle='steps-post')
ax.set_xlabel("max_depth")
ax.set_ylabel("accuracy")
ax.set_title("Accuracy vs max_depth for training and testing sets")
ax.legend()
plt.show()

- График ясно показывает, что по мере того, как мы делаем дерево решений глубже, оно становится лучше для точного прогнозирования обучающих данных.
- Однако это улучшение не работает, когда речь идет о новых, невидимых данных. Точность проверочного набора начинает падать, что указывает на переоснащение.
- Но в
max_depth = 4,мы находим баланс. Модель хорошо работает как с данными обучения, так и с данными проверки, демонстрируя свою способность обобщать и делать точные прогнозы.
GridSearchCV
Если мы хотим точно настроить несколько гиперпараметров, таких как min_sample_split и num_features, мы можем обратиться к удобному инструменту, предоставленному scikit-learn, который называется GridSearchCV. (Есть и другие методы!)
Перекрестная проверка (CV) – это метод, при котором вы
- Разделите набор обучающих данных на
kгрупп. - Попробуйте различные комбинации гиперпараметров, обучая модель на
k-1группах и тестируя оставшуюся группу. - Оцените производительность каждой комбинации и выберите оптимальные параметры.
Поиск по сетке включает в себя обучение нашей модели всем возможным комбинациям указанных гиперпараметров в k-1 группах, а затем тестирование модели в оставшейся группе. Он сравнивает и находит комбинацию гиперпараметров, которая дает наилучшую точность для нашей модели.
from sklearn.model_selection import GridSearchCV
tuned_params = [{'max_depth': [2,3,4,5,6,7,8], 'min_samples_split': [20,30,40,50,60,70,80,90]}]
tclf = GridSearchCV(tree.DecisionTreeClassifier(), tuned_params, scoring='accuracy')
# Using exploratory data directly instead of training data
# as the cross validation algorithm splits the provided data
# into training and validation groups internally
tclf.fit(X_explore, y_explore)
ix = tclf.best_index_
print(tclf.best_params_)
print('Index of the combination: ', ix)

- В этом примере у нас есть 7 возможных значений для
max_depthи 8 возможных значений дляmin_samples_split. - Это означает, что у нас есть всего 56 комбинаций параметров, которые можно опробовать.
- GridSearchCV строит и оценивает 56 моделей, используя перекрестную проверку предоставленных данных, а затем сообщает нам наилучшую комбинацию гиперпараметров, дающую максимальную оценку.
Мы даже можем построить поезд и результаты тестов для различных комбинаций, чтобы визуализировать их производительность.
train_scores = tclf.cv_results_["mean_train_score"]
val_scores = tclf.cv_results_["mean_test_score"]
index = np.arange(len(tclf.cv_results_["params"]))
fig, ax = plt.subplots()
ax.plot(index, train_scores, marker='o', label='train', drawstyle='steps-post')
ax.plot(index, val_scores, marker='o', label='val', drawstyle='steps-post')
ax.set_xlabel("Index")
ax.set_ylabel("Accuracy")
ax.set_title("Train and test scores for different hyperparameters")
ax.legend()
plt.show()

В индексе 8 мы видим, что и поезд, и тест имеют самые высокие оценки. Это соответствует комбинации гиперпараметров {'max_depth': 3, 'min_samples_split': 20}, в чем мы можем убедиться, обратившись к tclf.cv_results_["params"][8].
Наконец, мы можем проверить точность нашего настроенного классификатора дерева решений на обучающих, проверочных и невидимых тестовых данных.
print("Accuracy of tuned decision tree classifier on training data: ", train_scores[8])
print("Accuracy of tuned decision tree classifier on validation data: ", val_scores[8])
print("Accuracy of tuned decision tree classifier on unseen test data: ", tclf.score(X_test, y_test))

Шаг 7: Заключительный шаг
Поскольку значения точности для всех трех моделей одинаковы, это указывает на то, что наша модель не переоснащается.
Теперь мы можем приступить к обучению модели с использованием настроенных гиперпараметров на всем предоставленном обучающем наборе данных и делать прогнозы на тестовом наборе данных, предоставленном Kaggle.
Отправка выходных данных, сгенерированных приведенным ниже кодом, привела к получению оценки 0,7799.
# Create a decision tree classifier object using the tuned hyperparameters
clf = tree.DecisionTreeClassifier(max_depth=3, min_samples_split=20, random_state=42)
# Train the decision tree on the entire training dataset
clf.fit(X, y)
# Predict the survival outcomes on the provided test dataset (X_val)
X_final_test = test_data_p.loc[:, train_data_p.columns != 'Survived']
predictions = clf.predict(X_final_test)
# create output file
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})
output.to_csv('submission.csv', index=False)
Дальнейшие шаги:
Не стесняйтесь исследовать классификатор Random Forest, перейдя по этой ссылке.
Затем вы можете применить те же шаги, упомянутые ранее, и посмотреть, улучшит ли использование классификатора случайного леса производительность ваших прогнозов.