#featureselection #diogenes
Тестирую сейчас Диогена в контролируемом эксперименте. Несмотря на ожидания, RFECV звёзд с неба не хватает: некоторые значимые группы факторов "уплывают" из зоны видимости, без шансов выйти в топ. Думаю про альтернативу, ну или как минимум предварительный шаг: просчитывать важности признаков на случайных подгруппах случайных размеров, а не просто на всех доступных одним разом.
UPD. Кстати, эксперименты на подгруппах открыли интересный факт: важности признаков катбуста могут совершенно не отражать реальный вклад факторов в результат. Пример в комментах.
Тестирую сейчас Диогена в контролируемом эксперименте. Несмотря на ожидания, RFECV звёзд с неба не хватает: некоторые значимые группы факторов "уплывают" из зоны видимости, без шансов выйти в топ. Думаю про альтернативу, ну или как минимум предварительный шаг: просчитывать важности признаков на случайных подгруппах случайных размеров, а не просто на всех доступных одним разом.
UPD. Кстати, эксперименты на подгруппах открыли интересный факт: важности признаков катбуста могут совершенно не отражать реальный вклад факторов в результат. Пример в комментах.
#featureselection
Недавно я проводил опрос, нужен ли вообще отбор признаков, если есть современные мощные бустинги. Большая часть аудитории сказала, что нет, и этим не занимается.
Вот вам пример: 246 фичей, из них на таргет влияют 11. Результаты (mean_cv_score, std_cv_score) MSE с 5-фолдовой кросс-валидацией для всех фичей и только для важных фичей показывают ОГРОМНУЮ разницу (0.0219 vs 0.0145, при dummy=0.0278). По сути, наличие/отсутствие FS может быть причиной успеха/провала проекта. Порядок разницы одинаковый для Catboost и Xgboost, кстати.
Недавно я проводил опрос, нужен ли вообще отбор признаков, если есть современные мощные бустинги. Большая часть аудитории сказала, что нет, и этим не занимается.
Вот вам пример: 246 фичей, из них на таргет влияют 11. Результаты (mean_cv_score, std_cv_score) MSE с 5-фолдовой кросс-валидацией для всех фичей и только для важных фичей показывают ОГРОМНУЮ разницу (0.0219 vs 0.0145, при dummy=0.0278). По сути, наличие/отсутствие FS может быть причиной успеха/провала проекта. Порядок разницы одинаковый для Catboost и Xgboost, кстати.
#diogenes #featureselection #rfecv #mrmr
Ну и немного новостей по проекту Диоген. Собрал и потестировал на синтетике 2 полноценных отборщика признаков, filter & wrapper. мой улучшенный RFECV отлично отработал на датасете с 250+ факторами, 11k записями: из 11 значимых факторов нашёл 9, причём и нелинейные, и 2-way XOR, и 3-way XOR. Не смог найти 2 фактора с частичной зависимостью (на 10% и 30% области определения). Ну я не сильно расстроился, найди он и это на 11k записей, это было бы чудом. При росте числа записей находит и их. Что выяснилось: промежуточные модельки надо фиттить прям до упора (насколько ES позволяет).
И, кажется, оправдалась моя идея, что важности признаков надо складировать со всех запусков, а не только с самого первого. Оптимизатор мой MBHO отлично отработал - сократил время поиска вдвое. В общем, не зря пилил этот проект полгода.
В то же время, MRMR находит только 6 важных признаков из 11. Но время работы, Карл! 2 часа RFECV против 2 минут MRMR.
Мне уже стало казаться, что в бою на больших данных RFECV ну просто будет неприменим по времени. Начал тестировать на реальном датасете с 500+ столбцов общим размером 50Гб. Подождал часов 6 на сервере с 16 ядрами, за это время не обучилась полностью даже 1я FS моделька, махнул рукой. Придётся переносить тесты RFECV на GPU сервер с приличным объёмом VRAM.
Перешёл к тестированию MRMR. Тут тоже в реальности не всё гладко оказалось, биннинг датасета, который на небольшой синтетике шёл 2 секунды на 1 ядре, в реальном проекте растянулся на полчаса. Пришлось переписывать под многопоток, заодно улучшил работу с пропусками и отловил пару багов. Биннинг стал отрабатывать за 2 минуты. И снова сюрприз, который отнял полдня. Оказалось, что np.random.shuffle в многопотоке ужасно тормозит, пришлось оборачивать его в njit.
В итоге тестирую MRMR с полной загрузкой CPU на финансовом проекте, очень интересно смотреть в реальном времени, что он находит.
Ну и немного новостей по проекту Диоген. Собрал и потестировал на синтетике 2 полноценных отборщика признаков, filter & wrapper. мой улучшенный RFECV отлично отработал на датасете с 250+ факторами, 11k записями: из 11 значимых факторов нашёл 9, причём и нелинейные, и 2-way XOR, и 3-way XOR. Не смог найти 2 фактора с частичной зависимостью (на 10% и 30% области определения). Ну я не сильно расстроился, найди он и это на 11k записей, это было бы чудом. При росте числа записей находит и их. Что выяснилось: промежуточные модельки надо фиттить прям до упора (насколько ES позволяет).
И, кажется, оправдалась моя идея, что важности признаков надо складировать со всех запусков, а не только с самого первого. Оптимизатор мой MBHO отлично отработал - сократил время поиска вдвое. В общем, не зря пилил этот проект полгода.
В то же время, MRMR находит только 6 важных признаков из 11. Но время работы, Карл! 2 часа RFECV против 2 минут MRMR.
Мне уже стало казаться, что в бою на больших данных RFECV ну просто будет неприменим по времени. Начал тестировать на реальном датасете с 500+ столбцов общим размером 50Гб. Подождал часов 6 на сервере с 16 ядрами, за это время не обучилась полностью даже 1я FS моделька, махнул рукой. Придётся переносить тесты RFECV на GPU сервер с приличным объёмом VRAM.
Перешёл к тестированию MRMR. Тут тоже в реальности не всё гладко оказалось, биннинг датасета, который на небольшой синтетике шёл 2 секунды на 1 ядре, в реальном проекте растянулся на полчаса. Пришлось переписывать под многопоток, заодно улучшил работу с пропусками и отловил пару багов. Биннинг стал отрабатывать за 2 минуты. И снова сюрприз, который отнял полдня. Оказалось, что np.random.shuffle в многопотоке ужасно тормозит, пришлось оборачивать его в njit.
В итоге тестирую MRMR с полной загрузкой CPU на финансовом проекте, очень интересно смотреть в реальном времени, что он находит.
#autofeat #featureselection #featureselection
Как работает autofeat:
1) берётся подвыборка train set, из сырых фичей генерируется много кандидатов (с помощью простых математических операций)
2) в пул "хороших" добавляются кандидаты с высокой корреляцией с необъяснённым таргетом
3) на всех "хороших" кандидатах обучается линейная модель с регуляризацией LassoLarsCV. Отбрасываются кандидаты с низкими весами в последней модели. Пересчитывается таргет, не объясняемый моделью.
4) повтор цикла до стабилизации множества хороших кандидатов
5) отсев шума. обучение на итоговом пуле+случайных признаках, отбрасываем всех кандидатов с весами, меньшими весов шумовых фичей
Как работает autofeat:
1) берётся подвыборка train set, из сырых фичей генерируется много кандидатов (с помощью простых математических операций)
2) в пул "хороших" добавляются кандидаты с высокой корреляцией с необъяснённым таргетом
3) на всех "хороших" кандидатах обучается линейная модель с регуляризацией LassoLarsCV. Отбрасываются кандидаты с низкими весами в последней модели. Пересчитывается таргет, не объясняемый моделью.
4) повтор цикла до стабилизации множества хороших кандидатов
5) отсев шума. обучение на итоговом пуле+случайных признаках, отбрасываем всех кандидатов с весами, меньшими весов шумовых фичей
#featureselection #diogenes #clusteredfs
Задумался о модификации MRMR в свете коррелированных признаков.
Сейчас Диоген избыточные признаки просто отсеивает. Но представим себе такую ситуацию: истинный влияющий фактор вне выборки, до нас дошли только несколько его "отражений" A,B, C... каждое со своим случайным шумом. По факту, мы сейчас выбираем одно самое похожее отражение D, а остальные выкидываем. А это же нерационально. Не лучше ли брать вместо D, к примеру, mean(A,B,C,...)? Идея в том, что случайные шумы отменяют друг друга, а сигнал усиливается (как и обычно при ансамблировании).
О подходе к FS, когда несколько коррелированных факторов заменяются кластером, рассказывал Эрни Чан. Правда, почему-то этого не было в его статье.
В общем, буду делать. Как минимум будет нелишней такая опция.
Задумался о модификации MRMR в свете коррелированных признаков.
Сейчас Диоген избыточные признаки просто отсеивает. Но представим себе такую ситуацию: истинный влияющий фактор вне выборки, до нас дошли только несколько его "отражений" A,B, C... каждое со своим случайным шумом. По факту, мы сейчас выбираем одно самое похожее отражение D, а остальные выкидываем. А это же нерационально. Не лучше ли брать вместо D, к примеру, mean(A,B,C,...)? Идея в том, что случайные шумы отменяют друг друга, а сигнал усиливается (как и обычно при ансамблировании).
О подходе к FS, когда несколько коррелированных факторов заменяются кластером, рассказывал Эрни Чан. Правда, почему-то этого не было в его статье.
В общем, буду делать. Как минимум будет нелишней такая опция.
#featureselection #diogenes
в модуле filters Диогена уже 3k строчек кода. хотя вроде идеи основные такие простые и элегантные.
в модуле filters Диогена уже 3k строчек кода. хотя вроде идеи основные такие простые и элегантные.
#featureengineering #featureselection #diogenes
2024-03-02 05:39:17,484 - INFO - screen_predictors-line:1524 - Starting work with full_npermutations=10, min_nonzero_confidence=0.99000, max_failed=1
2024-03-02 05:39:49,214 - INFO - fit-line:2750 - MRMR selected 4 out of 5 features: [{'name': 'a', 'indices': (0,), 'gain': 0.33220730396336595, 'confidence': 1.0}, {'name': 'b', 'indices': (1,), 'gain': 0.5405325314273686, 'confidence': 1.0}, {'name': 'c', 'indices': (2,), 'gain': 0.20641517193369197, 'confidence': 1.0}, {'name': 'd', 'indices': (3,), 'gain': 0.07414164383695354, 'confidence': 1.0}]
2024-03-02 05:40:34,762 - INFO - fit-line:2983 - mul(log(c),sin(d)) is recommended to use as a new feature!
2024-03-02 05:42:12,619 - INFO - fit-line:2983 - mul(squared(a),reciproc(b)) is recommended to use as a new feature!
time: 3min 7s (started: 2024-03-02 05:39:05 +03:00)
Как тебе такое, Франциска Хорн? )
n =100_000
a = np.random.rand(n)
b = np.random.rand(n)
c = np.random.rand(n)
d = np.random.rand(n)
e = np.random.rand(n)
f = np.random.rand(n)
y=a**2/b+f/5+np.log(c)*np.sin(d)
df = pd.DataFrame(
{
"a": a,
"b": b,
"c": c,
"d": d,
"e": e,
}
)
from mlframe.feature_selection.filters import MRMR
fs=MRMR(full_npermutations=10,baseline_npermutations=20,verbose=1,n_workers=1,parallel_kwargs=dict(temp_folder=r"R:\Temp"),)
fs.fit(X=df,y=y)
2024-03-02 05:39:17,484 - INFO - screen_predictors-line:1524 - Starting work with full_npermutations=10, min_nonzero_confidence=0.99000, max_failed=1
2024-03-02 05:39:49,214 - INFO - fit-line:2750 - MRMR selected 4 out of 5 features: [{'name': 'a', 'indices': (0,), 'gain': 0.33220730396336595, 'confidence': 1.0}, {'name': 'b', 'indices': (1,), 'gain': 0.5405325314273686, 'confidence': 1.0}, {'name': 'c', 'indices': (2,), 'gain': 0.20641517193369197, 'confidence': 1.0}, {'name': 'd', 'indices': (3,), 'gain': 0.07414164383695354, 'confidence': 1.0}]
2024-03-02 05:40:34,762 - INFO - fit-line:2983 - mul(log(c),sin(d)) is recommended to use as a new feature!
2024-03-02 05:42:12,619 - INFO - fit-line:2983 - mul(squared(a),reciproc(b)) is recommended to use as a new feature!
time: 3min 7s (started: 2024-03-02 05:39:05 +03:00)
Как тебе такое, Франциска Хорн? )
#featureengineering #featureselection #autofeat
time: 5min 23s (started: 2024-03-02 06:07:07 +03:00)
Эмм.. А можно мне другой отборщик признаков? )
from autofeat import AutoFeatRegressor
model = AutoFeatRegressor(transformations = ('1/', 'exp', 'log', 'sin', 'sqrt', '^2', '^3'),featsel_runs=15)
new_df = model.fit_transform(df, y)
time: 5min 23s (started: 2024-03-02 06:07:07 +03:00)
Эмм.. А можно мне другой отборщик признаков? )
#featureengineering #featureselection #diogenes
Хорошие новости!
Как уже поняли читатели моего блога, в библиотеке отбора признаков Диоген появился также и модуль инженерии/конструирования новых признаков, но не бездумного, как в autofeat, а направленного, на основании теоретико-информационных метрик (в основном, взаимной информации MI комбинаций факторов с таргетом).
Основной мотивацией была попытка выделить рациональное зерно из набивших оскомину унылых рекомендаций и бубнежа вида "также иногда помогает логарифмирование, экспоненциирование, извлечение корней, попарное перемножение или деление исходных факторов". Эти рекомендации регулярно встречаются в курсах по FE и презентациях кэгглеров, но непонятно, как к этому вообще подступаться, кроме разве что каких-то случайных выпадов. Ну вот есть у меня 10k оригинальных признаков, мне взаимные отношения или произведения у каких именно из 50M пар проверять?
А так как метод MRMR в Диогене как раз и определяет достаточно хорошее в смысле предиктивности и уникальности подмножество признаков, некоторая проверка комбинаций становится уже реальной. Ещё больше пространство поиска сужает эвристика, что MI от "хорошей" на предмет тесной нелинейной связи пары признаков должна быть выше суммы индивидуальных MI факторов пары.
Это уже позволяет брать любые известные классы функций и для пары признаков a,b пытаться подбирать (в рамках бюджета) F3(F1(a),F2(b)) дающие максимальную MI с таргетом. В некоторых простых случаях этот метод срабатывает на ура, результаты я показывал выше. Но, если истинная зависимость сильно искажает вход ДО передачи в нелинейную функцию, метод становится практически бессилен и связь не обнаруживается.
Алексей @introspec предложил очень классную идею: почему бы не заменить подбор функций, сходимость которого дело скорее удачи, подбором коэффициентов ортогональных многочленов (например, Эрмитовых), теоретически умеющих аппроксимировать любую функциональную зависимость на отрезке? Взяв степень пониже, и коэффициенты поближе к 0, можно обеспечить своего рода регуляризацию.
Я попробовал пару дней тому заменить случайный поиск в пространстве функций на почти настолько же случайный поиск в пространстве коэффициентов Эрмитовых полиномов, но поставил вариацию на паузу из-за того, что не находились достаточно хорошие решения.
Теперь, собственно, к новостям )
Потестил свой модуль с разными исходными зависимостями, немного прояснил чувствительность и границы применимости метода. Пофиксил баги.
И... Заменил случайный перебор Эрмитовых полиномов на направленную оптимизацию с помощью Optuna )
Решения явно стали находиться получше за разумное время, иногда по качеству не уступают "нативным", когда зависимость известна. Нужно больше тестов. И, самое главное, предстоит выяснить, дают ли такие необычные преобразования реальные преимущества в ML метриках, или же ведут к оверфиту.
Хорошие новости!
Как уже поняли читатели моего блога, в библиотеке отбора признаков Диоген появился также и модуль инженерии/конструирования новых признаков, но не бездумного, как в autofeat, а направленного, на основании теоретико-информационных метрик (в основном, взаимной информации MI комбинаций факторов с таргетом).
Основной мотивацией была попытка выделить рациональное зерно из набивших оскомину унылых рекомендаций и бубнежа вида "также иногда помогает логарифмирование, экспоненциирование, извлечение корней, попарное перемножение или деление исходных факторов". Эти рекомендации регулярно встречаются в курсах по FE и презентациях кэгглеров, но непонятно, как к этому вообще подступаться, кроме разве что каких-то случайных выпадов. Ну вот есть у меня 10k оригинальных признаков, мне взаимные отношения или произведения у каких именно из 50M пар проверять?
А так как метод MRMR в Диогене как раз и определяет достаточно хорошее в смысле предиктивности и уникальности подмножество признаков, некоторая проверка комбинаций становится уже реальной. Ещё больше пространство поиска сужает эвристика, что MI от "хорошей" на предмет тесной нелинейной связи пары признаков должна быть выше суммы индивидуальных MI факторов пары.
Это уже позволяет брать любые известные классы функций и для пары признаков a,b пытаться подбирать (в рамках бюджета) F3(F1(a),F2(b)) дающие максимальную MI с таргетом. В некоторых простых случаях этот метод срабатывает на ура, результаты я показывал выше. Но, если истинная зависимость сильно искажает вход ДО передачи в нелинейную функцию, метод становится практически бессилен и связь не обнаруживается.
Алексей @introspec предложил очень классную идею: почему бы не заменить подбор функций, сходимость которого дело скорее удачи, подбором коэффициентов ортогональных многочленов (например, Эрмитовых), теоретически умеющих аппроксимировать любую функциональную зависимость на отрезке? Взяв степень пониже, и коэффициенты поближе к 0, можно обеспечить своего рода регуляризацию.
Я попробовал пару дней тому заменить случайный поиск в пространстве функций на почти настолько же случайный поиск в пространстве коэффициентов Эрмитовых полиномов, но поставил вариацию на паузу из-за того, что не находились достаточно хорошие решения.
Теперь, собственно, к новостям )
Потестил свой модуль с разными исходными зависимостями, немного прояснил чувствительность и границы применимости метода. Пофиксил баги.
И... Заменил случайный перебор Эрмитовых полиномов на направленную оптимизацию с помощью Optuna )
Решения явно стали находиться получше за разумное время, иногда по качеству не уступают "нативным", когда зависимость известна. Нужно больше тестов. И, самое главное, предстоит выяснить, дают ли такие необычные преобразования реальные преимущества в ML метриках, или же ведут к оверфиту.
#featureselection #diogenes #rfecv
Вот так работает обратное удаление признаков в Диогене, кстати, в реальном проекте уже.
Вот так работает обратное удаление признаков в Диогене, кстати, в реальном проекте уже.
#featureselection #kuhn
Читаю по рекомендации товарища книжку по ML. В главе по FS есть задание, мимо которого не смог пройти ) Надо будет потестить на нём Диогена. А возьмётся кто-то из читателей потестить на этом примере алгоритмы sklearn/mlxtend?
Читаю по рекомендации товарища книжку по ML. В главе по FS есть задание, мимо которого не смог пройти ) Надо будет потестить на нём Диогена. А возьмётся кто-то из читателей потестить на этом примере алгоритмы sklearn/mlxtend?
#news #automl #plans
ML/DS-планы на 2024-й.
Как-то незаметно прошло уже почти полгода! Поймал себя на том, что двигаюсь к своей мини-automl системе. Скажете, почему не возьмёшь готовую? Ответ обычный, хочешь чтоб было сделано хорошо - сделай сам (если у тебя есть экспертиза и классные идеи).
В рамках этой automl системы будут:
1) 2 отборщика признаков из Diogenes, MRMR и RFECV.
MRMR уже получил навык создания комбинаций признаков (feature engineering), его надо ускорить (запараллелить) и лучше потестировать подмодуль с ортогональными полиномами (там будет полезен хороший оптимизатор, сейчас стоит оптуна и работает через пень-колоду)
2) мой будущий классный MBHO оптимизатор HPT. мне уже удалось побить оптуну, гиперопт, скопт в задачах одномерной оптимизации (для решения проблемы feature selection, см бенчи по тегам #featureselection #hpt #optuna #hyperopt #skopt), пора его расширить на многомерный случай
3) модуль ансамблирования ENS. будет простое усреднение (много оттенков) и стэкинг. из ноу-хау тут будут instance-based confidence, numaggs over level 0 predictions, identity level 1 baseline, аугментация табличных данных. Для расширения ENS планируется написать универсальную обёртку для ранней остановки. С этой идеей ношусь уже несколько лет, да никак не сделаю. Смысл обёртки в том, чтобы дать функционал early stopping/overfitting detection тем моделькам, которые сами нативно его не поддерживают - путём partial_fit или дихотомического поиска по n_iterations.
Отборщики признаков получат апгрейд и во время своей работы будут собирать ценную информацию для модулей HPT (MRMR считает базовые статистики признаков, силу связей с таргетами и между собой; RFECV создаёт пары гиперпараметры-ml метрики для последующего обучения MBHO) и ENS (будут замерять, насколько прогнозы моделек с определёнными признаками и гиперпараметрами декоррелированы и спосбны помочь ансамблю).
Также планируется большое обновление Diogenes, после которого избыточные признаки опционально будут не удаляться из набора, а сливаться в единый "кластер" c primary (если это будет повышать стабильность). Идея взята из лекций Эрни Чана. Это может быть полезно, когда 1 скрытый драйвер влияет на множество факторов в датасете. Текущая реализация MRMR выбирает 1 фактор с самой сильной MI на таргет, остальные выкидывает, что приводит к потере информации если влияние драйвера на факторы неоднородно по инстансам или времени.
Ещё MRMR получит шаг удаления признака (чтобы сильный признак мог всё же уступать более удачной комбинации) и параллельные списки, когда на каждом шаге не просто берётся лучший кандидат, а N лучших кандидатов формируют "параллельную реальность" (идея взята у Тима Мастерса).
Хочу также изучить гибриды между MRMR и RFECV (например, все признаки отброшенные MRMR прогонять через RFECV).
ML/DS-планы на 2024-й.
Как-то незаметно прошло уже почти полгода! Поймал себя на том, что двигаюсь к своей мини-automl системе. Скажете, почему не возьмёшь готовую? Ответ обычный, хочешь чтоб было сделано хорошо - сделай сам (если у тебя есть экспертиза и классные идеи).
В рамках этой automl системы будут:
1) 2 отборщика признаков из Diogenes, MRMR и RFECV.
MRMR уже получил навык создания комбинаций признаков (feature engineering), его надо ускорить (запараллелить) и лучше потестировать подмодуль с ортогональными полиномами (там будет полезен хороший оптимизатор, сейчас стоит оптуна и работает через пень-колоду)
2) мой будущий классный MBHO оптимизатор HPT. мне уже удалось побить оптуну, гиперопт, скопт в задачах одномерной оптимизации (для решения проблемы feature selection, см бенчи по тегам #featureselection #hpt #optuna #hyperopt #skopt), пора его расширить на многомерный случай
3) модуль ансамблирования ENS. будет простое усреднение (много оттенков) и стэкинг. из ноу-хау тут будут instance-based confidence, numaggs over level 0 predictions, identity level 1 baseline, аугментация табличных данных. Для расширения ENS планируется написать универсальную обёртку для ранней остановки. С этой идеей ношусь уже несколько лет, да никак не сделаю. Смысл обёртки в том, чтобы дать функционал early stopping/overfitting detection тем моделькам, которые сами нативно его не поддерживают - путём partial_fit или дихотомического поиска по n_iterations.
Отборщики признаков получат апгрейд и во время своей работы будут собирать ценную информацию для модулей HPT (MRMR считает базовые статистики признаков, силу связей с таргетами и между собой; RFECV создаёт пары гиперпараметры-ml метрики для последующего обучения MBHO) и ENS (будут замерять, насколько прогнозы моделек с определёнными признаками и гиперпараметрами декоррелированы и спосбны помочь ансамблю).
Также планируется большое обновление Diogenes, после которого избыточные признаки опционально будут не удаляться из набора, а сливаться в единый "кластер" c primary (если это будет повышать стабильность). Идея взята из лекций Эрни Чана. Это может быть полезно, когда 1 скрытый драйвер влияет на множество факторов в датасете. Текущая реализация MRMR выбирает 1 фактор с самой сильной MI на таргет, остальные выкидывает, что приводит к потере информации если влияние драйвера на факторы неоднородно по инстансам или времени.
Ещё MRMR получит шаг удаления признака (чтобы сильный признак мог всё же уступать более удачной комбинации) и параллельные списки, когда на каждом шаге не просто берётся лучший кандидат, а N лучших кандидатов формируют "параллельную реальность" (идея взята у Тима Мастерса).
Хочу также изучить гибриды между MRMR и RFECV (например, все признаки отброшенные MRMR прогонять через RFECV).
#featureselection
Классная идея применения коэффициентов Шэпли для отбора признаков!
Задача FS вообще NP-сложная и сводится к выбору оптимального значения бинарного вектора длины n_features (n_features это количество признаков-кандидатов в исходной выборке). Строго говоря, для её точного решения нужно оценить OOS-метрики моделей, обученных на всех возможных сочетаниях признаков от 1 до n_features (2^n_features комбинаций).
Автор же показывает, как, используя свойство аддитивности индивидуальных shap values признаков, можно заменить дорогое обучение модели и выдачу прогноза на комбинации признаков на... просто суммирование shap values этих признаков в большой модели (обученной один раз на всех признаках).
Понятно, что это будет лишь аппроксимацией прогнозов реальной модели, честно (и долго) обученной именно на нужной комбинации признаков, но автор на множестве датасетов оценил точность этой аппроксимации, и её ранжирующие свойства оказались высоки.
PS. Тут надо провести дописследование. Как бы не вытащить себя самих за волосы из болота, как известный барон )
А вообще, конечно, сразу приходят в голову возможные улучшения для этого подхода:
1) обучать вместо одной N больших моделей (с разными HPT и вообще разными алгоритмами
2) обучать вместо одной большой модели на всех признаках M моделей на случайной части 1/M от всех признаков. Потом при оценке комбинаций, полностью попадающих в бакет i=1..M, брать не общую модель, а более конкретную i (ну или взвешенное среднее).
3) комбинация 1 и 2
4) а точно ли не нужно никакое масштабирование частичных сумм значений Шэпли?
Если эта идея рабочая, она позволит расширить область применения полного перебора (а это самый точный метод FS) с 5 (32 честные комбинации) до примерно 40 факторов (1.1 трлн аппроксимированных комбинаций).
Ну и, практически говоря, это поможет и в частичном переборе. Например, получили мы какой-то перспективный список предикторов - от эксперта, RFECV, или как-то ещё. Ну и берём 20-30-40 лучших признаков из списка, насколько потянет железо, и применяем полный аппроксимированный перебор уже к этому сокращённому списку. Профит? Профит.
Посоветовался с чат гпт, после нескольких пинков она даже сама распознала, что
Using SHAP values to approximate the predictions of models trained on specific subsets of features is an innovative approach. The idea is to use the contributions of individual features (as captured by SHAP values) to estimate the predictions of a model that would have been trained on a subset of those features.
Предложила использовать среднее сумм shap values предикторов-кандидатов для коррекции base value, и Interaction-aware SHAP Values.
Через год что, эти чёртовы языковые модели нас полностью превзойдут уже и в научной креативности? )
https://towardsdatascience.com/approximate-predictions-make-feature-selection-radically-faster-0f9664877687
Классная идея применения коэффициентов Шэпли для отбора признаков!
Задача FS вообще NP-сложная и сводится к выбору оптимального значения бинарного вектора длины n_features (n_features это количество признаков-кандидатов в исходной выборке). Строго говоря, для её точного решения нужно оценить OOS-метрики моделей, обученных на всех возможных сочетаниях признаков от 1 до n_features (2^n_features комбинаций).
Автор же показывает, как, используя свойство аддитивности индивидуальных shap values признаков, можно заменить дорогое обучение модели и выдачу прогноза на комбинации признаков на... просто суммирование shap values этих признаков в большой модели (обученной один раз на всех признаках).
Понятно, что это будет лишь аппроксимацией прогнозов реальной модели, честно (и долго) обученной именно на нужной комбинации признаков, но автор на множестве датасетов оценил точность этой аппроксимации, и её ранжирующие свойства оказались высоки.
PS. Тут надо провести дописследование. Как бы не вытащить себя самих за волосы из болота, как известный барон )
А вообще, конечно, сразу приходят в голову возможные улучшения для этого подхода:
1) обучать вместо одной N больших моделей (с разными HPT и вообще разными алгоритмами
2) обучать вместо одной большой модели на всех признаках M моделей на случайной части 1/M от всех признаков. Потом при оценке комбинаций, полностью попадающих в бакет i=1..M, брать не общую модель, а более конкретную i (ну или взвешенное среднее).
3) комбинация 1 и 2
4) а точно ли не нужно никакое масштабирование частичных сумм значений Шэпли?
Если эта идея рабочая, она позволит расширить область применения полного перебора (а это самый точный метод FS) с 5 (32 честные комбинации) до примерно 40 факторов (1.1 трлн аппроксимированных комбинаций).
Ну и, практически говоря, это поможет и в частичном переборе. Например, получили мы какой-то перспективный список предикторов - от эксперта, RFECV, или как-то ещё. Ну и берём 20-30-40 лучших признаков из списка, насколько потянет железо, и применяем полный аппроксимированный перебор уже к этому сокращённому списку. Профит? Профит.
Посоветовался с чат гпт, после нескольких пинков она даже сама распознала, что
Using SHAP values to approximate the predictions of models trained on specific subsets of features is an innovative approach. The idea is to use the contributions of individual features (as captured by SHAP values) to estimate the predictions of a model that would have been trained on a subset of those features.
Предложила использовать среднее сумм shap values предикторов-кандидатов для коррекции base value, и Interaction-aware SHAP Values.
Через год что, эти чёртовы языковые модели нас полностью превзойдут уже и в научной креативности? )
https://towardsdatascience.com/approximate-predictions-make-feature-selection-radically-faster-0f9664877687
Medium
“Approximate-Predictions” Make Feature Selection Radically Faster
Feature selection is so slow because it requires the creation of many models. Find out how to make it blazingly faster thanks to…
#featureselection
Подобрался к более детальной проверке идеи из этого поста. Результаты поистине изумительные.
Как мы и знали раньше (из оригинального исследования автора, + моей проверки), корреляция "аппроксимированных предсказаний" и "честных предсказаний", хотя иногда и поднимается выше 90% (если количество признаков-кандидатов близко к полному количеству признаков), в среднем звёзд с неба не хватает.
Я взял датасет poker из pycaret, т.к. там достаточно наблюдений (100k), и дополнительно к к-ту корреляции посчитал RMSE честных и аппроксимированных предсказаний. Выяснился печальный факт, что RMSE просто среднего таргета по выборке (dummy) зачастую побеждает авторский способ оценки (naive).
Я расстроился, но, помня красивые графики автора, всё-таки посчитал реальные ошибки ground truth vs naive predictions, а уже от них NDCG в разрезе наборов признаков-кандидатов.
И был просто шокирован.
ndcg(naive_opt_fin_rmse)=0.99995 по 50 наборам признаков-кандидатов с числом признаков от 1 до 9 (всего в датасете их 10).
То есть, из Shap-значений нельзя вытащить прям точные аппроксимации честных прогнозов (слишком высокая RMSE). Но и не надо: даже эти аппроксимации позволяют с высокой точностью ранжировать наборы признаков-кандидатов (удивительно высокий NDCG).
Почему? Загадка. Видимо, движения "в нужном направлении" достаточно для точного ранжирования, и это важнее, чем абсолютная величина совпадения прогнозов. Здесь, похоже, действуют какие-то тонкие математические эффекты, которых я не понимаю. Но эта идея реально работает.
На датасете poker "честное переобучение" модельки занимает у меня 8 секунд, а оценка авторским методом 0,005 секунд. Ускорение в 1500+ раз при 0.99995 условной точности ранжирования.
"Условной", потому что на больших списках ndcg становится "логарифмически нечувствительным" к хорошему ранжированию. Например, случайное ранжирование в этой же задаче (с теми же релевантностями) на списке размером 50 выдаёт NDCG=0.987.
Если же отказаться от абсолютной шкалы целевой ML-метрики, и в качестве релевантностей использовать целые числа [1,2,..,N], NDCG случайного ранжирования становится в среднем 0,827, а NDCG авторского ранжирования 0,968. Ну то есть, это прекрасный значимый результат.
Подобрался к более детальной проверке идеи из этого поста. Результаты поистине изумительные.
Как мы и знали раньше (из оригинального исследования автора, + моей проверки), корреляция "аппроксимированных предсказаний" и "честных предсказаний", хотя иногда и поднимается выше 90% (если количество признаков-кандидатов близко к полному количеству признаков), в среднем звёзд с неба не хватает.
Я взял датасет poker из pycaret, т.к. там достаточно наблюдений (100k), и дополнительно к к-ту корреляции посчитал RMSE честных и аппроксимированных предсказаний. Выяснился печальный факт, что RMSE просто среднего таргета по выборке (dummy) зачастую побеждает авторский способ оценки (naive).
Я расстроился, но, помня красивые графики автора, всё-таки посчитал реальные ошибки ground truth vs naive predictions, а уже от них NDCG в разрезе наборов признаков-кандидатов.
И был просто шокирован.
ndcg(naive_opt_fin_rmse)=0.99995 по 50 наборам признаков-кандидатов с числом признаков от 1 до 9 (всего в датасете их 10).
То есть, из Shap-значений нельзя вытащить прям точные аппроксимации честных прогнозов (слишком высокая RMSE). Но и не надо: даже эти аппроксимации позволяют с высокой точностью ранжировать наборы признаков-кандидатов (удивительно высокий NDCG).
Почему? Загадка. Видимо, движения "в нужном направлении" достаточно для точного ранжирования, и это важнее, чем абсолютная величина совпадения прогнозов. Здесь, похоже, действуют какие-то тонкие математические эффекты, которых я не понимаю. Но эта идея реально работает.
На датасете poker "честное переобучение" модельки занимает у меня 8 секунд, а оценка авторским методом 0,005 секунд. Ускорение в 1500+ раз при 0.99995 условной точности ранжирования.
"Условной", потому что на больших списках ndcg становится "логарифмически нечувствительным" к хорошему ранжированию. Например, случайное ранжирование в этой же задаче (с теми же релевантностями) на списке размером 50 выдаёт NDCG=0.987.
Если же отказаться от абсолютной шкалы целевой ML-метрики, и в качестве релевантностей использовать целые числа [1,2,..,N], NDCG случайного ранжирования становится в среднем 0,827, а NDCG авторского ранжирования 0,968. Ну то есть, это прекрасный значимый результат.
Telegram
Aspiring Data Science
#featureselection
Классная идея применения коэффициентов Шэпли для отбора признаков!
Задача FS вообще NP-сложная и сводится к выбору оптимального значения бинарного вектора длины n_features (n_features это количество признаков-кандидатов в исходной выборке).…
Классная идея применения коэффициентов Шэпли для отбора признаков!
Задача FS вообще NP-сложная и сводится к выбору оптимального значения бинарного вектора длины n_features (n_features это количество признаков-кандидатов в исходной выборке).…
#featureselection
В дополнение к посту. Потестировал много вариантов улучшения исходной идеи:
1) усреднение значений Шэпли нескольких типов (с разными feature_perturbation)
2) усреднение значений Шэпли нескольких разных моделей
3) использование парных интеракций (shap_interaction_values)
4) мета-модель ML: зная индексы выбранных в комбинацию признаков и оставшихся признаков, а также честные предсказания моделек, давайте попробуем создать как мета-признаки ряд простых числовых агрегатов от шепли-значений (суммы, средние, отклонения, мин/макс и тп). ну и уже от этого мета-модель, вдруг она будет точнее чем исходная простая идея просуммировать значения Шепли выбранных в комбинацию признаков?
Находки/открытия:
1) не существует работающей реализации Shap на GPU (GPUTreeExplainer из пакета shap нерабочий, и всем похер. По идее он должен ставиться с xgboost (без shap), но он всё равно не юзает gpu, я проверял.)
2) KernelExplainer непроходимо медленен, забудьте про его использование. Речь о сотнях часов даже на небольшом датасете.
3) некоторые модели (lightgbm) считают интеракции в один поток и очень медленно (~40 минут на 100k x 20 датасете)
4) некоторые бустинги (Catboost) раздувают expected_value так, что они не просто не сходятся точно к среднему прогнозу, а превышают его вдвое. При этом внутренняя проверка shap на аддитивность проходит! ХЗ как это возможно. У других бустингов тоже такое наблюдалось, но хотя бы с гораздо меньшей амплитудой. В режиме feature_perturbation="tree_path_dependent" такого никогда не наблюдал.
5) Режим feature_perturbation="interventional" требует теневого датасета и считает значения Шэпли на порядки дольше, но ничего не даёт к точности.
6) xgboost (и только он) поддерживает доп параметр approximate=True, который отрабатывает быстрее, но реально роняет качество. его использовать не надо.
7) документация shap по-прежнему дырявая (параметры объясняльщика, которые ничего не делают, например), а на гитхабе никто по-прежнему не отвечает и не отрабатывает сигналы и проблемы юзеров. не понимаю, как они при этом релизят новые версии, скорее всего, это в основном переписывания исходного говнокода Скотта Ландберга.
Ну и самое главное, по поводу аппроксимации честных прогнозов шэпли-значениями.
1) все виды бустингов и все виды объясняльщиков для нашей задачи имеют примерно одинаковое качество (если не использовалось approximate=True)
2) усреднения ничего особо не меняют.
3) метамодель существенно улучшает линейную (да и другие) корреляцию, но особо не меняет метрики ранжирования комбинаций (которые и так на удивление хороши).
4) при небольшой по размеру группе кандидатов на удивление ранжирующие свойства сильно не падают.
В дополнение к посту. Потестировал много вариантов улучшения исходной идеи:
1) усреднение значений Шэпли нескольких типов (с разными feature_perturbation)
2) усреднение значений Шэпли нескольких разных моделей
3) использование парных интеракций (shap_interaction_values)
4) мета-модель ML: зная индексы выбранных в комбинацию признаков и оставшихся признаков, а также честные предсказания моделек, давайте попробуем создать как мета-признаки ряд простых числовых агрегатов от шепли-значений (суммы, средние, отклонения, мин/макс и тп). ну и уже от этого мета-модель, вдруг она будет точнее чем исходная простая идея просуммировать значения Шепли выбранных в комбинацию признаков?
Находки/открытия:
1) не существует работающей реализации Shap на GPU (GPUTreeExplainer из пакета shap нерабочий, и всем похер. По идее он должен ставиться с xgboost (без shap), но он всё равно не юзает gpu, я проверял.)
2) KernelExplainer непроходимо медленен, забудьте про его использование. Речь о сотнях часов даже на небольшом датасете.
3) некоторые модели (lightgbm) считают интеракции в один поток и очень медленно (~40 минут на 100k x 20 датасете)
4) некоторые бустинги (Catboost) раздувают expected_value так, что они не просто не сходятся точно к среднему прогнозу, а превышают его вдвое. При этом внутренняя проверка shap на аддитивность проходит! ХЗ как это возможно. У других бустингов тоже такое наблюдалось, но хотя бы с гораздо меньшей амплитудой. В режиме feature_perturbation="tree_path_dependent" такого никогда не наблюдал.
5) Режим feature_perturbation="interventional" требует теневого датасета и считает значения Шэпли на порядки дольше, но ничего не даёт к точности.
6) xgboost (и только он) поддерживает доп параметр approximate=True, который отрабатывает быстрее, но реально роняет качество. его использовать не надо.
7) документация shap по-прежнему дырявая (параметры объясняльщика, которые ничего не делают, например), а на гитхабе никто по-прежнему не отвечает и не отрабатывает сигналы и проблемы юзеров. не понимаю, как они при этом релизят новые версии, скорее всего, это в основном переписывания исходного говнокода Скотта Ландберга.
Ну и самое главное, по поводу аппроксимации честных прогнозов шэпли-значениями.
1) все виды бустингов и все виды объясняльщиков для нашей задачи имеют примерно одинаковое качество (если не использовалось approximate=True)
2) усреднения ничего особо не меняют.
3) метамодель существенно улучшает линейную (да и другие) корреляцию, но особо не меняет метрики ранжирования комбинаций (которые и так на удивление хороши).
4) при небольшой по размеру группе кандидатов на удивление ранжирующие свойства сильно не падают.
Telegram
Aspiring Data Science
#featureselection
Подобрался к более детальной проверке идеи из этого поста. Результаты поистине изумительные.
Как мы и знали раньше (из оригинального исследования автора, + моей проверки), корреляция "аппроксимированных предсказаний" и "честных предсказаний"…
Подобрался к более детальной проверке идеи из этого поста. Результаты поистине изумительные.
Как мы и знали раньше (из оригинального исследования автора, + моей проверки), корреляция "аппроксимированных предсказаний" и "честных предсказаний"…
#featureselection
Вот внесэмпловые метрики XGBRegressor feature_perturbation=tree_path_dependent, approximate=False из предыдущего поста.
meta=мета-моделька, naive это просто сумма шэпли-значений как у автора идеи, adjusted это naive минус сумма шэпли-значений признаков не вошедших в комбинацию.
Считалось на датасете poker (10 исходных признаков + 5 фейковых случайных + 5 коррелированных с исходными). Помимо 2 видов ndgc (rel/abs), грубыми, но выразительными метриками были top_recall@k. Например, чтобы посчитать recall@10, брались 10 лучших (согласно честными прогнозам) на test комбинаций, и проверялось, сколько из них оказались в 10 лучших по версии того или иного метода.
В целом, для данной задачи нет смысла морочиться с мета-моделью, надо просто брать наивный оригинальный метод автора, и feature_perturbation="tree_path_dependent".
Вот внесэмпловые метрики XGBRegressor feature_perturbation=tree_path_dependent, approximate=False из предыдущего поста.
meta=мета-моделька, naive это просто сумма шэпли-значений как у автора идеи, adjusted это naive минус сумма шэпли-значений признаков не вошедших в комбинацию.
Считалось на датасете poker (10 исходных признаков + 5 фейковых случайных + 5 коррелированных с исходными). Помимо 2 видов ndgc (rel/abs), грубыми, но выразительными метриками были top_recall@k. Например, чтобы посчитать recall@10, брались 10 лучших (согласно честными прогнозам) на test комбинаций, и проверялось, сколько из них оказались в 10 лучших по версии того или иного метода.
В целом, для данной задачи нет смысла морочиться с мета-моделью, надо просто брать наивный оригинальный метод автора, и feature_perturbation="tree_path_dependent".
#featureselection #shap
Ну и теперь к практической реализации отборщика признаков на основе этой прекрасной идеи. Как это вообще сделать?
Обучать одну большую модель на всех признаках надо обязательно. Это, по счастливому совпадению, 1-й шаг всех RFE-* методов.
Далее получаем "простые" кэфы Шэпли самым быстрым (но не приближённым) методом. По желанию усредняем на CV.
И тут открывается простор для фантазии:
Полный брутфорс:
Генерим все 2^n_features сочетаний признаков, сортируем индексы признаков в сочетаниях.
суммируем шэпли-значения 1й комбинации. далее удаляем суммы убывших, прибавляем суммы прибывших в комбинацию признаков. раз в N итераций ресет суммы, чтобы сбросить накопленную ошибку суммирования.
Генетик:
Вектор 1/0 длины n_features генов - это особь популяции, её фитнесс оценивать мы умеем (суммируя его шэпли-значения и считая от них и ground truth нашу ml-метрику).
применяем направленный поиск путём скрещивания, мутаций, и прочего элитизма. Запускаем эволюцию, играем в Создателя, смеёмся страшным голосом mwa-ha-ha.
Любая другая эвристика, типа имитации отжига:
Начинаем со случайного вектора, делаем небольшие изменения, продвигаемся с вероятностью пропорциональной улучшениям, порог принятия снижается со временем.
Мультистарт. А если начинать с кандидатов ранжированных по FI?
Градиентный поиск:
Ну да, это ж бинарный вектор, нет непрерывности, как по нему дифференцировать? Есть идея применить "признаки Шрёдингера"! ))
А именно, размазать их бинарность с помощью весового коэффициента. Они могут как бы входить, а как бы и нет в комбинацию с определённым весом. А чтобы вес в итоге ограничивался промежутком [0,1], к нему можно применить сигмоиду. Тем самым autograd-оптимизатор по идее сможет найти экстремумы ML-метрики, плавно включив/исключив признаки из комбинации.
А если итоговая ML-метрика недифференцируема (типа ROC, PR AUC)? Ну тогда ведь можно взять Brier score или какую-то подходящую прокси.
Уже есть набросок кода для pytorch, попробую затестить.
Не знаю, что сработает лучше, есть надежды на градик.
В любом случае, надо дать методу оптимизации поработать (в рамках бюджета времени), и получить от него топ-N лучших кандидатов. А их уже "честно" проверить (в оставшееся время) на insample CV и вернуть самую лучшую/устойчивую комбинацию признаков.
Надо ещё помнить, что точность метода может падать при уменьшении количества кандидатов в группе по сравнению с размерностью матрицы значений Шэпли, но это обсудим позже.
Ну и теперь к практической реализации отборщика признаков на основе этой прекрасной идеи. Как это вообще сделать?
Обучать одну большую модель на всех признаках надо обязательно. Это, по счастливому совпадению, 1-й шаг всех RFE-* методов.
Далее получаем "простые" кэфы Шэпли самым быстрым (но не приближённым) методом. По желанию усредняем на CV.
И тут открывается простор для фантазии:
Полный брутфорс:
Генерим все 2^n_features сочетаний признаков, сортируем индексы признаков в сочетаниях.
суммируем шэпли-значения 1й комбинации. далее удаляем суммы убывших, прибавляем суммы прибывших в комбинацию признаков. раз в N итераций ресет суммы, чтобы сбросить накопленную ошибку суммирования.
Генетик:
Вектор 1/0 длины n_features генов - это особь популяции, её фитнесс оценивать мы умеем (суммируя его шэпли-значения и считая от них и ground truth нашу ml-метрику).
применяем направленный поиск путём скрещивания, мутаций, и прочего элитизма. Запускаем эволюцию, играем в Создателя, смеёмся страшным голосом mwa-ha-ha.
Любая другая эвристика, типа имитации отжига:
Начинаем со случайного вектора, делаем небольшие изменения, продвигаемся с вероятностью пропорциональной улучшениям, порог принятия снижается со временем.
Мультистарт. А если начинать с кандидатов ранжированных по FI?
Градиентный поиск:
Ну да, это ж бинарный вектор, нет непрерывности, как по нему дифференцировать? Есть идея применить "признаки Шрёдингера"! ))
А именно, размазать их бинарность с помощью весового коэффициента. Они могут как бы входить, а как бы и нет в комбинацию с определённым весом. А чтобы вес в итоге ограничивался промежутком [0,1], к нему можно применить сигмоиду. Тем самым autograd-оптимизатор по идее сможет найти экстремумы ML-метрики, плавно включив/исключив признаки из комбинации.
А если итоговая ML-метрика недифференцируема (типа ROC, PR AUC)? Ну тогда ведь можно взять Brier score или какую-то подходящую прокси.
Уже есть набросок кода для pytorch, попробую затестить.
Не знаю, что сработает лучше, есть надежды на градик.
В любом случае, надо дать методу оптимизации поработать (в рамках бюджета времени), и получить от него топ-N лучших кандидатов. А их уже "честно" проверить (в оставшееся время) на insample CV и вернуть самую лучшую/устойчивую комбинацию признаков.
Надо ещё помнить, что точность метода может падать при уменьшении количества кандидатов в группе по сравнению с размерностью матрицы значений Шэпли, но это обсудим позже.