ds_private_sharing | Unsorted

Telegram-канал ds_private_sharing - Data Science Private Sharing

1829

Советы и лайфхаки для соревновательного (в основном) дата сайнса, о которых не расскажут на курсах. Канал про LLM -> @llm_is_all_you_need Для связи -> @slivka_83 Tags: #EDA #Evaluation #Models #TimeSeries #Train #Preprocessing #Valid

Subscribe to a channel

Data Science Private Sharing

#курс

Всем привет :)

Почти 2 месяца ничего не постил.
А это потому, что был очень занят - писал лучший курс по машинному обучению (и другие курсы ему завидуют :)

А если серьезно, то аналогов такому курсу и в правду не встречал.
Курс посвящен реализации всех классических алгоритмов машинного обучения с нуля. На чистом питоне + нампай и пандас.
Упор в курсе будет делаться именно на алгоритмы. Хотя и немного математики там есть.

Курс бесплатный :) На степике.

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

Сейчас ищу 3-4 человека, которые помогут протестировать задания перед публикацией в открытый доступ.
От кандидатов жду понимания основ МЛ, умения писать на питоне и знания нампай и пандас. Плюс свободное время.

Кто хочет - пишите в личку.

Читать полностью…

Data Science Private Sharing

#Tip31 #Train

Обычно оптуну воспринимают как инструмент оптимизации гипер-параметров модели.
Но ее возможности несколько шире. Например, можно повесить на нее и препроцессинг :)

Вот небольшой пример. Допустим, у вас есть датасет. В датасете есть колонки с пропусками. Колонки, в которых очень много пропусков - бесполезны и по-хорошему от них нужно избавиться. Но какой процент считать бесполезным? Выкидывать колонки, в которых более 90% пропусков? Более 80%? 70%? Можно пробовать выяснять это вручную, а можно поручить это опутне. Примерно так:

nulls_perc = (X.isna().sum() / X.shape[0] * 100).astype(int).sort_values(ascending=False)

def objective(trial):
params = {
'objective': 'regression',
'metric': 'mse',
'learning_rate': trial.suggest_float('learning_rate', 1e-5, 0.7, log=True),
'num_leaves': trial.suggest_int('num_leaves', 20, 150),
'verbose': -1
}

nulls_max = trial.suggest_int('nulls_max', 10, 100)
f_cols = list(nulls_perc[nulls_perc < nulls_max].index)

X_train = train[f_cols]
X_test = test[f_cols]

model = lgbm.train(
params = params,
train_set = lgbm.Dataset(X_train, y_train),
valid_sets = lgbm.Dataset(X_test, y_test),
verbose_eval = None
)

score = model.best_score['valid_0']['l2']
print(score, len(f_cols))

return score

study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=3000, timeout=300)

Здесь мы в начале подсчитываем процент пропусков в каждой колонке. Затем внутри цикла генерируем кол-во пропусков, которое хотим оставить (от 10% до 100%). Отбираем колонки по этому показателю и формируем датасеты для обучения и валидации.

Точно также можно выкидывать статичные колонки, можно перебирать способы заполнение пропусков и кучу других препроцессинговых задач.

Читать полностью…

Data Science Private Sharing

#Tip30 #Train

В отличии от других бустингов в LGBM деревья растут асимметрично (по листьям). В то время как в CatBoost и XGBoost рост происходит по уровням. И это декларируется разработчиками LGBM как одно из основных преимуществ.

И тут закралась ловушка: если вы ограничите глубину дерева в LGBM (а для бустингов рекомендуются не глубокие деревья), то вы по сути превратите его в симметричное урезанное дерево!

Именно поэтому по умолчанию в LGBM глубина деревьев (max_depth) = -1 (что значит - бесконечная), а в CatBoost и XGBoost глубина = 6.

Но бесконечно расти тоже не вариант - так мы просто запомним все данные. Поэтому, чтобы ограничить глубину деревьев используйте такие параметры как:
num_leaves — максимальное количество листьев в одном дереве
min_data_in_leaf — минимальное количество данных в одном листе
min_data_in_bin — минимальное количество данных внутри одного бина
min_data_per_group — минимальное количество данных на одно значение категориальной фичи
min_gain_to_split — минимальный прирост, которое дает разделение
min_sum_hessian_in_leaf — минимальная сумма гессиана в одном листе

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

