Загрузите датасет digits с помощью функции load_digits из sklearn.datasets и подготовьте матрицу признаков X и ответы на обучающей выборке y (вам потребуются поля data и target в объекте, который возвращает load_digits).
In [1]:
from sklearn import datasets, tree, cross_validation, ensemble
from sklearn.model_selection import cross_val_score
from math import sqrt
import numpy as np
In [2]:
digits = datasets.load_digits()
In [3]:
X = digits.data
y = digits.target
In [4]:
def write_answer(cross_val_score, file_name):
with open(file_name, "w") as fout:
fout.write(str(cross_val_score))
1. Создайте DecisionTreeClassifier с настройками по умолчанию и измерьте качество его работы с помощью cross_val_score. Эта величина и будет ответом в пункте 1.
In [5]:
clf = tree.DecisionTreeClassifier()
x_val_score = cross_val_score(clf, X, y, cv=10).mean()
write_answer(x_val_score, 'answer_1.txt')
print(x_val_score)
2. Воспользуйтесь BaggingClassifier из sklearn.ensemble, чтобы обучить бэггинг над DecisionTreeClassifier. Используйте в BaggingClassifier параметры по умолчанию, задав только количество деревьев равным 100.
Качество классификации новой модели - ответ в пункте 2. Обратите внимание, как соотносится качество работы композиции решающих деревьев с качеством работы одного решающего дерева.
In [6]:
bagging_clf = ensemble.BaggingClassifier(clf, n_estimators=100)
x_val_score = cross_val_score(bagging_clf, X, y, cv=10).mean()
write_answer(x_val_score, 'answer_2.txt')
print(x_val_score)
3. Теперь изучите параметры BaggingClassifier и выберите их такими, чтобы каждый базовый алгоритм обучался не на всех d признаках, а на $\sqrt d$ случайных признаков. Качество работы получившегося классификатора - ответ в пункте 3. Корень из числа признаков - часто используемая эвристика в задачах классификации, в задачах регрессии же часто берут число признаков, деленное на три. Но в общем случае ничто не мешает вам выбирать любое другое число случайных признаков.
In [7]:
stoch_train_len = int(sqrt(X.shape[1]))
bagging_clf = ensemble.BaggingClassifier(clf, n_estimators=100, max_features=stoch_train_len)
x_val_score = cross_val_score(bagging_clf, X, y, cv=10).mean()
write_answer(x_val_score, 'answer_3.txt')
print(x_val_score)
4. Наконец, давайте попробуем выбирать случайные признаки не один раз на все дерево, а при построении каждой вершины дерева. Сделать это несложно: нужно убрать выбор случайного подмножества признаков в BaggingClassifier и добавить его в DecisionTreeClassifier. Какой параметр за это отвечает, можно понять из документации sklearn, либо просто попробовать угадать (скорее всего, у вас сразу получится). Попробуйте выбирать опять же $\sqrt d$ признаков. Качество полученного классификатора на контрольной выборке и будет ответом в пункте 4.
In [8]:
stoch_clf = tree.DecisionTreeClassifier(max_features=stoch_train_len)
bagging_clf = ensemble.BaggingClassifier(stoch_clf, n_estimators=100)
x_val_score_own = cross_val_score(bagging_clf, X, y, cv=10).mean()
write_answer(x_val_score_own, 'answer_4.txt')
print(x_val_score)
5. Полученный в пункте 4 классификатор - бэггинг на рандомизированных деревьях (в которых при построении каждой вершины выбирается случайное подмножество признаков и разбиение ищется только по ним). Это в точности соответствует алгоритму Random Forest, поэтому почему бы не сравнить качество работы классификатора с RandomForestClassifier из sklearn.ensemble. Сделайте это, а затем изучите, как качество классификации на данном датасете зависит от количества деревьев, количества признаков, выбираемых при построении каждой вершины дерева, а также ограничений на глубину дерева. Для наглядности лучше построить графики зависимости качества от значений параметров, но для сдачи задания это делать не обязательно.
In [9]:
random_forest_clf = ensemble.RandomForestClassifier(random_state=stoch_train_len, n_estimators=100)
x_val_score_lib = cross_val_score(random_forest_clf, X, y, cv=10).mean()
print(x_val_score_lib)
In [10]:
answers = '2 3 4 7'
write_answer(answers, 'answer_5.txt')