#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. У меня оба заданы, но результат все еще меняется. Нужно ли устанавливать для них одно и то же значение или разные значения? какие-нибудь хитрости есть?