З.Ы. Недавно поведение аналогичное LGBM и XGBoost реализовали в катбусте.

Читать полностью…

Data Science Private Sharing

#Tip29 #Train

Случайный лес не переобучается! Но с оговоркой... :)
Лес переобучается, но он не переобучается от увеличения кол-ва деревьев (при прочих разумных условиях).

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

Но если вы зададите для леса глубину скажем 1000, то он конечно же переобучится: просто запомнит данные, вместо того чтобы выучить закономерности.

Интуитивно это можно понять так... Представим себе генеральную совокупность на 10 000 000 экземпляров. Возьмем из нее два случайных экземпляра и посчитаем их среднее. Очевидно, что это среднее будет сильно отличаться от среднего генеральной совокупности. Также и для трех, четыре, пяти... экземпляров. Но если мы возьмем 1 000 000 случайных экземпляров, то среднее будет очень близко к генеральной совокупности. И добавление миллион первого, второго, третьего экземпляра сильно на среднее не повлияет.
Лес точно также усредняет предсказания своих деревьев. И в определенный момент кол-во деревьев становится достаточным, и добавление новых уже ни на что не виляет (если не считать шум).

Читать полностью…

Data Science Private Sharing

#Tip28 #Train

Nested Cross-Validation - самая дорогая из "классических" схем валидации.
Состоит из двух вложенных кросс-валидаций: внешней и внутренней. Внутренняя используется для подбора гипер-параметров/выбора модели, а внешняя - для оценки модели.

При обучении модели вам нужно решить две задачи: подобрать гипер-параметры и оценить модель. Если использовать для них только одну кросс-валидацию, то это может привести к чрезмерно оптимистичной оценке модели. Поскольку одни и те же данные используются и для подбора гипер-параметров и для оценки модели. Обычно в этом случае для финальной оценки выделяют тестовую часть, которая никаким образом в обучении не участвует. Но тогда мы теряем часть данных для обучения. С помощью Nested Cross-Validation можно задействовать все данные для обучения и получить корректную оценку.

Алгоритм такой:
1. Делим весь датасет на фолды
2. Для каждого фолда:
- Делим часть для обучения на свои фолды
- Подбираем гипер-параметры
- Обучаем одну модель на всей тренировочной части на лучших гипер-параметрах
- Оцениваем модель на тестовой части
3. Усредняем скоры по всем внешним фолдам

На выходе, помимо скоров, у нас будут N обученных моделей. Для предсказания используются все три, результаты усредняются.

Т.к. такая схема очень дорогая по времени, то применять ее следует в двух случаях:
1. У вас очень маленький датасет.
2. У вас есть своя майнинг-ферма :)

З.Ы. Для временного CV все аналогично просто оба цикла будут со сдвигом.

Читать полностью…

Data Science Private Sharing

Ловите еще одну статью :)
На этот раз посвященную Evidently - библиотеке для мониторинга качества данных и моделей в проде.

https://habr.com/ru/post/692272/

Лайки приветствуются :)

Читать полностью…

Data Science Private Sharing

Написал на Хабре туториал про Dagster - оркестратор предназначенный для организации конвейеров обработки данных: ETL, проведение тестов, формирование отчетов, обучение ML-моделей.

https://habr.com/ru/post/690342/

Заходим, не стесняемся, лайкаем :)

З.Ы. Туториал написан в рамках прохождения курса ML System Design (можете еще присоединиться): https://ods.ai/tracks/ml-system-design-22

Читать полностью…

Data Science Private Sharing

#Tip26 #EDA

Partial dependence plots (PDP) — это график, который позволяет понять, как различные значения конкретной фичи влияют на предсказания модели.
Под капотом PDP меняет исходные значения целевой фичи и смотрит как изменяются предсказания модели.
По сути PDP показывает ожидаемое среднее значение таргета при различных значения интересующей нас фичи.

Строятся PDP в двух вариантах - для одной фичи и для пары фичей. Обычно для графика выбирают наиболее значимые для модели фичи.

