#!/usr/bin/env python # coding: utf-8 # # Ансамблевые методы. # # Понижение размерности данных. # Шестаков А.В. Майнор по анализу данных 10/05/2016 # ## 1) Ансамблевые методы (Ensembles) # Не обращаясь к формулам, констатируем, что ошибку модели можно выразить через 3 компоненты: $\text{Error} = \text{Bias}^2 + \text{Variance} + \text{Noise}$ # * $\text{Bias}$ (Смещение) - точность модели. Высокое смещение чаще всего означает, что модель недообучена (underfitting). # * $\text{Variance}$ (Разброс) - чувствительность модели к данным. Высокие разброс чаще всего означает, что модель переобучена (overfitting) # * $\text{Noise}$ (Шум) - это просто шум. # # Для иллюстрации рассмотрим следующую картинку # # # На эти компоненты можно влиять несколькими способами, например, подбирая гиперпараметры моделей.
# *Вопрос: Как меняются Bias и Variance если повышать глубину дерева решений?* # # А еще, можно строить комбинации (ансамбли) моделей! # На лекции в кратце были рассмотрены два способа\алгоритма построения ансамблей. # ### Bagging # Bagging - это параллельный способ построения ансамбля.
# 1. Обучающая выборка сэмплируется $k$ раз с помощью *bootstrap'a* (выборка с возвратом) # 2. На каждом сэмпле обучается отдельная базовая модель # 3. Ответы моделей усредняются (возможно с весом) # # # **Теоретически, такой подход должен уменьшать Variance составляющую ошибки.** # # Самый известный представитель этого метода - модель случайного леса (RandomForest). В данном случае, на каждом сэмпле базовой моделью является дерево решений.
# Если вам нужно за минимальное время построить достаточно точную и устойчивую модель - это ваш вариант. # # *Вопрос: Какая доля объектов в среднем попадает в один bootstrap сэмпл?* # ### Немного интуиции # #### Классификация # In[ ]: import pandas as pd import numpy as np from sklearn.datasets import make_circles from sklearn.datasets import make_moons from sklearn.ensemble import RandomForestRegressor from sklearn.ensemble import RandomForestClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.tree import DecisionTreeRegressor from sklearn.metrics import roc_curve from sklearn.cross_validation import train_test_split import matplotlib.pyplot as plt plt.style.use('ggplot') get_ipython().run_line_magic('matplotlib', 'inline') # In[ ]: X, y = make_circles(n_samples=500, factor=0.1, noise=0.35, random_state=1) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) plt.scatter(X_train[:,0], X_train[:,1], c=y_train) # In[ ]: dtree = DecisionTreeClassifier(random_state=1) dtree.fit(X_train, y_train) # In[ ]: # Копипаст с предыдущего семинара x_range = np.linspace(X.min(), X.max(), 100) xx1, xx2 = np.meshgrid(x_range, x_range) y_hat = dtree.predict(np.c_[xx1.ravel(), xx2.ravel()]) y_hat = y_hat.reshape(xx1.shape) plt.contourf(xx1, xx2, y_hat, alpha=0.2) plt.scatter(X[:,0], X[:,1], c=y) # In[ ]: # Выведем распределение выроятностей предсказаний # Your code here # In[ ]: # Теперь попробуем Случайный лес # Your code here rf = RandomForestClassifier() # In[ ]: # Рисуем предсказания x_range = np.linspace(X.min(), X.max(), 100) xx1, xx2 = np.meshgrid(x_range, x_range) y_hat = rf.predict(np.c_[xx1.ravel(), xx2.ravel()]) y_hat = y_hat.reshape(xx1.shape) plt.contourf(xx1, xx2, y_hat, alpha=0.2) plt.scatter(X[:,0], X[:,1], c=y) # In[ ]: # Распределение вероятнсстей # Your code here # In[ ]: # Посмотрим, из чего складываются предсказания for tree in rf.estimators_: y_hat = tree.predict(np.c_[xx1.ravel(), xx2.ravel()]) y_hat = y_hat.reshape(xx1.shape) plt.contourf(xx1, xx2, y_hat, alpha=0.02) plt.scatter(X[:,0], X[:,1], c=y) # In[ ]: # Сравните roc-кривые для дерева и леса на тесте # Your code here # #### Регрессия # In[ ]: X = np.random.uniform(1, 100, 500) y = np.log(X) + np.random.normal(0, .3, 500) plt.scatter(X, y) # In[ ]: # Обучите модель, изобразите индивидуальные предсказания деревьев # И устредненное предсказание леса plt.scatter(X, y) rf = RandomForestRegressor(n_estimators=10) rf.fit(X.reshape(-1,1), y) x_range = np.linspace(X.min(), X.max(), 100) # Your code here # ### Boosting # Boosting - это последовательный способ построения ансамбля.
Мы постоянно работаем с одним и тем же набором данных, **но** на каждом шаге строим новую базовую модель, которая учитывает ошибки предыдущей модели. # # # **Важное ограничение накладывается на базовые модели: они должны быть НЕМНОГО лучше, чем подбрасывание монетки (weak models).** Иначе нас ждет мгновенный overfitting. # # **Теоретически, такой подход должен уменьшать Bias составляющую ошибки.** # ### Вновь интуиция # #### Классификация # In[ ]: from sklearn.ensemble import GradientBoostingClassifier from sklearn.ensemble import GradientBoostingRegressor # In[ ]: X, y = make_moons(noise=0.1) plt.scatter(X[:, 0], X[:, 1], c=y) # In[ ]: # Обучаем градиентный бустинг на деревьях gbt = GradientBoostingClassifier(n_estimators=12, max_depth=2, learning_rate=0.3, subsample=1) gbt.fit(X, y) # In[ ]: # Cмотрим, как изменяется предсказания с каждым новым деревом fig, ax = plt.subplots(4,3, figsize=(15,15)) ax = ax.ravel() xx1, xx2 = np.meshgrid(np.arange(-1.5, 2.5, 0.1), np.arange(-1, 1.5, 0.1)) yy = gbt.staged_predict(np.c_[xx1.ravel(), xx2.ravel()]) for i, y_hat in enumerate(yy): y_hat = y_hat.reshape(xx1.shape) ax[i].set_title('iteration = %d' % i ) ax[i].contourf(xx1, xx2, y_hat, cmap=plt.cm.Paired) ax[i].scatter(X[:, 0], X[:, 1], c=y) # *Вопрос: Какие недостатки\преимущества есть у ансамблевых методов?* # # 2) Методы понижения размерности данных. # Большое количество признаков в данных - не всегда хорошо. # * Проклятие размерности! # * В признаках может быть шум, а не хотим использовать шумовые взаимосвязи между признаками и прогнозируемой величиной # * Мультиколлинеарность # * Далеко не все признаки вносят весомый вклад в предсказание, но если и дальше их "тащить", то это может повлиять на качество # * Неудобно смотреть на данные # # Избавляться от размерности можно методами **отбора признаков (Feature Selection)** и методами **уменьшения разрмености (Feature Reduction)** # # ### Feature Selection # Методы деляться на три группы: # * Filter methods # * Признаки рассматриваются независимо друг от друга # * Изучается индивидуальный "вклад" призника в предсказываемую переменную # * Быстрое вычисление # * *Пример?* # * Wrapper methods # * Идет отбор группы признаков # * Может быть оооочень медленным, но качество, обычно, лучше чем у Filter Methods # * Stepwise feature selection for regression # * Embedded methods # * Отбор признаков "зашит" в модель # * *Пример?* # #### Filter method - Mutual Information # $$MI(y,x) = \sum_{x,y} p(x,y) \ln[\frac{p(x,y)}{p(x)p(y)}]$$ # Сколько информации $x$ сообщает об $y$. # $$NormalizedMI(y,x) = \frac{MI(y,x)}{H(y)}$$ # In[ ]: from sklearn.metrics import normalized_mutual_info_score as nmi # In[ ]: # Размеберем некоторые примеры # *Вопрос: А что делать если у нас не категориальные а вещественные признаки?* # #### Wrapper Methods - Recursive Feature Elimination # При данном подходе из модели последовательно удаляются признаки с наименьшим коэффициентом # In[ ]: from sklearn.datasets import make_regression from sklearn.feature_selection import RFE from sklearn.linear_model import LinearRegression # In[ ]: X, y = make_regression(n_samples=500, n_features=4, n_informative=1, n_targets=1, tail_strength=0.5, noise=1.0, coef=False, random_state=None) # In[ ]: plt.scatter(y, X[:,1]) # In[ ]: model = LinearRegression() rfe = RFE(model, n_features_to_select=1, verbose=1) rfe.fit(X,y) # In[ ]: rfe.support_ # ### Feature Reduction # Методы Feature Reduction производят преобразования признакового пространства, при этом пытаясь сохранить какие-то свойства данных. # # PCA (Principal Component Analysis) - делаем такое линейное преобразование признаков, чтобы каждая следующая комплнента содержала в себе наибольшую изменчивость в данных. # # Мы уже делали PCA на семинарах (в самом начале, где еще было задание с лицами). Повторимся.. # In[ ]: from sklearn.decomposition import PCA from sklearn.datasets import load_digits # In[ ]: digits = load_digits() X = digits.images y = digits.target # In[ ]: plt.imshow(X[2,:], cmap='Greys', interpolation='none') # In[ ]: # Перейдем от изображений к матрице объект-признак # И сделаем PCA в помощью готовой функции в sklearn и SVD # In[ ]: