2.7Kпросмотров
18 июля 2022 г.
Score: 3.0K
Недавно мне понадобилось для калибровки регрессионных моделей обучить формулу y=f(X), которая хорошо бы приближала заданное облако точек (возможно, нелинейно) и была бы монотонно возрастающая и по возможности гладкая. В scikit-learn нашлись три примерно подходящие модели:
1) Старая добрая LinearRegression: монотонная и максимально гладкая, но неспособная описывать нелинейности.
2) IsotonicRegression: монотонная и умеющая в произвольные нелинейности, но очень негладкая и склонная к переобучению.
3) HistGradientBoostingRegressor: нечто кусочно-постоянное, вроде IsotonicRegression, но приспособленное и для многомерных Х. Мне захотелось создать что-то среднее: модель, которая была бы настолько же гибкая, как IsotonicRegression, но в которой можно было бы задавать степень гладкости (так, что максимально гладкая версия сходилась бы к линейной регрессии). Для этого можно обучать линейную регрессию над базисом из множества непрерывных кусочно-линейных ступенек, минимизируя одновременно MSE и средний модуль разностей крутизны соседних ступенек, с ограничением, что крутизна каждой ступеньки – неотрицательная. Чем больше вес второй компоненты в функции потерь, тем более гладкая получится в результате функция. Попробовал имплементировать эту идею, получилось ровно 100 строк кода:
- Ступеньки такие: слева и справа от – константа, между ними – линейная функция.
- Границы ступенек делаем в каждом наблюдении, если данных мало, и в процентилях (либо с равномерным шагом), если датасет большой.
- Веса ступенек инициализируем из Ridge-регрессии: она тоже добавляет гладкости, но минимизирует не разность крутизны соседних ступенек, а сумму квадратов крутизны ступенек.
- Дальше "правильную" функцию потерь минимизируем с помощью scipy.optimize.
- После обучения модель можно сконвертировать в IsotonicRegression, которая делает predict эффективнее (под капотом очень быстрая numpy.interp). Код тут: https://gist.github.com/avidale/83998aa24e5d9c40c894e9e39c9f9c86