Т.к. PDP работает с уже обученной моделью, то это еще один способ приоткрыть завесу черного ящика (наряду с SHAP и пр.).

PDP можно построить либо с помощью скалерна (но на вход принимаются только родные для скалерна модели):

fig, ax = plt.subplots(figsize=(18.5,4.5))
features = ['bahrooms','sqf_living','yr_buil']
PartialDependenceDisplay.from_estimator(clf, X, features, ax=ax);


Либо с помощью сторонних пакетов, например PDPbox (https://github.com/SauceCat/PDPbox):
features_to_plot = ['sqf_living','bahrooms']
inter1 = pdp.pdp_interact(model=model, dataset=X, model_features=fcols, features=features_to_plot)
pdp.pdp_interact_plot(pdp_interact_out=inter1, feature_names=features_to_plot, plot_type='contour')
plt.show()


З.Ы. У PDPbox есть еще много других интересных графиков.

Читать полностью…

Data Science Private Sharing

#Tip24 #Train

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

Поэтому для градиентного бустинга придумали такой фокус:
1. Разбиваете датасет на трейн и тест.
2. Обучаете модель и подбираете наилучшие гипер-параметры. Проверяете модель на тесте.
3. Объединяете трейн и тест.
4. Заново обучаете модель на полном датасете с найденными гиперпарамтрами, но только увеличиваете в них количество итераций на % размера теста.
Т.е. если у вас получилось 100 итераций, а тест составляет 20% от размера трейна, то для нового обучения выставляете кол-во итераций в 120.
5. Делаете предсказание с новой моделью. При этом протестировать ее сможете только на лидерборде.

Данный фокус не имеет под собой научного обоснования, но иногда докидывает...

Читать полностью…

Data Science Private Sharing

#Tip22 #Evaluation
Object Importance - это метод, который позволяет определить, насколько каждая запись тренировочного датасета влияет на оптимизируемую метрику.
А значит, он позволяет найти и избавится от бесполезных записей (шум, выбросы и т.д.).

Метод реализован в библиотеке Catboost:

train_pool = Pool(X_train, y_train)
val_pool = Pool(X_val, y_val)

cb = CatBoost({'eval_metric': 'RMSE'})
cb.fit(train_pool)

indices, scores = cb.get_object_importance(
val_pool,
train_pool,
importance_values_sign='Positive' # Negative, All
)

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

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

З.Ы. В параметре update_method доступны три алгоритма расчета - можете поэксперементировать.

Читать полностью…

Data Science Private Sharing

#Tip20 #Train
Псевдо-лейблинг (pseudo-labeling) это метод обучения на не размеченных данных.

В соревнованиях он может использоваться так:
1. Обучаете модель на трейне
2. Делаете предсказание на тесте
3. Объединяете трейн+тест и заново обучаете модель. И тут супер важно валидироваться только на данных из трейна, поскольку в тесте будут и ошибочно размеченные данные.
4. Заново предсказать тест.

Очевидно, что при таком подходе модель увидит больше данных и закономерностей. А чем больше (хороших) данных тем точнее модель.

Читать полностью…

Data Science Private Sharing

#Tip18 #TimeSeries
Интересный пример подмены задачи.
Допустим Вам дана задача регрессия на временных рядах.
Вы можете решать ее напрямую. А можете предсказывать не абсолютные значения, а прирост значения относительно предыдущего.
Из очевидных преимуществ - меньше разброс значений целевой переменной, а значит меньше выбросов - а модели выбросы не любят :)

Читать полностью…

Data Science Private Sharing

#Tip16 #Evaluation
Способ повысить стабильность модели.
На курсах учат подбирать гиперпараметры на кросс-валидации. Тут все правильно.
Но как выбрать наилучшие гиперпараметры. Обычно берут средний скор по фолдам.
Но тут еcть подвох. У двух одинаковых усредненных скоров есть важное отличие - стандартное отклонение.
Чем меньше стандартное отклонение - тем лучше.
Поэтому отбираем модель так:

mean(скоры_по_фолдам) - std(скоры_по_фолдам)
Таким образом мы будем стремиться отбирать модель с меньшим разбросом по скорам между фолдами.

Читать полностью…

Data Science Private Sharing

