Задание 3 Смещение и разброс методов обучения

Исследуем численно разброс и смещение различных моделей обучения. Данные будем генирировать следующим образом. x- одномерное распределение (рассмотрите три различных распределения: нормальное ( np.random.normal(0, 0.3), экспоненциальное (np.random.exponential(0.3)), равномерное (np.random.uniform(0, 1)) y- сумма f(x)=cos(2pi x) и случайного шума (равномерное распределение на [-0.2. 0.2]

Возьмем метод обучения (рассмотрите 4 различных "LinearRegression", "DecisionTree", "RandomForest", "GradientBoosting")

1) Обучите модель с параметрами по умолчанию на сгенерированной выборке (число объектов выборки 100). Постройте на одном графике объекты выборки и восстановленную регрессионную кривую

2) Рассмотрим ансамбль обучающих моделей. Сгенерируйте N_samples=25 случайных выборок, обучите и постройте все выборки и все регрессионные кривые на одном графике (полупрозрачным). Посчитайте среднюю кривую F(x) , как среднее арифмитическое по ансамблю регрессионных кривых. Изобразите его тоже на графике. Изобразите истинную кривую ответов.

3) Вычислите смещение метода обучения. Смещение - это среднее квадрата разности вектора зашумленных ответов и вектора предсказаний

$$ Bias= E_{x,y} ((\mathbb{E}[y|x] - \mathbb{E}_X [\mu(X)])^2)$$

.

Для вычисления этого мат.ожидания будем генерировать выборку размера N_objects=100. Средний ответ $\mathbb{E}[y|x] $ на объекте x вычислите как сумму f(x) + среднее значение шума на выборке N_objects (для этого можно сгенерировать отдельно N_objects шумовых компонент) Среднее предсказание $\mathbb{E}_X [\mu(X)]$ на объекте x - это значение построенной функции F(x) (см.2) Мат. ожидание заменяем на среднее арифмитическое по выборке N_objects.

4) Вычислите разброс метода обучения. Разброс - это среднеквадратичное отклонение предсказания алгоритмов метода $\mu$ на объекте x от среднего предсказания $\mathbb{E}_X [\mu(X)]$ $$ Variance=E_{x,y} (E_{X}(\mathbb{E}_X [\mu(X)] - \mu(X)])^2)$$

Чтобы его вычислить, на выборке N_objects вычислите среднее арифмитическое по N_samples алгоритмам (см. 2) для N_objects объектов.

5) Представьте результаты в виде таблицы, проанализируйте (какой метод дает наименьший разброс, какой наименьшее смещение, почему?, как смещение и разброс связаны с распределением признака x)

28.02. Бэггинг и случайный лес

1)Загрузите датасет digits с помощью функции load_digits из sklearn.datasets и подготовьте матрицу признаков X и ответы на обучающей выборке y.

2)Для оценки качества далее нужно будет использовать cross_val_score из sklearn.cross_validation с параметром cv=10. Эта функция реализует k-fold cross validation c k равным значению параметра cv. Используйте k=10, чтобы полученные оценки качества имели небольшой разброс. Функция cross_val_score будет возвращать numpy.ndarray, в котором будет k чисел - качество в каждом из k экспериментов k-fold cross validation. Получите среднее значение (которое и будет оценкой качества работы) массива, который возвращает cross_val_score.

3)Воспользуйтесь BaggingClassifier из sklearn.ensemble, чтобы обучить бэггинг над DecisionTreeClassifier. Используйте в BaggingClassifier параметры по умолчанию, задав только количество деревьев равным 100. Качество классификации новой модели - среднее значение cross_val_score . Сравните работу композиции деревьев с одним решающем деревом.

4)Теперь изучите параметры BaggingClassifier и выберите их такими, чтобы каждый базовый алгоритм обучался не на всех d признаках, а на $\sqrt{d}$ случайных признаков. Каково качество работы алгоритма?

5)Наконец, давайте попробуем выбирать случайные признаки не один раз на все дерево, а при построении каждой вершины дерева. Сделать это несложно: нужно убрать выбор случайного подмножества признаков в BaggingClassifier и добавить его в DecisionTreeClassifier. Какой параметр за это отвечает, можно понять из документации sklearn. Попробуйте выбирать опять же $\sqrt{d}$ признаков. Какое теперь качество полученного классификатора?

