Набор данных: «Титаник» — машинное обучение после катастрофы
В этой статье мы исследуем практическую реализацию алгоритма дерева решений с использованием 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, перейдя по этой ссылке.
Затем вы можете применить те же шаги, упомянутые ранее, и посмотреть, улучшит ли использование классификатора случайного леса производительность ваших прогнозов.