#Tip14 #Preprocessing
Есть такая функция в пандас - transform - которую незаслуженно обходят вниманием на курсах.

Допустим у нас есть данные по продажам в разрезе клиентов.

df[['client_id','sales']]
И мы хотим посчитать сумму/среднее (или любой другой агрегат) по продажам, чтобы затем подставить его в ту же самую таблицу.
Если делать это в лоб, то через промежуточную таблицу:
temp_df = df.groupby('client_id')['sales'].mean().rename('sales_mean')
df = pd.merge(df, temp_df, on='client_id')
С функцией трансформ это делается в одну строку:
df['sales_mean'] = df.groupby('client_id')['sales'].transform('mean')

Читать полностью…

Data Science Private Sharing

#Tip12.1 #Preprocessing
У логарифмов 👆 есть некоторые недостатки, в частности они плохо борются с недостаточно длинными хвостами.
Поэтому придумали немного более сложный метод - Бокса-Кокса, который зачастую дает более правильное нормально распределение.

В отличии от логарифма, его нужно обучить на трейна и применить к тесту (если речь о преобразовании фичей):

from scipy.stats import boxcox
train_price, fitted_lambda = boxcox(df['price'])
train['price_boxcox'] = train_price
test['price_boxcox'] = boxcox(test['price_boxcox'], fitted_lambda)

Обратное преобразование производится так:
from scipy.special import inv_boxcox
inv_boxcox(test['price_predict'],fitted_lambda)

Читать полностью…

Data Science Private Sharing

#Tip32 #Train

Самый простой способ борьбы с выбросами (о котором не расскажут на курсах :)
1. Обучаете модель.
2. Делаете предсказание на трейне.
3. Объекты, у которых самые большие ошибки выкидываете из трейна.

З.Ы. Для задачи регрессии возможно стоит попробовать метрику MAE, поскольку MSE сильнее штрафует за большие ошибки (а значит лучше борется с выбросами).

Читать полностью…

Data Science Private Sharing

Написал небольшой эпос о библиотеке transformers.
И хотя текста много это все равно только лишь введение. Функционала в библиотеке слишком много.
https://habr.com/ru/post/704592/

Для тех кто не в курсе: библиотека Transformers предоставляет доступ к куче современных предобученных DL-моделей.
И на текущий момент является чуть ли не аналогом скалерна в мире Deep Learning.

Читать полностью…

Data Science Private Sharing

Залил на Хабр статью про библиотеку Voilà (читается "вуаля"), которая позволяет конвертировать ноутбуки в веб-приложения.

https://habr.com/ru/post/698662/

Читать полностью…

Data Science Private Sharing

Написал туториал про фреймворк Hydra
https://habr.com/ru/post/696820/

Гидра предназначена для управления файлами конфигурации в ML-проектах.

Читать полностью…

Data Science Private Sharing

#Tip27 #Train

При K-fold валидации прогнозы делаются на тестовых частях, которые не участвуют в обучении и эти прогнозы называются Out-of-Fold (OOF) Predictions.

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

Стэкинг это способ построения ансамбля моделей, в котором есть базовые модели и есть мета модель.
Базовые модели обучаются на исходных данных, а мета-модель на предсказаниях базовых моделей.
Обычно для построения стекинга исходный датасет делится на несколько крупных частей из-за чего все модели увидят меньше данных. Но благодаря Out-of-Fold Predictions можно реализовать обучение на всех (почти) данных.

В соревновательном DS алгоритм в целом такой:
1. Разбиваем датасет с метками на трейн и эвал + у нас уже есть тестовый датасет от организаторов.
2. Трейн разбиваем на фолды.
3. Для каждого фолда:
- Обучаем модель на тренировочной части.
- Выполняем предсказание для тестовой части фолда и сохраняем предсказание в отдельный вектор, каждый элемент которого соответствует строке тренировочного датасета.
- Выполняем предсказание для валидационного датасета.
- Выполняем предсказание для тестового датасета.
4. Собранные предсказания на фолдах передаем в мета-модель как фичу.
5. Усредняем предсказания полученные для валидационного и тестового датасета.
6. С помощью мета-модели делаем предсказание для усредненных значений валидационного и тестового датасета.
7. Значения полученные для валидационного датасета используем для оценки, а значения полученные для тестового датасета заворачиваем в сабмит.