6)Полученный в пункте 4 классификатор - бэггинг на рандомизированных деревьях (в которых при построении каждой вершины выбирается случайное подмножество признаков и разбиение ищется только по ним). Это в точности соответствует алгоритму Random Forest. Сравнить качество работы классификатора с RandomForestClassifier из sklearn.ensemble.

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

1)Загрузите датасет digits с помощью функции load_digits из sklearn.datasets и подготовьте матрицу признаков X и ответы на обучающей выборке y.

In [6]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn import datasets
digits = datasets.load_digits()
X = digits.data
y = digits.target
print(digits.DESCR)
Optical Recognition of Handwritten Digits Data Set
===================================================

Notes
-----
Data Set Characteristics:
    :Number of Instances: 5620
    :Number of Attributes: 64
    :Attribute Information: 8x8 image of integer pixels in the range 0..16.
    :Missing Attribute Values: None
    :Creator: E. Alpaydin (alpaydin '@' boun.edu.tr)
    :Date: July; 1998

This is a copy of the test set of the UCI ML hand-written digits datasets
http://archive.ics.uci.edu/ml/datasets/Optical+Recognition+of+Handwritten+Digits

The data set contains images of hand-written digits: 10 classes where
each class refers to a digit.

Preprocessing programs made available by NIST were used to extract
normalized bitmaps of handwritten digits from a preprinted form. From a
total of 43 people, 30 contributed to the training set and different 13
to the test set. 32x32 bitmaps are divided into nonoverlapping blocks of
4x4 and the number of on pixels are counted in each block. This generates
an input matrix of 8x8 where each element is an integer in the range
0..16. This reduces dimensionality and gives invariance to small
distortions.

For info on NIST preprocessing routines, see M. D. Garris, J. L. Blue, G.
T. Candela, D. L. Dimmick, J. Geist, P. J. Grother, S. A. Janet, and C.
L. Wilson, NIST Form-Based Handprint Recognition System, NISTIR 5469,
1994.

References
----------
  - C. Kaynak (1995) Methods of Combining Multiple Classifiers and Their
    Applications to Handwritten Digit Recognition, MSc Thesis, Institute of
    Graduate Studies in Science and Engineering, Bogazici University.
  - E. Alpaydin, C. Kaynak (1998) Cascading Classifiers, Kybernetika.
  - Ken Tang and Ponnuthurai N. Suganthan and Xi Yao and A. Kai Qin.
    Linear dimensionalityreduction using relevance weighted LDA. School of
    Electrical and Electronic Engineering Nanyang Technological University.
    2005.
  - Claudio Gentile. A New Approximate Maximal Margin Classification
    Algorithm. NIPS. 2000.

In [12]:
print(X.shape,'\n', y.shape)
(1797, 64) 
 (1797,)

2)Для оценки качества далее нужно будет использовать cross_val_score из sklearn.cross_validation с параметром cv=10. Эта функция реализует k-fold cross validation c k равным значению параметра cv. Используйте k=10, чтобы полученные оценки качества имели небольшой разброс. Функция cross_val_score будет возвращать numpy.ndarray, в котором будет k чисел - качество в каждом из k экспериментов k-fold cross validation. Получите среднее значение (которое и будет оценкой качества работы) массива, который возвращает cross_val_score.

In [16]:
from sklearn import cross_validation
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier()
cv_score = cross_validation.cross_val_score(model, X, y, cv=10)
print(cv_score.shape)
print(np.mean(cv_score))
(10,)
0.823659940565

3)Воспользуйтесь BaggingClassifier из sklearn.ensemble, чтобы обучить бэггинг над DecisionTreeClassifier. Используйте в BaggingClassifier параметры по умолчанию, задав только количество деревьев равным 100. Качество классификации новой модели - среднее значение cross_val_score . Сравните работу композиции деревьев с одним решающем деревом.

In [33]:
from sklearn.ensemble import BaggingClassifier
bag_model = BaggingClassifier(model, n_estimators=100)
cv_score_bag = cross_validation.cross_val_score(bag_model, X, y, cv=10)
print(cv_score_bag.shape)
print(np.mean(cv_score_bag))
(10,)
0.921602578895

