sklearn.linear_model.LogisticRegression возвращает разные коэффициенты каждый раз, хотя задано значение random_state

#python #scikit-learn #logistic-regression

#python #scikit-learn #логистическая регрессия

Вопрос:

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

Каждый раз, когда я выполняю «подгонку», я получаю разные коэффициенты, пример:

 classifier_instance.fit(train_examples_features, train_examples_labels)
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, penalty='l2', random_state=1, tol=0.0001)

>>> classifier_instance.raw_coef_
array([[ 0.071101940040772596  ,  0.05143724979709707323,  0.071101940040772596  , -0.04089477198935181912, -0.0407380696457252528 ,  0.03622160087086594843,  0.01055345545606742319,
         0.01071861708285645406, -0.36248634699444892693, -0.06159019047096317423,  0.02370064668025737009,  0.02370064668025737009, -0.03159781822495803805,  0.11221150783553821006,
         0.02728295348681779309,  0.071101940040772596  ,  0.071101940040772596  ,  0.                    ,  0.10882033432637286396,  0.64630314505709030026,  0.09617956519989406816,
         0.0604133873444507169 ,  0.                    ,  0.04111685986987245051,  0.                    ,  0.                    ,  0.18312324521915510078,  0.071101940040772596  ,
         0.071101940040772596  ,  0.                    , -0.59561802045324663268, -0.61490898457874587635,  1.07812569991461248975,  0.071101940040772596  ]])

classifier_instance.fit(train_examples_features, train_examples_labels)
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, penalty='l2', random_state=1, tol=0.0001)

>>> classifier_instance.raw_coef_
array([[ 0.07110193825129411394,  0.05143724970282205489,  0.07110193825129411394, -0.04089477178162870957, -0.04073806899140903354,  0.03622160048165772028,  0.010553455400928528  ,
         0.01071860364222424096, -0.36248635488413910588, -0.06159021545062405567,  0.02370064608376460866,  0.02370064608376460866, -0.03159783710841745225,  0.11221149816037970237,
         0.02728295411479400578,  0.07110193825129411394,  0.07110193825129411394,  0.                    ,  0.10882033461822394893,  0.64630314701686075729,  0.09617956493834901865,
         0.06041338563697066372,  0.                    ,  0.04111676713793514099,  0.                    ,  0.                    ,  0.18312324401049043243,  0.07110193825129411394,
         0.07110193825129411394,  0.                    , -0.59561803345113684127, -0.61490899867901249731,  1.07812569539027203191,  0.07110193825129411394]])
  

Я использую версию 0.14, в документах указано: «Базовая реализация C использует генератор случайных чисел для выбора функций при подгонке модели. Таким образом, нередко для одних и тех же входных данных получаются несколько разные результаты. Если это произойдет, попробуйте использовать меньший параметр tol . «

Я думал, что установка случайного состояния обеспечит отсутствие случайности, но, видимо, это не так. Это ошибка или желаемое поведение?

Комментарии:

1. Я также заметил, что иногда это поведение меняется между «запусками», один раз, когда я запускаю повторные вызовы python для подгонки, генерируются разные коэффициенты, а в других случаях я перезапускаю python, которого я не делаю. Очень странно.

Ответ №1:

На самом деле это нежелательно, но это известная проблема, которую очень сложно исправить. Дело в том, что LogisticRegression модели обучаются с помощью Liblinear, что не позволяет установить его случайное начальное значение полностью надежным способом. Когда вы явно устанавливаете random_state , прилагаются все усилия, чтобы установить случайное начальное значение Liblinear, но это может привести к сбою.

Комментарии:

1. Если необходимо иметь точно такие же коэффициенты, вы можете написать функцию get_logistic_regression_coef , которая соответствует модели и возвращает коэффициенты, а затем кэшировать ее с помощью sklearn.externals.joblib.Memory . Таким образом, он сохранит результаты на диск для данного ввода и перезагрузит их при втором вызове, если ввод не изменился.

2. Если при каждом запуске все цифры после, скажем, 6 знаков после запятой меняются, то по сути они бессмысленны, нет? как насчет просто округления коэффициентов после того, как они говорят 6 десятичных знаков? таким образом, результаты будут детерминированными.

3. @jonathans Все еще могут быть случайные случайности, которые вызывают большие различия. Я чувствую, что ваше предложение сводится к сокрытию проблемы, а не к ее решению (например, путем установки другого RNG в Liblinear, что сложно, но возможно).

4. Я согласен, на данный момент я прибегаю к тому, что я могу лично контролировать, и исправление этого непосредственно в Liblinear не является одной из вещей, которые, по моему мнению, я могу сделать.

5. Применимо ли это также к решателям ‘lbfgs’ и ‘newton-cg’?

Ответ №2:

Я тоже был озадачен этой проблемой, но в конце концов обнаружил, что numpy.random.seed() в дополнение к передаче также необходимо вызвать, чтобы установить состояние внутреннего RNG numpy random_state .

Это было протестировано с помощью sklearn 0.13.1.

Комментарии:

1. Это сработало для меня! Знаем ли мы, почему это работает? Возможно, функция srand внутри логистической регрессии использует глобальное случайное начальное значение numpy?

2. У меня это не сработало… Я использую sklearn 0.19.1. @P.C. какую версию sklearn вы использовали?

3. У меня оба заданы, но результат все еще меняется. Нужно ли устанавливать для них одно и то же значение или разные значения? какие-нибудь хитрости есть?