Я пытаюсь вручную предсказать модель логистической регрессии, используя коэффициент и перехват выходных данных из модели scikit-learn. Однако я не могу сопоставить свои прогнозы вероятности с методом predict_proba
из классификатора.
Я пытался:
from sklearn.datasets import load_iris
from scipy.special import expit
import numpy as np
X, y = load_iris(return_X_y=True)
clf = LogisticRegression(random_state=0).fit(X, y)
# use sklearn's predict_proba function
sk_probas = clf.predict_proba(X[:1, :])
# and attempting manually (using scipy's inverse logit)
manual_probas = expit(np.dot(X[:1], clf.coef_.T)+clf.intercept_)
# with a completely manual inverse logit
full_manual_probas = 1/(1+np.exp(-(np.dot(iris_test, iris_coef.T)+clf.intercept_)))
выходы:
>>> sk_probas
array([[9.81815067e-01, 1.81849190e-02, 1.44120963e-08]])
>>> manual_probas
array([[9.99352591e-01, 9.66205386e-01, 2.26583306e-05]])
>>> full_manual_probas
array([[9.99352591e-01, 9.66205386e-01, 2.26583306e-05]])
Мне кажется, что классы совпадают (используя np.argmax
), но вероятности разные. Что мне не хватает?
Выходы на manual_probas
показаны под выходами в вопросе.
В моем комментарии я вычесть максимум логитов от каждого логита: X[:1] - np.max(X[:1], axis=1)
. Не так, как ты. Я ожидаю, что эта модификация вернет значения, равные sk_probas
. Большинство реализаций softmax используют одинаковые приемы для предотвращения переполнения.
Извините, я пропустил, что вы изменили определение. Ваша формулировка дает что-то другое снова. Принятый ответ работает и объясняет, чего мне не хватало.
документация утверждает, что
For a multi_class problem, if multi_class is set to be “multinomial” the softmax function is used to find the predicted probability of each class
То есть, чтобы получить те же значения, что и sklearn, вам нужно нормализовать с помощью softmax, например:
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
import numpy as np
X, y = load_iris(return_X_y=True)
clf = LogisticRegression(random_state=0, max_iter=1000).fit(X, y)
decision = np.dot(X[:1], clf.coef_.T)+clf.intercept_
print(clf.predict_proba(X[:1]))
print(np.exp(decision) / np.exp(decision).sum())
Чтобы использовать сигмоиды вместо этого, вы можете сделать это следующим образом:
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
import numpy as np
X, y = load_iris(return_X_y=True)
clf = LogisticRegression(random_state=0, max_iter=1000, multi_class='ovr').fit(X, y) # Notice the extra argument
full_manual_probas = 1/(1+np.exp(-(np.dot(X[:1], clf.coef_.T)+clf.intercept_)))
print(clf.predict_proba(X[:1]))
print(full_manual_probas / full_manual_probas.sum())
Какой результат вы получаете с
manual_probas = expit(np.dot(X[:1] - np.max(X[:1], axis=1), clf.coef_.T) + clf.intercept_)
?