4)Теперь изучите параметры BaggingClassifier и выберите их такими, чтобы каждый базовый алгоритм обучался не на всех d признаках, а на $\sqrt{d}$ случайных признаков. Каково качество работы алгоритма?

In [34]:
bag_model1 = BaggingClassifier(model, n_estimators=100, max_features=int(np.sqrt(X.shape[1])))
cv_score_bag1 = cross_validation.cross_val_score(bag_model1, X, y, cv=10)
print(cv_score_bag1.shape)
print(np.mean(cv_score_bag1))
(10,)
0.938305561506

5)Наконец, давайте попробуем выбирать случайные признаки не один раз на все дерево, а при построении каждой вершины дерева. Сделать это несложно: нужно убрать выбор случайного подмножества признаков в BaggingClassifier и добавить его в DecisionTreeClassifier. Какой параметр за это отвечает, можно понять из документации sklearn. Попробуйте выбирать опять же $\sqrt{d}$ признаков. Какое теперь качество полученного классификатора?

In [35]:
tree_model = DecisionTreeClassifier(splitter='random', max_features=int(np.sqrt(X.shape[1])))
bag_model2 = BaggingClassifier(tree_model, n_estimators=100, bootstrap=False, max_features=int(np.sqrt(X.shape[1])))
cv_score_bag2 = cross_validation.cross_val_score(bag_model2, X, y, cv=10)
cv_score_tree = cross_validation.cross_val_score(tree_model, X, y, cv=10)
print(np.mean(cv_score_bag2))
print(np.mean(cv_score_tree))
0.940482695099
0.743906729552

6)Полученный в пункте 4 классификатор - бэггинг на рандомизированных деревьях (в которых при построении каждой вершины выбирается случайное подмножество признаков и разбиение ищется только по ним). Это в точности соответствует алгоритму Random Forest. Сравнить качество работы классификатора с RandomForestClassifier из sklearn.ensemble.

In [25]:
from sklearn.ensemble import RandomForestClassifier
model_rfc = RandomForestClassifier()
cv_score_rfc = cross_validation.cross_val_score(model_rfc, X, y, cv=10)
print(np.mean(cv_score_rfc))
0.922604624474

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

In [73]:
num_trees = np.arange(1, 200, 10)
num_features = np.arange(1, X.shape[1]+1, 1)
depths = np.arange(1, 100, 5)
In [57]:
a = []
nn = 0
for i in num_trees:
    nn += 1
    print(nn)
    temp_tree = DecisionTreeClassifier(splitter='best')
    temp_model = BaggingClassifier(temp_tree, n_estimators=i)
    temp_score = cross_validation.cross_val_score(temp_model, X, y, cv=10)
    a.append(np.mean(temp_score))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
In [60]:
plt.plot(num_trees, a)
plt.xlabel("num_trees")
plt.ylabel("Score")
Out[60]:
<matplotlib.text.Text at 0x7f90418e2e48>
In [61]:
nn = 0
for i in num_features:
    nn += 1
    print(nn)
    temp_tree = DecisionTreeClassifier(splitter='best', max_features=i)
    temp_model = BaggingClassifier(temp_tree, max_features=i)
    temp_score = cross_validation.cross_val_score(temp_model, X, y, cv=10)
    a.append(np.mean(temp_score))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
In [70]:
plt.plot(num_features, a[num_trees.shape[0]:])
plt.xlabel("num_features")
plt.ylabel("Score")
Out[70]:
<matplotlib.text.Text at 0x7f903b8c8ac8>
In [74]:
nn = 0
b = []
for i in depths:
    nn += 1
    print(nn)
    temp_tree = DecisionTreeClassifier(splitter='best', max_depth=i)
    temp_model = BaggingClassifier(temp_tree)
    temp_score = cross_validation.cross_val_score(temp_model, X, y, cv=10)
    b.append(np.mean(temp_score))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
In [75]:
plt.plot(depths, b)
plt.xlabel("depth")
plt.ylabel("Score")
Out[75]:
<matplotlib.text.Text at 0x7f903b90abe0>