sklearn TheilSenRegressor ValueError при установке fit_intercept = False для 1d регрессоров - PullRequest
0 голосов
/ 04 августа 2020

Я пытаюсь уместить строку (функция 1d) с перехватом 0, используя sklearn.linear_model.TheilSenRegressor, но когда я указываю fit_intercept=False, я получаю следующую ошибку:

ValueError: matmul: Входной операнд 1 не имеет достаточных размеров (имеет 0, gufun c ядро ​​с подписью (n?, K), (k, m?) -> (n?, M?) Требуется 1)

Это исходный пример в руководстве sklearn, который отлично работает, также указывая fit_intercept=False:

from sklearn.linear_model import TheilSenRegressor
from sklearn.datasets import make_regression
X, y = make_regression(n_samples=200, n_features=2, noise=4.0, random_state=0)
reg = TheilSenRegressor(random_state=0).fit(X, y)
reg.score(X, y)

Вот исходный пример, измененный для n_features=1, который работает со значением fit_intercept=True по умолчанию :

from sklearn.linear_model import TheilSenRegressor
from sklearn.datasets import make_regression
X, y = make_regression(n_samples=200, n_features=1, noise=4.0, random_state=0)
reg = TheilSenRegressor(random_state=0).fit(X, y)
reg.score(X, y)

Вот исходный пример, измененный для n_features=1 и fit_intercept=False, который вызывает сбой:

from sklearn.linear_model import TheilSenRegressor
from sklearn.datasets import make_regression
X, y = make_regression(n_samples=200, n_features=1, noise=4.0, random_state=0)
reg = TheilSenRegressor(random_state=0, fit_intercept=False).fit(X, y)
reg.score(X, y)

Сбои возникают как при подсчете баллов, так и при прогнозировании .

Что мне не хватает?

1 Ответ

1 голос
/ 05 августа 2020

Проверяя сценарий exmath.py под ~/lib/python3.6/site-packages/sklearn/utils/extmath.py, можно перейти к следующей функции

from scipy import linalg, sparse

def safe_sparse_dot(a, b, dense_output=False):
    """Dot product that handle the sparse matrix case correctly

    Parameters
    ----------
    a : array or sparse matrix
    b : array or sparse matrix
    dense_output : boolean, (default=False)
        When False, ``a`` and ``b`` both being sparse will yield sparse output.
        When True, output will always be a dense array.

    Returns
    -------
    dot_product : array or sparse matrix
        sparse if ``a`` and ``b`` are sparse and ``dense_output=False``.
    """
    if a.ndim > 2 or b.ndim > 2:
        if sparse.issparse(a):
            # sparse is always 2D. Implies b is 3D+
            # [i, j] @ [k, ..., l, m, n] -> [i, k, ..., l, n]
            b_ = np.rollaxis(b, -2)
            b_2d = b_.reshape((b.shape[-2], -1))
            ret = a @ b_2d
            ret = ret.reshape(a.shape[0], *b_.shape[1:])
        elif sparse.issparse(b):
            # sparse is always 2D. Implies a is 3D+
            # [k, ..., l, m] @ [i, j] -> [k, ..., l, j]
            a_2d = a.reshape(-1, a.shape[-1])
            ret = a_2d @ b
            ret = ret.reshape(*a.shape[:-1], b.shape[1])
        else:
            ret = np.dot(a, b)
    else:
        ret = a @ b

    if (sparse.issparse(a) and sparse.issparse(b)
            and dense_output and hasattr(ret, "toarray")):
        return ret.toarray()
    return ret

Обратите внимание, что он выполняет скалярное произведение между двумя массивами. Эта функция safe_sparse_dot вызывается изнутри при вызове reg.score() с параметрами X, self.coef_.T (в вашем примере это X и reg.coef_.T).

Случай n переменные регрессора с n> = 2

Теперь, , когда у вас есть две переменные регрессора, с fit_intercept=False. Например, тот, который вы ранее упомянули

X, y = make_regression(n_samples=200, n_features=2, noise=4.0, random_state=0)
reg = TheilSenRegressor(random_state=0, fit_intercept=False, verbose=True).fit(X, y)
reg.score(X, y)

, вы получите следующие формы ваших переменных:

X.shape
>>> (200, 2)
reg.coef_.T.shape
>>> (2,)

. Теперь, если вы вызовете функцию разреженных точек, вы получите результат, потому что (200,2) x (2,) - допустимое умножение.

safe_sparse_dot(X, reg.coef_.T)
>>> array([-3.11195300e+01,  3.97852518e+00,  3.83392622e+01,  6.10470897e+01,
          -4.93104975e+00, -7.79836353e+00, -2.92253822e+01,  1.95366691e+01,
          -2.53890049e+01,  2.31799242e+00, -4.29133706e+01, -2.64249217e+01,
          .....
          .....

Случай регрессора с одной переменной

Когда вы рассматриваете единственную переменную регрессии . Например,

X, y = make_regression(n_samples=200, n_features=1, noise=4.0, random_state=0)
reg = TheilSenRegressor(random_state=0, fit_intercept=False, verbose=True).fit(X, y)
reg.score(X, y)

, вы получите следующую ошибку:

ValueError: matmul: Input operand 1 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)

в основном потому, что reg.coef_ является скаляром и должен быть преобразован в 1d-массив, то есть reg.coef_.T.reshape(-1). Таким образом, операцию скалярного произведения можно назвать

safe_sparse_dot(X, reg.coef_.T.reshape(-1))
>>> array([-3.11195300e+01,  3.97852518e+00,  3.83392622e+01,  6.10470897e+01,
           -4.93104975e+00, -7.79836353e+00, -2.92253822e+01,  1.95366691e+01,
           -2.53890049e+01,  2.31799242e+00, -4.29133706e+01, -2.64249217e+01,
          ....

Я не знаю, поднималась ли уже эта проблема, но вы можете опубликовать ее на странице github scikit-learn.

...