Реализуется данный алгоритм обычно вручную.

Варианты для изменений:
- На фолдах можно обучить несколько видов базовых моделей, тогда на вход мета-модели пойдет несколько фичей.
- На шаге обучения мета-модели можно присоединить фичи-предсказания к исходным фичам.

Для большей эффективности ансамбля для базовых и мета-модели стараются задействовать разные алгоритмы (линейные/KNN/деревья).

Читать полностью…

Data Science Private Sharing

Написал на Хабре еще один туториал (в рамках курса ML System Design).
На этот раз посвященный ClearML - системе трекинга Ml-экспериментов.

https://habr.com/ru/post/691314/

Заходим, читаем и не забываем ставить лайки :)

Читать полностью…

Data Science Private Sharing

#Tip26.1 #EDA
Для понимания как строится PDP попробуем построить его в ручную.
Алгоритм такой:
- Выбираем какую-нибудь фичу
- Вычисляем все ее уникальные значения (для непрерывной фичи можно взять сколько-то квантильных значений)
- Проходимся по каждому из них и:
- В исходном датасете для нашей фичи заменяем все значения на одно - текущее
- Делаем предсказание
- Усредняем полученные предсказания
И так для каждого уникального значения. В итоге получаем набор пар: (уникальное значение - средний предикт)
По смыслу мы как бы спрашиваем модель: а что если бы фича принимала бы только одно значение из возможного диапазона (при этом другие фичи не трогаем) - какими тогда стали бы предсказания?
- Выводим их на графике.

З.Ы. Также для демонстрации влияния на отдельные примеры выведем случайные 50 записей. Такой график уже будет называться Individual Conditional Expectation (ICE). Он позволяет увидеть какие-либо аномалии - как отдельные записи отклоняются от среднего значения.

# Считаем PDP
col = 'grade'
uniq_values = sorted(X[col].unique())
preds = {}
for v in uniq_values:
X_copy = X.copy()
X_copy[col] = v
preds[v] = model.predict(X_copy)
preds = pd.DataFrame(preds)
pdp = preds.mean()

# Выбираем случайные 50 записей
samp = preds.sample(50).copy()
samp = samp.reset_index().melt('index', var_name='cols', value_name='vals')

# Строим графики
plt.figure(figsize=(13,6))
sns.lineplot(data=samp, x='cols', y='vals', hue='index', legend=False, palette='GnBu', alpha=0.2)
sns.lineplot(x=pdp.index, y=pdp, color='red', linewidth=2)
plt.xlabel(col)
plt.ylabel('PDP');

Читать полностью…

Data Science Private Sharing

#Tip25 #TimeSeries #Valid

TimeSeriesSplit - известный способ разбиения временных данных для кросс-валидации из скалерна.
Метод разбиения, который в нем реализован называется Expanding window.

Но наука о временных рядах знает гораздо больше способов разбить временные данные. Основных два:
- Expanding Window
- Sliding Window

А дальше включается воображение:
- Нахлесты между периодами
- Пробел между трейном/валидом/тестом
- Способ выделения тестовой выборки

Как уже было сказано, Expanding Window можно найти в скалерне. Для Sliding Window и других ухищрений нужно либо писать свой код (основные ML-библиотеки принимают готовые сплиты в виде индексов строк), либо поискать на гитхабе:
https://github.com/WenjieZ/TSCV
https://github.com/AaronOS0/Time-series-Cross-validation
https://github.com/marmurar/jano
и прочие...

Читать полностью…

Data Science Private Sharing

#Tip23 #Preprocessing

pipe - это метод реализации паплайна в датафреймах пандас посредством последовательной цепочки преобразований.
З.Ы. Не путать с Pipeline из скалерна - это разные вещи.

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

def normilize(df):
...
return df

def fill_null(df, method):
...
return df

def parse_time(df):
...
return df

new_df = (df
.pipe(normilize)
.pipe(fill_null, method='median')
.pipe(parse_time)
)

Читать полностью…

Data Science Private Sharing

#Tip21 #Train

