Почему статистические модели не могут воспроизвести мои результаты логистической регрессии R?

Я не понимаю, почему мои модели логистической регрессии в R и статистические модели не согласуются.

Если я подготовлю некоторые данные в R с помощью

# From https://courses.edx.org/c4x/MITx/15.071x/asset/census.csv
library(caTools) # for sample.split
census = read.csv("census.csv")
set.seed(2000)
split = sample.split(census$over50k, SplitRatio = 0.6)
censusTrain = subset(census, split==TRUE)
censusTest = subset(census, split==FALSE)

а затем запустите логистическую регрессию с

CensusLog1 = glm(over50k ~., data=censusTrain, family=binomial)

Я вижу результаты вроде

                                           Estimate Std. Error z value Pr(>|z|)    
(Intercept)                              -8.658e+00  1.379e+00  -6.279 3.41e-10 ***
age                                       2.548e-02  2.139e-03  11.916  < 2e-16 ***
workclass Federal-gov                     1.105e+00  2.014e-01   5.489 4.03e-08 ***
workclass Local-gov                       3.675e-01  1.821e-01   2.018 0.043641 *  
workclass Never-worked                   -1.283e+01  8.453e+02  -0.015 0.987885    
workclass Private                         6.012e-01  1.626e-01   3.698 0.000218 ***
workclass Self-emp-inc                    7.575e-01  1.950e-01   3.884 0.000103 ***
workclass Self-emp-not-inc                1.855e-01  1.774e-01   1.046 0.295646    
workclass State-gov                       4.012e-01  1.961e-01   2.046 0.040728 *  
workclass Without-pay                    -1.395e+01  6.597e+02  -0.021 0.983134   
...

но я использую те же данные в Python, сначала экспортируя из R с помощью

write.csv(censusTrain,file="traincensus.csv")
write.csv(censusTest,file="testcensus.csv")

а затем импортировать в Python с помощью

import pandas as pd

census = pd.read_csv("census.csv")
census_train = pd.read_csv("traincensus.csv")
census_test = pd.read_csv("testcensus.csv")

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

Если я просто попытаюсь

import statsmodels.api as sm

census_log_1 = sm.Logit.from_formula(f, census_train).fit()

Я получаю сообщение об ошибке:

ValueError: operands could not be broadcast together with shapes (19187,2) (19187,) 

Даже если подготовить данные с помощью patsy, используя

import patsy
f = 'over50k ~ ' + ' + '.join(list(census.columns)[:-1])
y, X = patsy.dmatrices(f, census_train, return_type='dataframe')

пытающийся

census_log_1 = sm.Logit(y, X).fit()

приводит к той же ошибке. Единственный способ избежать ошибок — использовать use GLM

census_log_1 = sm.GLM(y, X, family=sm.families.Binomial()).fit()

но это приводит к результатам, которые полностью отличаются от результатов (как я думал) эквивалентного R API:

                                                   coef    std err          t      P>|t|      [95.0% Conf. Int.]
----------------------------------------------------------------------------------------------------------------
Intercept                                       10.6766      5.985      1.784      0.074        -1.055    22.408
age                                             -0.0255      0.002    -11.916      0.000        -0.030    -0.021
workclass[T. Federal-gov]                       -0.9775      4.498     -0.217      0.828        -9.794     7.839
workclass[T. Local-gov]                         -0.2395      4.498     -0.053      0.958        -9.055     8.576
workclass[T. Never-worked]                       8.8346    114.394      0.077      0.938      -215.374   233.043
workclass[T. Private]                           -0.4732      4.497     -0.105      0.916        -9.288     8.341
workclass[T. Self-emp-inc]                      -0.6296      4.498     -0.140      0.889        -9.446     8.187
workclass[T. Self-emp-not-inc]                  -0.0576      4.498     -0.013      0.990        -8.873     8.758
workclass[T. State-gov]                         -0.2733      4.498     -0.061      0.952        -9.090     8.544
workclass[T. Without-pay]                       10.0745     85.048      0.118      0.906      -156.616   176.765
...

Почему логистическая регрессия в Python приводит к ошибкам и результатам, отличным от результатов, полученных в R? Являются ли эти API на самом деле не эквивалентными (у меня они работали раньше, чтобы давать идентичные результаты)? Требуется ли дополнительная обработка наборов данных, чтобы их можно было использовать в статистических моделях?


person orome    schedule 28.03.2014    source источник
comment
Я не вижу age в ваших статистических моделях...?   -  person Ben Bolker    schedule 28.03.2014
comment
Можете ли вы воспроизвести вышеуказанные различия на небольшом примере, который можно воспроизвести?   -  person Akavall    schedule 28.03.2014
comment
@BenBolker: добавлено. Результаты были упорядочены по-разному в Python.   -  person orome    schedule 28.03.2014
comment
@Akavall: используйте связанные данные.   -  person orome    schedule 28.03.2014
comment
нет времени вникать, но я бы предположил, что разница в контрастах / фиктивном кодировании. Получаете ли вы сопоставимые ответы, если используете только непрерывные предикторы?   -  person Ben Bolker    schedule 28.03.2014
comment
См. также stackoverflow.com/questions/19612577/   -  person Dieter Menne    schedule 28.03.2014
comment
о ValueError: y должен быть одномерным для Logit, в зависимости от формата исходных данных, patsy может вернуть фиктивную кодировку с двумя столбцами. Результаты GLM выглядят так, как будто у них перевернутый знак, что означает, что кодировка 0, 1 перевернута по сравнению с R.   -  person Josef    schedule 28.03.2014


