Создайте регрессор с нечисловыми c целями, которые внутренне преобразуются в числовые c значения - PullRequest
1 голос
/ 23 апреля 2020

Я хочу построить модель линейной регрессии, которая принимает временные метки в качестве целей и использует секунды с 1970-01-01 00:00:00 (pd.Timestamp(0)) внутри. predict должен возвращать метки времени.

Я пытался сделать эту работу с TransformedTargetRegressor. Тем не менее, я сталкиваюсь с TypeError: invalid type promotion Я не могу решить.

Демонстрационный код:

import pandas as pd
import numpy as np
from sklearn.compose import TransformedTargetRegressor
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import FunctionTransformer

# helper function to convert a 2D numpy array of seconds to a 2D array of timestamps
def _to_timestamp(seconds: np.ndarray):
    return pd.DataFrame(seconds).apply(pd.to_datetime, unit='s').values

# helper function 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

# build transformer from helper functions
TimeTransformer = FunctionTransformer(
    func=_to_float,
    inverse_func=_to_timestamp,
    validate=True,
    check_inverse=True
)

# make a LinearRegression chained with a TimeTransformer
def TimeTargetLinearRegression():
    return TransformedTargetRegressor(
        regressor=LinearRegression(),
        transformer=TimeTransformer
    )

# test run
if __name__ == '__main__':
    model = TimeTargetLinearRegression()
    X = np.array([[1], [2], [3]], dtype=float)
    y = pd.date_range(start=0, periods=3, freq='s')
    model.fit(X=X, y=y) # raises TypeError

Вывод:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2019.3.3\plugins\python-ce\helpers\pydev\_pydev_bundle\pydev_umd.py", line 197, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2019.3.3\plugins\python-ce\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "C:/Users/actualpanda/.PyCharmCE2019.3/config/scratches/scratch2.py", line 36, in <module>
    model.fit(X=X, y=y) # raises TypeError
  File "C:\Users\actualpanda\.virtualenvs\SomeProject--3333Ox_\lib\site-packages\sklearn\compose\_target.py", line 185, in fit
    self._fit_transformer(y_2d)
  File "C:\Users\actualpanda\.virtualenvs\SomeProject--3333Ox_\lib\site-packages\sklearn\compose\_target.py", line 139, in _fit_transformer
    self.transformer_.fit(y)
  File "C:\Users\actualpanda\.virtualenvs\SomeProject--3333Ox_\lib\site-packages\sklearn\preprocessing\_function_transformer.py", line 125, in fit
    self._check_inverse_transform(X)
  File "C:\Users\actualpanda\.virtualenvs\SomeProject--3333Ox_\lib\site-packages\sklearn\preprocessing\_function_transformer.py", line 102, in _check_inverse_transform
    if not _allclose_dense_sparse(X[idx_selected], X_round_trip):
  File "C:\Users\actualpanda\.virtualenvs\SomeProject--3333Ox_\lib\site-packages\sklearn\utils\validation.py", line 1288, in _allclose_dense_sparse
    return np.allclose(x, y, rtol=rtol, atol=atol)
  File "<__array_function__ internals>", line 5, in allclose
  File "C:\Users\actualpanda\.virtualenvs\SomeProject--3333Ox_\lib\site-packages\numpy\core\numeric.py", line 2159, in allclose
    res = all(isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan))
  File "<__array_function__ internals>", line 5, in isclose
  File "C:\Users\actualpanda\.virtualenvs\SomeProject--3333Ox_\lib\site-packages\numpy\core\numeric.py", line 2254, in isclose
    dt = multiarray.result_type(y, 1.)
  File "<__array_function__ internals>", line 5, in result_type
TypeError: invalid type promotion

Я ищу ответ который объясняет / разрешает TypeError и - в случае моего подхода некорректен - предлагает метод построения регрессора, который может обрабатывать нечисловые c цели (данные функции для преобразования и обратного преобразования).

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

1 Ответ

1 голос
/ 23 апреля 2020

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

Это сравнение "туда-обратно" происходит, когда вы устанавливаете check_inverse=True, и оно передается np.isclose. Это приводит к ошибке.

y = pd.date_range(start=0, periods=3, freq='s')
y_ = TimeTransformer.inverse_func(TimeTransformer.func(y))

np.isclose(y, y_)
# raises:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-68-90ab2804af58> in <module>
----> 1 np.isclose(y, y_)

<__array_function__ internals> in isclose(*args, **kwargs)

C:\Anaconda3\lib\site-packages\numpy\core\numeric.py in isclose(a, b, rtol, atol, equal_nan)
   2264     # This will cause casting of x later. Also, make sure to allow subclasses
   2265     # (e.g., for numpy.ma).
-> 2266     dt = multiarray.result_type(y, 1.)
   2267     y = array(y, dtype=dt, copy=False, subok=True)
   2268

<__array_function__ internals> in result_type(*args, **kwargs)

TypeError: invalid type promotion

Фактическая ошибка исходит из функции result_type C. Это проверяет, каким будет тип результата операции, и используется для выделения новых массивов.

y2 = np.array(y)
y_ == y2 
# returns:
array([[ True],
       [ True],
       [ True]])

np.isclose(yy, y_)
# raises: TypeError: invalid type promotion

np.core.multiarray.result_type(y_, 1.)
# raises: TypeError: invalid type promotion

Я предполагаю, что np.datetime64 dtype не реализован для этого метода.

Я открыл вопрос на странице github.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...