Планировщик (scheduler) в нейронных сетях довольно обыденная вещь - он позволяет уменьшать шаг обучения (learniтп rate) с каждой эпохой (ну или раз в несколько эпох).

В бустингах такая вещь тоже встречается, но не часто ее увидишь.
Например, в LGBM динамический learning rate можно реализовать так:

model = lgb.train(
params,
train_df,
learning_rates = lambda iter: 0.5 * (0.85 ** iter),
valid_sets = eval_df)

Читать полностью…

Data Science Private Sharing

#Tip19 #Evaluation
Когда вы делаете предсказание для задачи классификации, то, помимо метрики, также визуально оцениваете качество по матрице ошибок.
А когда делаете регрессию, куда смотреть?

Тут я строю два графика:
Первый - самый очевидный - просто отложить на двух осях фактические и предсказанные значения.
Второй - подсмотрел у Дьконова - изменить координаты на True-Pred и True+Pred. По сути, тот же вариант что и первый, но растянут по одной оси и сужен по второй. Позволяет посмотреть на график под другим углом. Говорят иногда бывает полезно.

Читать полностью…

Data Science Private Sharing

#Tip17 #Models
Перед построением какой-ниубдь сложной модели рекомендуется сначала построить простой бейзлайн, чтобы было с чем сравнивать повышение качества. Но какую модель выбрать? А ничего выбирать не надо - есть специальные пакеты, которые сразу строят кучу моделей.

Я знаю два таких:
- PyCaret - https://github.com/pycaret/pycaret
- Lazy Predict - https://github.com/shankarpandala/lazypredict

Но второй требует более старой версии пандаса, да и вообще похоже уже не развивается.
А вот первый довольно интересный (скрин с него). В документации вы найдете туториалы.

Читать полностью…

Data Science Private Sharing

#Tip15 #Evaluation
Построили вы модель, вывели feature importance. Допустим фичей достаточно много. И вам нужно выкинуть какое-то кол-во фичей. В идеале бесполезных.

Есть такой старый фокус: перед построением модели добавляете в датасет три случайно сгенерированные фичи:
- Бинарную (0 или 1)
- Непрерывную, между 0 и 1
- Целочисленную (например, между 1 и 10_000)
Далее обучаете модель и выводите feature importance - все фичи, которые ниже случайно сгенерированных - выкидываете.
Эти новые фичи по сути шум и все что ниже их - бесполезный мусор.

Читать полностью…

Data Science Private Sharing

#Tip13 #Preprocessing
Некоторые данные по своей природе имеют циклическую структуру: часы, минуты, месяцы и т.д.
Рассмотрим часы. С т.з. математики число 22 больше 1, но с т.з. времени 1 час сегодняшнего дня больше 22 часов вчерашнего.
И по-хорошему, модели необходимо сообщить эту информацию (особенно линейным).

Для этого делают косинусо-синусное преобразование:

hours_in_day = 24

df['hour_sin'] = np.sin(2 * np.pi * df['hour'] / hours_in_day)
df['hour_cos'] = np.cos(2 * np.pi * df['hour'] / hours_in_day)

После этого одна циклическая фича будет представлена двумя непрерывными фичами.

Читать полностью…

Data Science Private Sharing

#Tip12 #Preprocessing
Зачастую, в задачах линейной регрессии таргет имеет длинный хвост в распределении данных.
А моделям "нравится" когда данные имеют нормальное распределение. Особенно это касается линейных моделей.

Чтобы привести распределение к нормальному, нужно:
1. Прологарифмировать таргет.

df['target_log'] = np.log(df['target'] + np.abs(df['target'].min()) + 1)
Обратите внимание, что мы сначала делаем таргет не отрицательным, добавляя константу и >= 1 (чтобы не было отрицательных значений).
2. Обучить модель на логарифмированном таргете.
3. Когда получите предсказание модели, необходимо привести его к изначальному виду через экспоненту:
df['predict'] = np.expm1(df['predict_log'])

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

Возможности для маневров:
- Разные основания логарифмов
- Взять логарифм от логарифма (и так несколько раз)
- Привести к нормальному распределению входные данные
- В взять корень от числа

Читать полностью…
Subscribe to a channel