Как известно, многие методы машинного обучения основаны на аппарате математической статистики. Методы ресемплинга, или методы получения повторных выборок - это как раз статистические методы, которые позволяют из одной выборки определенным образом сгенерировать множество новых выборок. То есть ресемплинг занимается тем, что формирует новые выборки на основе исходной, а не из генеральной совокупности, и помогает вычислять различные статистики по каждой из этих выборок. Такая стратегия помогает получить дополнительную информацию для настройки процесса машинного обучения и получить более производительные модели.

Каждый раз, когда мы берем выборку из генеральной совокупности и вычисляем различные статистики, оцениваемый параметр может быть близок к реальному значению, только благодаря случайности, поэтому мы располагаем очень малым количеством информации о достоверности наших выводов и наши предсказания могут быть сомнительными. Поэтому использование повторных выборок помогает исследовать различные комбинации вычисленных значений характеристик, которые дают нам согласованный диапазон значений для оценки истинных параметров.

Основной недостаток машинного обучения - это расхождение между ошибками на этапе обучения и ошибками на этапе тестирования модели. Метрики обучения являются ключевыми для автоматизации и получения представления о выполнении алгоритмов обучения, но полезность модели заключается в том, насколько хорошо она справляется с невидимыми данными. Рассмотрим основные методы для получения повторных выборок.

Метод Джекнайф (Jacknife) - один из методов ресемплинга. Метод применяется для построения достаточно точных характеристик параметров распределения выборки.

Джекнайф выборками

\ X_{[1]}, X_{[2]},..,X_{[n]}

называются наборы, формируемые из исходной выборки следующим образом:

\ X_{[i]} = (X_{1},..., X_{i-1}, X{i+1},.., X_{n})

Другими словами, i-ая джекнайф-выборка получается из исходной удалением i-го элемента. Можно заметить, что используя такой метод мы можем сразу получить n псевдовыборок.

Тогда, если мы хотим получить оценки параметров распределения по выборке, мы получим вместо одной оценки n-1 частичных оценок.

\widehat{\theta}_{-i} = \widehat{\theta}_{n-1}(X_{[i]})= \widehat{\theta}_{n-1}(X_{1},..,X_{i-1},X_{i+1},..,X{n})

Тогда средним джекнайф-оценки будет величина 

\widehat{\theta}_{jack}= \frac{1}{n}\sum_{i=1}^n {\widetilde\theta_{i}}

где

\widetilde\theta_{i} = n\widehat\theta_{n}-(n-1)\widehat\theta_{(-i)}

i-ое псевдозначение параметра θ, построенного по джекнайф-выборке X[i].

Другими словами можно сказать, что джекнайф-оценка параметра θ - это n исходных оценок по выборке

 \ X_{[1]}, X_{[2]},..,X_{[n]}

  минус (n-1) среднее арифметическое частичных оценок.

Теперь оценим дисперсию

\widehat{\theta}_{n}

Джекнайф-оценкой дисперсии будет величина

\widehat{\ Var}_{jack}=\frac {1} {n(n-1)}\sum_{i=1}^n{( \widetilde {\theta_{i}}-\widehat{\theta}_{jack}})^2

Метод бутстрэп (Bootstrap) является еще одним из методов генерации повторных псевдовыборок. Был предложен в 1979 году Брэдли Эфроном. Метод основывается на следующей идее. Пусть X1, X2,..,Xn - выборка. Опираясь на нее, мы можем смоделировать распределение ξ и в дальнейшем получить необходимые выборки из смоделированного распределения.

Как известно из статистики, истинное распределение ξ по выборке X1, X2,..,Xn разумно приближается эмпирическим с функцией распределения 

\ F^{*}_n(x)= \frac{1} {n}\sum_{i=1}^n{I(X_{i}<x)}

где I(A) - индикатор события А задается как

f(n) = \begin{cases}   1,  \mbox{ A произошло} \\ 0,  \mbox { A  не произошло} \end{cases}

Имея функцию распределения можно легко моделировать выборки необходимого объема. Это будет эквивалентно формированию выборок путем случайного выбора из n объектов с возвращением из исходной выборки.