Ответы (1)


Ошибка связана с тем, что patsy расширяет переменную LHS до полного контраста лечения. Logit не обрабатывает это, как указано в строке документации, но, как вы видите, GLM с биномиальным семейством справляется.

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

Вы можете использовать logit, выполнив следующий шаг предварительной обработки.

census = census.replace(to_replace={'over50k' : {' <=50K' : 0, ' >50K' : 1}})

Также обратите внимание, что решатель по умолчанию для логита, похоже, не очень хорошо работает для этой проблемы. Это сталкивается с сингулярной матричной проблемой. Действительно, количество условий для этой проблемы огромно, и то, что вы получаете в R, может не быть полностью конвергентной моделью. Вы можете попробовать уменьшить количество фиктивных переменных.

[~/]
[73]: np.linalg.cond(mod.exog)
[73]: 4.5139498536894682e+17

Мне пришлось использовать следующее, чтобы получить решение

mod = sm.formula.logit(f, data=census)
res = mod.fit(method='bfgs', maxiter=1000)    

Некоторые из ваших клеток становятся очень маленькими. Это усугубляется другими разреженными фиктивными переменными.

[~/]
[81]: pd.Categorical(census.occupation).describe()
[81]: 
                    counts     freqs
levels                              
?                    1816  0.056789
Adm-clerical         3721  0.116361
Armed-Forces            9  0.000281
Craft-repair         4030  0.126024
Exec-managerial      3992  0.124836
Farming-fishing       989  0.030928
Handlers-cleaners    1350  0.042217
Machine-op-inspct    1966  0.061480
Other-service        3212  0.100444
Priv-house-serv       143  0.004472
Prof-specialty       4038  0.126274
Protective-serv       644  0.020139
Sales                3584  0.112077
Tech-support          912  0.028520
Transport-moving     1572  0.049159
person jseabold    schedule 28.03.2014
comment
Я связал полный вывод. - person orome; 28.03.2014
comment
У вас есть NA в вашем выводе R. Я предполагаю, что он пропускает некоторые столбцы из-за мультиколлинеарности, в этих ячейках недостаточно наблюдений для оценки (что-то вроде того же), или в вашей модели R есть проблемы со сходимостью, которые вы должны проверить. Мы не удаляем столбцы по умолчанию. Как я уже упоминал, вы можете попробовать удалить или объединить определенные категории для ваших фиктивных переменных. Используйте описать, как я сделал выше, чтобы увидеть, насколько редки ваши категории. Смотрите и другие мои комментарии выше. - person jseabold; 28.03.2014
comment
По сути, у вас есть проблемы с моделированием и данными. В идеальных условиях они должны давать один и тот же результат, но вам придется выяснить, почему они этого не делают. Если это что-то вроде R пропускает столбец из-за предполагаемой мультиколлинеарности, а statsmodels нет, то это то, что мы можем посмотреть. - person jseabold; 28.03.2014
comment
Я бы не беспокоился об этом, за исключением того, что я получаю высокую точность в R, и в курсовом упражнении, из которого это взято, говорится, что мы только что видели, как модель логистической регрессии для этих данных достигает высокой точности. Более того, значения переменных дают нам возможность оценить, какие переменные имеют отношение к этой задаче прогнозирования. Так что это не модель мусора для демонстрации проблем с переменными. Я ожидаю, что оба инструмента дадут одинаковый результат. - person orome; 28.03.2014
comment
Кстати, если непонятно. Я совершенно новичок в R и аналитике. Я развил мгновенную неприязнь к R, и мне бы ОЧЕНЬ понравилось, чтобы статистические модели взяли верх. Курс, который я изучаю, преподается на R, и я работал (в основном успешно) над тем, чтобы сделать это на Python, но часто натыкаюсь на такие камни преткновения, как этот, когда мне приходится возвращаться к R, что всегда оставляет у меня ощущение немного грязный. - person orome; 28.03.2014
comment
Высокая точность при наличии NaN в результирующих коэффициентах вызывает у меня подозрения. Для меня это указывает на то, что еще предстоит проделать работу по моделированию. На самом деле я не использовал ваш сплит поезд/тест. Я просто использовал весь набор данных. Я подал проблему, чтобы изучить это подробнее, но подозреваю, что это что-то в коде . Моделирование должно быть таким же, если только R не делает что-то тонкое. - person jseabold; 29.03.2014
comment
Спасибо! Я не гарантирую высокую точность модели R; Я просто (наивно) цитирую материалы корса. Я рад слышать, что моделирование должно быть таким же (по крайней мере, мои ожидания оправдались), и с нетерпением жду возможности увидеть, чем закончится проблема. - person orome; 29.03.2014
comment
Примечание. Даже если параметры не идентифицированы и алгоритм выбирает одно решение, вы все равно можете получить хороший предиктор, если линейная комбинация независимых переменных не имеет значения или остается неизменной в ваших случаях вне выборки. (statsmodels делает что-то подобное в линейных моделях, когда мы используем для решения обобщенную обратную функцию pinv. - person Josef; 29.03.2014