Scikit learn: как проверить значение коэффициентов

Я пытался сделать LR с SKLearn для довольно большого набора данных с ~ 600 манекенами и только несколькими переменными интервалов (и 300 К строк в моем наборе данных), и возникающая в результате матрица смешения выглядит подозрительной. Я хотел проверить значение возвращаемых коэффициентов и ANOVA, но я не могу найти, как получить к нему доступ. Это вообще возможно? И какова лучшая стратегия для данных, которая содержит множество фиктивных переменных? Большое спасибо!

Ответ 1

Scikit-learn сознательно не поддерживает статистический вывод. Если вы хотите, чтобы тесты значимости коэффициентов "вне коробки" (и многое другое), вы можете использовать Logit от Statsmodels. Этот пакет имитирует интерфейсы glm в R, поэтому вы можете найти его знакомым.

Если вы все еще хотите придерживаться scikit-learn LogisticRegression, вы можете использовать асимптотическое приближение к распределению максимальных вероятностных оценок. Точно, для вектора оценок максимального правдоподобия theta его матрица дисперсии-ковариации может быть оценена как inverse(H), где H - матрица Гессиана лог-правдоподобия при theta. Именно это выполняет следующая функция:

import numpy as np
from scipy.stats import norm
from sklearn.linear_model import LogisticRegression

def logit_pvalue(model, x):
    """ Calculate z-scores for scikit-learn LogisticRegression.
    parameters:
        model: fitted sklearn.linear_model.LogisticRegression with intercept and large C
        x:     matrix on which the model was fit
    This function uses asymtptics for maximum likelihood estimates.
    """
    p = model.predict_proba(x)
    n = len(p)
    m = len(model.coef_[0]) + 1
    coefs = np.concatenate([model.intercept_, model.coef_[0]])
    x_full = np.matrix(np.insert(np.array(x), 0, 1, axis = 1))
    ans = np.zeros((m, m))
    for i in range(n):
        ans = ans + np.dot(np.transpose(x_full[i, :]), x_full[i, :]) * p[i,1] * p[i, 0]
    vcov = np.linalg.inv(np.matrix(ans))
    se = np.sqrt(np.diag(vcov))
    t =  coefs/se  
    p = (1 - norm.cdf(abs(t))) * 2
    return p

# test p-values
x = np.arange(10)[:, np.newaxis]
y = np.array([0,0,0,1,0,0,1,1,1,1])
model = LogisticRegression(C=1e30).fit(x, y)
print(logit_pvalue(model, x))

# compare with statsmodels
import statsmodels.api as sm
sm_model = sm.Logit(y, sm.add_constant(x)).fit(disp=0)
print(sm_model.pvalues)
sm_model.summary()

Выходы print() идентичны, и они являются коэффициентами p-значений.

[ 0.11413093  0.08779978]
[ 0.11413093  0.08779979]

sm_model.summary() также печатает хорошо отформатированную HTML-сводку.