В данном случае бутсрэп-выборкой объема n из выборки  X1, X2,..,Xn

будет набор

\ X^{(j)}_{1}, X^{(j)}_{2},..,X^{(j)}_{n}

где

\ X^{(j)}_{i} \in {X_{1}, X_{2},..,X_{n}}

Понятно, что число полученных таким образом выборок чрезвычайно велико и поэтому на практике берут значительно меньшее количество бутстрэп-выборок, чем существует. Так как выбор производится с возвращением, то в бутсрэп-выборках могут встречаться повторяющиеся элементы исходной выборки. Таким образом, после генерации бутсрэп-выборок можно вычислить оценки математического ожидания и дисперсии оценки

\widehat \theta_{(*),B}=\frac {1} {B} \sum_{j=1}^B{\widehat {\theta}_{j}}\widehat{\ Var}_{B}=\frac {1} {(B-1)}\sum_{i=1}^n{( \widehat {\theta}^{j}-\widehat{\theta}_{(*),B}})^2

Можно обратить внимание, что мы не выдвигали никаких предположений о распределении ξ. В то же время, если известно, каким образом распределение ξ зависит от интересующего нас параметра, метод можно усилить. В этом случае бутстрэп-выборки генерируются из эмпирической функции распределения, в которую вместо неизвестного параметра θ может быть подставлена его оценка.

Можно сделать еще небольшое замечание, что присутствует небольшая путаница, связанная с несколько иным, но родственным методом LOOCV (Leave-One-Out Cross Validation поэлементная кросс-валидация). Данный метод иногда тоже называется складной нож, но при этом используется для оценки качества прогноза вычислительных моделей, используемых для прогнозирования данных, не используемых для обучения модели. Складной нож можно использовать для оценки фактической прогностической способности моделей путем прогнозирования значений зависимой переменной каждого наблюдения, как если бы это наблюдение было новым наблюдением. Для этого прогнозируемые значения каждого наблюдения получают из модели, построенной на выборка наблюдений за вычетом прогнозируемого наблюдения. Складной нож в данном контексте — это процедура, которая используется для получения несмещенного прогноза (т. е. случайного эффекта) и минимизации риска переобучения. LOOCV является расширением техники складного ножа. В LOOCV мы вычисляем статистику для неиспользованной выборки (выборок) и прогнозируем оставшуюся выборку (выборки), строя модель на оставшихся выборках. В Jackknife мы вычисляем статистику только из оставшихся выборок.

При решении задач машинного обучения обычно мы берем конкретный метод, реализуем его и оцениваем точность. Если точность хорошая, значит задача решена. Но, к сожалению ни один из методов не является полностью универсальным, так как каждый из них работает на определенных данных, в определенной ситуации и сложно надеяться, что он будет хорошо работать на любых данных. Поэтому мы приходим к такому понятию как ансамбли моделей. 

Ансамбли - это набор различных алгоритмов, обученных на одних и тех же данных. Основной смысл заключается в том, что вместе несколько моделей будут работать лучше, чем одна. И для обучения различных моделей желательно иметь разные данные. Но обычно мы работаем с одной выборкой. И тут как раз приходят на помощь различные методы ресемплинга, рассмотренные ранее.

Предположим, что мы рассматриваем обучение с учителем и имеем обучающую выборку \ X1, X2,..,Xn с откликами Y1, Y2,..,Yn

где

\ x_{i} \in X, y_{i} \in Y , i=1,..,n

Пусть

b_{1}(x), b_{2}(x),..,b_{n}(x)

- базовые алгоритмы, тогда ансамблем алгоритмов с корректирующим правилом F и решающим правилом С называется алгоритм

\ a(x) = C(F(b_{1}(x), b_{2}(x),..,b_{k}(x)))

.

Разберемся, что же такое корректирующее правило. Каждый базовый алгоритм выдает нам какое-то предсказание, например, вероятность принадлежности к классу в задачах классификации, в общей сложности k решений. Далее нам необходимо принять какое-то одно решение, используя k предсказаний наших базовых алгоритмов. Для этого чаще всего используются следующие методы

  1. Простое голосование (Simple Voting)

