Цель
Я пытаюсь создать регрессоры, которые инкапсулируют процесс
- преобразования цели из нечислительного c в числовое c формат
- внутри, используйте числа для всех вычислений
- обратное преобразование чисел c - возвращает значения в исходный формат перед тем, как представить их пользователю.
В идеале, Конечный пользователь должен иметь возможность использовать регрессор, не зная внутренних данных целевых преобразований. Ожидается, что разработчик предоставит функции, которые реализуют преобразование и обратное преобразование логи c.
Prototype Demo
С помощью sklearn.compose.TransformedTargetRegressor
я смог построить модель линейной регрессии, которая принимает временные метки в качестве целей и внутренне преобразует их в секунды, выделенные с 1970-01-01 00:00:00 (Unix эпоха). Методы fit
и predict
уже работают должным образом.
import pandas as pd
from sklearn.compose import TransformedTargetRegressor
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import FunctionTransformer
_check_inverse = False
# helper to convert a 2D numpy array of timestamps to a 2D array of seconds
def _to_float(timestamps):
deltas = pd.DataFrame(timestamps).sub(pd.Timestamp(0))
return deltas.apply(lambda s: s.dt.total_seconds()).values
# helper to convert a 2D numpy array of seconds to a 2D array of timestamps
def _to_timestamp(seconds):
return pd.DataFrame(seconds).apply(pd.to_datetime, unit='s').values
# build transformer from helper functions
time_transformer = FunctionTransformer(
func=_to_float,
inverse_func=_to_timestamp,
validate=True,
check_inverse=_check_inverse
)
# build TransformedTargetRegressor
tt_reg = TransformedTargetRegressor(
regressor=LinearRegression(),
transformer=time_transformer,
check_inverse=_check_inverse
)
Использование:
>>> import numpy as np
>>> X = np.array([[1], [2], [3]], dtype=float)
>>> y = pd.date_range(start=0, periods=3, freq='min')
>>> tt_reg = tt_reg.fit(X, y)
>>> tt_reg.predict(X)
array(['1970-01-01T00:00:00.000000000', '1970-01-01T00:01:00.000000000',
'1970-01-01T00:02:00.000000000'], dtype='datetime64[ns]')
Однако методы, которые используют результат predict
внутри, например score
(и, возможно, другие методы более сложных регрессоров sklearn) не работают, потому что они не могут обработать вывод _to_timestamp
:
>>> tt_reg.score(X, y)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Users\actualpanda\.virtualenvs\SomeProject--3333Ox_\lib\site-packages\sklearn\base.py", line 435, in score
return r2_score(y, y_pred, sample_weight=sample_weight,
File "C:\Users\actualpanda\.virtualenvs\SomeProject--3333Ox_\lib\site-packages\sklearn\metrics\_regression.py", line 591, in r2_score
numerator = (weight * (y_true - y_pred) ** 2).sum(axis=0,
TypeError: ufunc 'square' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
Чтобы получить оценку, пользователь должен знать внутреннюю часть tt_reg.regressor_
.
>>> tt_reg.regressor_.score(X, y.to_series().sub(pd.Timestamp(0)).dt.total_seconds())
1.0
Вопрос
Существует ли реальный способ создания надежных, удобных в использовании регуляторов sklearn, которые могут работать с нечисленными c целями и не протекать изнутри