Используя линейную регрессию sklearn, как я могу ограничить вычисленные коэффициенты регрессии больше 0?

Я использую ссылку для sklearn здесь http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html, но нет возможности ограничить коэффициенты регрессии.

Кто-нибудь знает другой пакет на python для выполнения линейной регрессии с несколькими переменными и ограничения коэффициентов регрессии больше 0?

Вот код, который у меня есть.

'''data:
date        A            B              C
10/30/2015  0.063363323 -0.005218807    0.079777558
11/30/2015  -0.013171244    -0.008727599    0.010352028
12/31/2015  -0.017551268    8.09E-05    -0.020491923
1/29/2016   -0.042606469    0.052272139 -0.080362246
2/29/2016   -0.015224562    0.031250961 0.029988488
3/31/2016   0.058291876 -0.000238614    0.056727336
4/29/2016   0.000505675 -0.005325338    0.02854057
5/31/2016   0.012766515 0.008548162 -0.001631845
6/30/2016   -0.038981203    0.064236963 0.00570145
7/29/2016   0.033715429 0.024269606 0.02703294
8/31/2016   -0.002083837    -0.009439625    0.004129397
9/30/2016   -0.009825674    -0.01737909 -0.019251885
11/30/2016  0.0084733   -0.11668582 0.031928726
12/30/2016  0.017084282 -0.005553088    0.029372131
1/31/2017   0.014263947 0.004036504 0.00187079
2/28/2017   0.037375566 0.016081105 0.039331615
3/31/2017   -0.002494984    -0.005942793    -0.002097504
4/28/2017   -0.005054922    0.015685226 0.008243977
5/31/2017   0.002285393 0.020771375 0.002697755
6/30/2017   0.002841457 0.004886117 0.019202011
7/31/2017   0.014866638 -0.006900926    0.010126577
8/31/2017   -0.016647997    0.035687133 -0.008709075
9/29/2017   0.019523651 -0.022154361    0.020468398
10/31/2017  0.019407629 -0.000705663    0.016574416
11/30/2017  0.027486425 0.008008173 0.033427299
12/29/2017  0.007861222 0.018095096 0.017908809
1/31/2018   0.058702838 -0.032765285    0.05
'''

reg = linear_model.LinearRegression(fit_intercept=False)
reg.fit(df[['B', 'C']], df['A'])

print(reg.coef_)

# [ 0.67761268 -0.08845756]

Рабочий код ниже

from scipy.optimize import lsq_linear   

lb = 0
ub = np.Inf
res = lsq_linear(df[['B', 'C']], 
                 df['A'], 
                 bounds=(lb, ub))

print(res.x)

person Alex F    schedule 16.02.2018    source источник
comment
Некоторые из ваших значений y, например df ['A'], отрицательны. Возможно, попробуйте нормализовать ваши данные, например с помощью MinMaxScaler от sklearn?   -  person Thomas Fauskanger    schedule 16.02.2018


Ответы (1)


sklearn просто обертывает scipy's lstsq, который не поддерживает это.

Вы можете легко изменить код sklearn хотя:

    if sp.issparse(X):
        if y.ndim < 2:
            out = sparse_lsqr(X, y)
            self.coef_ = out[0]
            self._residues = out[3]
        else:
            # sparse_lstsq cannot handle y with shape (M, K)
            outs = Parallel(n_jobs=n_jobs_)(
                delayed(sparse_lsqr)(X, y[:, j].ravel())
                for j in range(y.shape[1]))
            self.coef_ = np.vstack(out[0] for out in outs)
            self._residues = np.vstack(out[3] for out in outs)
    else:
        self.coef_, self._residues, self.rank_, self.singular_ = \
            linalg.lstsq(X, y)
        self.coef_ = self.coef_.T

Просто замените lstsq / lsqr на scipy nnls (плотный !!!) или lsq_linear с границами, установленными вручную (для крупномасштабных: optimize.minimize с методом lbfgs - еще один кандидат, хотя вам нужно подготовить градиент, и есть как минимум два разных общих подхода: например, с использованием предварительно вычисленных: A.T*A, который теряет разреженность).

Примечание: эти методы сводят к минимуму различные функции (норма против квадрата нормы; 0,5 фактор против 1,0 фактора). Это не меняет результат с точки зрения найденного вектора, но цель, конечно, выглядит иначе, и вы должны позаботиться об этом (при необходимости).

person sascha    schedule 16.02.2018
comment
спасибо за помощь, выложил код, который написал выше. - person Alex F; 16.02.2018