\ F(b_{1}(x), b_{2}(x),..,b_{k}(x))=\frac {1} {k} \sum_{i=1}^k{b_i{x}},

то есть просто усреднение ответов

  1. Взвешенное голосование (Weighted Voting)

\ F(b_{1}(x), b_{2}(x),..,b_{k}(x))= \sum_{i=1}^k{w_ib_i(x)},

где w_i - какие-то веса, причем \sum_{i=1}^k{w_i}=1

Здесь, больший вес мы будем давать алгоритму, которому больше доверяем.

  1. Голосование большинством

\ F(b_{1}(x), b_{2}(x),..,b_{k}(x)) = mode(a_1(x), a_2(x),..., a_k(x))

то есть выбираем значение, которое встречается наиболее часто. Если таких значений несколько, можно взять любое.

  1. Взвешенное голосование.

    \ F(b_{1}(x), b_{2}(x),..,b_{k}(x)) = arg \mbox { max} \sum_{i=1}^k{w_iI(a_i(x)=m)}

где I -индикаторная функция, m - номер класса в задаче M классовой классификации.

Методы 1 и 2 можно использовать в задачах регрессии, а 3-4 в задачах классификации

Здесь приведены наиболее часто встречающиеся корректирующие функции, и выбор какой-то одной из них является достаточно сложной задачей, которая зависит от предметной области. 

Базовые алгоритмы могут быть получены как с использованием различных алгоритмов машинного обучения, так и с помощью различных обучающих выборок.

Теперь перейдем к рассмотрению ансамблевых алгоритмов.

Бэггинг

Одним из подходов к построению ансамблей является бэггинг, который основан на независимом обучении базовых алгоритмов на различных выборках. Суть бэггинга заключается в том, что по исходной обучающей выборке \ X_{1}, X_{2},..,X_{n} создается какое-то определенное количество, например t, независимых подвыборок объема l<n методом бутстрэп.

X_{1}^{(j)}, X_{2}^{(j)},..,X_{l}^{(j)}, j=1,2..,t.

Далее, базовые алгоритмы b_{1}(x), b_{2}(x),..,b_{t}(x)обучаются для каждой из подвыборок и формируется ансамбль моделей. Часто бэггинг используется для уменьшения дисперсии каждого базового алгоритма. Естественно, что выбор объема подвыборки l- это отдельная задача. С одной стороны, получившаяся выборка должна быть репрезентативной для обучения, а с другой - не позволять модели переобучиться. Кроме того, чем больше объем выборки, тем дольше обучается модель. Если, к тому же, велико и число t, то вычислительных мощностей может и не хватить.

Бустинг

Адаптивный бустинг отличается от бэггинга тем, что базовые алгоритмы обучаются теперь не независимо, а последовательно, учитывая опыт предыдущего. Причем каждый следующий классификатор строится по объектам, которые неверно классифицировали предыдущие ансамбли. 

Предположим, что мы имеем обучающую выборку \ x_{1}, x_{2},..,x_{n} с откликами \ y_{1}, y_{2},..,y_{n}

 Попробуем описать алгоритм по шагам

  1. Инициализируем веса 

\ alpha_i= \frac{1}{n}, i=1,..,T, где T - количество обученных алгоритмов

  1. Для всех t=1,...,T

  1. Находим такой алгоритм \ b_t из множества базовых алгоритмов, что

