Pull to refresh

Automatic Relevance Determination или машинное обучение когда данных очень мало

Reading time 4 min
Views 13K

Когда речь заходит про машинное обучение, обычно подразумевают большие объемы данных — миллионы или даже миллиарды транзакций, из которых надо сделать сложный вывод о поведении, интересах или текущем cостоянии пользователя, покупателя или какого-нибудь аппарата (робота, автомобиля, дрона или станка).
Однако в жизни обычного аналитика самой обычной компании много данных встречается нечасто. Скорее даже наоборот — у вас будет мало или очень мало данных — буквально десятки или сотни записей. Но анализ все же нужно провести. Причем не какой попало анализ, а качественный и достоверный.


Зачастую ситуация усугубляется еще и тем, что вы без труда можете нагенерить для каждой записи много признаков (чаще всего добавляют полиномы, разницу с предыдущим значением и значением за прошлый год, one-hot-encoding для категориальных признаков и т.п.). Вот только совсем нелегко разобраться, какие из них действительно полезны, а какие только усложняют модель и увеличивают ошибки вашего прозноза.


Для этого вы можете воспользоваться методами байесовой статистики, например, Automatic Relevance Determination. Это относительно новый метод, предложенный в 1992 Дэвидом Макаем (все началось с его докторской диссертации (PDF)). Предельно краткое, но непонятное изложение метода можно найти в этой PDF-презентации. Понятное, но излишне многословное объяснение можно посмотреть здесь:



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


Посмотрим, как это работает на практике. Итак, у нас есть исходные данные — всего 30 точек (например, данные о 30 магазинах). Причем у каждого магазина по 30 признаков. И ваша задача — создать регрессионную модель (например, предсказать объем продаж по данным о местоположении, формату, торговой площади, конфигурации, численности персонала и другим параметрам магазина).
Строить обычную линейную регрессию в таких условиях будет чистой воды безумием. Давайте еще больше усугубим проблему тем, что лишь 5 признаков на самом деле имеют значение, а остальные — совершенно не отноcящиеся к делу данные.


Таким образом, пусть реальная зависимость представлена формулой Y = w * X + e, где e — случайная нормальная ошибка, а коэффициенты w равны [1, 2, 3, 4, 5, 0, 0, ....,0], то есть только первые пять коэффициентов ненулевые, а признаки с 6-го по 30-й вообще никак не влияют на реальное значение Y. Однако мы этого не знаем. У нас есть только данные — X и Y — а коэффициенты w нам надо рассчитать.


Теперь запустим ARD:


import numpy as np
from sklearn.linear_model import ARDRegression

N = 30

# данные о магазинах (в данном примере случайные)
X = np.random.random(size=(N,N)) * 10 + 1

# реальные коэффициенты [1 2 3 4 5 0 0 ... 0]
w = np.zeros(N)
w[:5] = np.arange(5) + 1

# добавим случайную ошибку
e = np.random.normal(0, 1, size=N)

# данные о продажах
Y = np.dot(X, w) + e

ard = ARDRegression()
ard.fit(X, Y)

print ard.coef_

И получаем просто впечатляющий результат:


array([ 1.01,  2.14,  2.95,  3.89,  4.79,  0.,  0.,  0.,   0.,  0.01,  
        0.,    0.,    0.31,  0.04, -0.05,  0. , 0.,  0.01, 0.,  0.,  
        0.,    0.,    0.01,  0.,    0.,    0.,  0.,  0.17, 0.,  0.  ])

Напомню, что реальные коэффициенты равны:


array([ 1.,  2.,  3.,  4.,  5.,  0.,  0., 0.,  0., 0.,
        0.,  0.,  0.,  0.,  0., 0.,  0.,  0.,  0., 0.,
        0.,  0.,  0.,  0.,  0., 0.,  0.,  0.,  0., 0. ])

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


Для сравнения приведу коэффициенты, рассчитанные с помощью обычной линейной регрессии:


array([ 0.39  2.07  3.16  2.86  4.8  -0.21 -0.13  0.42  0.6  -0.21 
       -0.96  0.03 -0.46  0.57  0.89  0.15  0.24  0.11 -0.38 -0.36 
       -0.28 -0.01  0.43 -1.22  0.23  0.15  0.12  0.43 -1.11 -0.3 ])

линейной регрессии с L2-регуляризацией:


array([-0.36  1.48  2.67  3.44  3.99 -0.4   1.01  0.58 -0.81  0.78
       -0.13 -0.23 -0.26 -0.24 -0.38 -0.24 -0.38 -0.25  0.54 -0.31 
       -0.21 -0.42  0.14  0.88  1.09  0.66  0.12 -0.07  0.08 -0.58])

И они обе не выдерживают никакой критики.


А вот линейная регрессия с L1-регуляризацией дает похожий результат:


array([ 0.68  1.9   2.88  3.86  4.88 -0.05  0.09  0.   0.    0. 
        0.    0.    0.    0.    0.    0.    0.    0.   0.    0. 
        0.    0.    0.01  0.    0.    0.    0.    0.   0.    0.  ])

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


В общем, ARD — метод замечательный, но есть нюанс. Как и многие (можно даже сказать, почти все) байесовы методы, ARD чрезвычайно сложен с вычислительной точки зрения (хотя и хорошо параллелится). Поэтому на данных объемом несколько десятков-сотен точек он работает быстро (доли секунды), на нескольких тысячах — медленно (десятки-сотни секунд), а на десятках и сотнях тысяч — о-о-о-очень медленно (минуты и часы). Кроме того, ему необходим огромный объем оперативной памяти.


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


ARD активно применяется в разнообразных kernel-методах, например, Relevance Vector Machine (RVM) — это Support Vector Machine (SVM) вместе с ARD. Также он удобен в классификаторах, когда вам необходимо оценить значимость имеющихся признаков. В общем, попробуйте — и вам понравится.

Tags:
Hubs:
+24
Comments 23
Comments Comments 23

Articles