\ b_t =  arg \mbox { min} \sum_{i=1}^n{\alpha_i |(b(x_i \neq {y_i)}}

t = 1,.., T - это слабые классификаторы.

  1. Пусть \varepsilon_t  - минимальное значение на алгоритме \ b_t и

\varepsilon_t =  \sum_{i=1}^n{\alpha_i |(b_t(x_i )\neq {y_i)}}

тогда веса \ w_t

\ w_t=\frac {1}{2}ln \frac {1-\varepsilon_t}{\varepsilon_t}
  1. Вычислить \alpha_i=\alpha_ie^{-y_iw_ib_t(x_i)}, где i=1,2,..,n

  2. Нормировать коэффициенты \alpha_i, i=1,..,n

\alpha_0=\sum_{i=1}^n\alpha_i, \alpha_i= \frac{ \alpha_i}{\alpha_0}

3. Итоговый ансамбль имеет вид

a(x)=sign(\sum_{t=1}^Tw_tb_t(x))

Стекинг

Идея стекинга состоит в том, чтобы обучить несколько разных базовых моделей и объединить их путем обучения так называемой метамодели для получения прогнозов, основанных на предсказаниях возвращаемых базовыми моделями. Получается, что используется не заранее спланированное решение, вроде голосования, а корректирующее правило новой модели.

Рассмотрим алгоритм

Предположим, что мы имеем обучающую выборку X= {x_{1}, x_{2},..,x_{n}} с откликами Y={ y_{1}, y_{2},..,y_{n}}, b_1, b_2,.., b_n - базовые алгоритмы.

  1. Разделим выборку на l непересекающихся блоков (фолдов) X_1, X_2,.., X_l.

  2. Для каждого i=1,2,..,l и j=1,2,..,l последовательно перебирая фолды необходимо обучить базовые алгоритмы b_i на всех фолдах, кроме одного. А на оставшемся получить отклики базовых алгоритмов Y{ji}

  3. Сформировать метаданные (метапредикторы) для обучения метамодели

\begin{pmatrix}   Y_{11}& Y_{22}&...&Y_{1l}\\   Y_{21}& Y_{22}&...&Y_{2l} \\ ...&...&...&...\\Y_{l1}&Y_{l2}&...&Y_{ll}\\ \end{pmatrix}

.

В качестве откликов для обучения метамодели взять исходные отклики Y.

  1. Обученная модель является ансамблем, построенным на основе стекинга

Вообще стекинг является наименее популярным ансамблевым алгоритмом. Также, можно обратить внимание, что модели стекирования обычно требуют больше времени для обучения и имеют гораздо меньшие задержки, чем другие модели. То есть, если нужны быстрые прогнозы, тогда модели стекирования являются идеальным инструментом.

Попробуем теперь посмотреть на работу ансамблевых алгоритмов. Возьмем данные, которые содержат сводную статистику с 2015 по 2020 год по мировому счастью и восприятию коррупции. Индекс коррупции представляет собой оценку от 0 (максимальный уровень коррупции) до 100 (отсутствие коррупции). Данный набор содержит такие характеристики как: страна, индекс счастья (оценка от 0 до 10), ВВП на душу населения, семья, здоровье, щедрость, доверие правительству, остаточная дистопия, континент, год, социальная поддержка, индекс коррупции. Попробуем настроить базовые (метод линейной регрессии, случайный лес) и ансамблевые (бэггинг и стекикнг) модели машинного обучения для предсказания индекса коррупции. 

import pandas as pd

import numpy as np

data_corruption = pd.read_csv('WorldHappiness_Corruption.csv')

data_corruption

Еще немного посмотрим на наш набор данных и будем настраивать алгоритмы машинного обучения

X =data_corruption.drop(['Country','continent','Year'],axis=1)

import matplotlib.pyplot as plt

import seaborn as sns

%matplotlib inline

sns.scatterplot(x="happiness_score", y ="cpi_score", data = X)

Можно заметить, что чаще все-таки странам с высоким показателем счастья соответствует низкий уровень индекса коррупции, хотя есть и отклонения.

Интересно посмотреть на уровень счастья и восприятие коррупции в России

data_Russia = data_corruption.loc[(data_corruption['Country'] == 'Russia')]

data_Russia

И можно увидеть другие страны, которым соответствуют такие же показатели коррупции.

new_data = data_corruption[data_corruption.cpi_score<30]

new_data.groupby('Country').mean().sort_values("cpi_score",ascending=False).head(10)

Теперь перейдем к настройке наших моделей. Проведем масштабирование нашего набора данных и разделим выборку на обучающую и тестовую

#масштабирование всех данных, кроме столбца cpi_score
from sklearn.preprocessing import RobustScaler
scale = X.iloc[:, :-1]
scale.reset_index()
scaler = RobustScaler()
scale = scaler.fit_transform(scale.to_numpy())
scale = pd.DataFrame (scale, columns = ["happiness_score", "gdp_per_capita", "family", "health", "freedom", "generosity", "gov_trust", "dyst_residual", "social_support"])
X.iloc[:, : -1] = scale
clean_x = X.drop(['cpi_score'], axis= 1)
clean_y = X["cpi_score"].values
# делим выборку на обучающую и тестовую
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(clean_x, clean_y, test_size = 0.3, random_state = 42).

Сначала рассмотрим работу алгоритма линейной регрессии и случайного леса.

#линейная регрессия
from sklearn.linear_model import LinearRegression
metodlin = LinearRegression()
#подгонка модели
metodlin.fit(x_train, y_train)
#случайный лес
from sklearn.ensemble import RandomForestRegressor
tree = DecisionTreeRegressor()
#подгонка модели
tree.fit(x_train,y_train)

Теперь посмотрим на работу ансамблевых алгоритмов. Рассмотрим бэггинг и стеккинг. В библиотеке scikit-learn имеется два метода BaggingClassifier и BaggingRegressor соответственно для классификации данных и для предсказания значений. Аналогично и для стеккинга, имеются методы StackingClassifier и StackingRegressor 

#bagging
from sklearn.ensemble import BaggingRegressor
from sklearn.tree import DecisionTreeRegressor
bagging = BaggingRegressor()
bagging.fit(x_train, y_train)
#стеккинг
from sklearn.ensemble import StackingRegressor
base_estimators = [('Linear', metodlin), ('Bagging DT', bagging),  ('DecisionForest', tree)]
sclf = StackingRegressor(estimators=base_estimators, cv=2)
sclf.fit(x_train, y_train)

Теперь посмотрим на показатели точности, коэффициент l детерминации R_2 и среднюю абсолютную ошибку MAE базовых и ансамблевых алгоритмов. 

maelin =  mean_absolute_error(y_test,metodlin.predict(x_test))
r2lin = r2_score(y_test,metodlin.predict(x_test))
print('Score: [%.5f]'% metodlin.score(x_test,y_test) + '   MAE: [%.5f]' % maelin +'  R_2: [%.5f]'% r2lin)
maetree=  mean_absolute_error(y_test,tree.predict(x_test))
r2tree = r2_score(y_test,tree.predict(x_test))
print('Score: [%.5f]'% tree.score(x_test,y_test) + '   MAE: [%.5f]' % maetree +'  R_2: [%.5f]'% r2tree)
maebagging=  mean_absolute_error(y_test,bagging.predict(x_test))
r2bagging = r2_score(y_test,bagging.predict(x_test))
print('Score: [%.5f]'% bagging.score(x_test,y_test) + '   MAE: [%.5f]' % maebagging +'   R_2: [%.5f]'% r2bagging)
maesclf=  mean_absolute_error(y_test,sclf.predict(x_test))
r2sclf = r2_score(y_test,sclf.predict(x_test))
print('Score: [%.5f]'% sclf.score(x_test,y_test) + '   MAE: [%.5f]' % maesclf +'   R_2: [%.5f]'% r2sclf)

LINEAR:   Score: [0.64440]   MAE: [9.17327]   R_2: [0.64440]
TREE:     Score: [0.69982]   MAE: [7.28788]   R_2: [0.69982]
BAGGING:  Score: [0.80767]   MAE: [6.15455]   R_2: [0.80767]
STACKING: Score: [0.82382]   MAE: [5.80701]   R_2: [0.82382]

Видно, что у ансамблевых алгоритмов точность выше, чем у базовых. Показатели коэффициента детерминации также показывают, что эффективность ансамблевых алгоритмов также выше. Скорее всего, если поработать с различными параметрами алгоритмов, точность можно еще увеличить. 

Стоит заметить, что все-таки для решения задач машинного обучения сначала стоит попробовать применить более простые модели, а если результат не устраивает, тогда переходит к ансамблям.

В заключение хочу пригласить всех желающих на бесплатный урок курса Machine Learning. Advanced, где с руководителем курсов по ML в Otus, Марией Тихоновой, вы обсудите несколько классических подходов к построению рекомендательных систем и реализуете один из них своими руками. А что порекомендует ваша рекомендательная система? Приходите и узнаете!

Комментарии (0)