Подтвердить что ты не робот

Scikit-learn predict_proba дает неправильные ответы

Это следующий вопрос от Как узнать, какие классы представлены в массиве return из pred_proba в Scikit-learn

В этом вопросе я привел следующий код:

>>> import sklearn
>>> sklearn.__version__
'0.13.1'
>>> from sklearn import svm
>>> model = svm.SVC(probability=True)
>>> X = [[1,2,3], [2,3,4]] # feature vectors
>>> Y = ['apple', 'orange'] # classes
>>> model.fit(X, Y)
>>> model.predict_proba([1,2,3])
array([[ 0.39097541,  0.60902459]])

Я обнаружил в этом вопросе этот результат представляет вероятность точки, принадлежащей каждому классу, в порядке, заданном model.classes _

>>> zip(model.classes_, model.predict_proba([1,2,3])[0])
[('apple', 0.39097541289393828), ('orange', 0.60902458710606167)]

Итак... этот ответ, если он правильно интерпретируется, говорит, что точка, вероятно, является "оранжевой" (с довольно низким доверием из-за крошечного объема данных). Но интуитивно этот результат явно неверен, так как указанная точка идентична данным обучения для "яблока". Чтобы быть уверенным, я также проверил обратное:

>>> zip(model.classes_, model.predict_proba([2,3,4])[0])
[('apple', 0.60705475211840931), ('orange', 0.39294524788159074)]

Опять же, очевидно, неверно, но в другом направлении.

Наконец, я попробовал это с точками, которые были намного дальше.

>>> X = [[1,1,1], [20,20,20]] # feature vectors
>>> model.fit(X, Y)
>>> zip(model.classes_, model.predict_proba([1,1,1])[0])
[('apple', 0.33333332048410247), ('orange', 0.66666667951589786)]

Опять же, модель предсказывает неправильные вероятности. НО, функция model.predict получает это правильно!

>>> model.predict([1,1,1])[0]
'apple'

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

-------- UPDATE --------

Хорошо, поэтому я сделал еще несколько "экспериментов" в этом: поведение pred_proba сильно зависит от "n", но не предсказуемым образом!

>>> def train_test(n):
...     X = [[1,2,3], [2,3,4]] * n
...     Y = ['apple', 'orange'] * n
...     model.fit(X, Y)
...     print "n =", n, zip(model.classes_, model.predict_proba([1,2,3])[0])
... 
>>> train_test(1)
n = 1 [('apple', 0.39097541289393828), ('orange', 0.60902458710606167)]
>>> for n in range(1,10):
...     train_test(n)
... 
n = 1 [('apple', 0.39097541289393828), ('orange', 0.60902458710606167)]
n = 2 [('apple', 0.98437355278112448), ('orange', 0.015626447218875527)]
n = 3 [('apple', 0.90235408180319321), ('orange', 0.097645918196806694)]
n = 4 [('apple', 0.83333299908143665), ('orange', 0.16666700091856332)]
n = 5 [('apple', 0.85714254878984497), ('orange', 0.14285745121015511)]
n = 6 [('apple', 0.87499969631893626), ('orange', 0.1250003036810636)]
n = 7 [('apple', 0.88888844127886335), ('orange', 0.11111155872113669)]
n = 8 [('apple', 0.89999988018127364), ('orange', 0.10000011981872642)]
n = 9 [('apple', 0.90909082368682159), ('orange', 0.090909176313178491)]

Как мне безопасно использовать эту функцию в моем коде? По крайней мере, существует ли какое-либо значение n, для которого будет гарантировано согласие с результатом модели. Представьте?

4b9b3361

Ответ 1

если вы используете svm.LinearSVC() в качестве оценки и .decision_function() (что похоже на svm.SVC.predict_proba()) для сортировки результатов от наиболее вероятного класса до наименее вероятного. это согласуется с функцией .predict(). Плюс, эта оценка быстрее и дает почти те же результаты с svm.SVC()

единственным недостатком для вас может быть то, что .decision_function() дает знаковое значение sth, например, между -1 и 3 вместо значения вероятности. но он согласуется с предсказанием.

Ответ 2

predict_probas использует функцию масштабирования Platt для libsvm для вызова вероятности, см.

Таким образом, гипотезы о гиперплоскости и калибровка проба могут не совпадать, особенно если у вас всего 2 образца в вашем наборе данных. Странно, что внутренняя перекрестная проверка, сделанная libsvm для масштабирования вероятностей, в этом случае не подлежит (явно). Возможно, это ошибка. Нужно было бы погрузиться в код масштабирования Platt libsvm, чтобы понять, что происходит.

Ответ 3

Существует некоторая путаница в отношении того, что на самом деле делает pred_proba. Он не прогнозирует вероятности, как предполагает название, но выводит расстояния. В примере яблока против апельсина 0,39097541, 0,60902459 кратчайшее расстояние 0.39097541 - класс яблока. что противоречит интуиции. вы смотрите на наивысшую вероятность, но это не так.

Другой источник путаницы проистекает из того, что pred_proba действительно соответствует жестким меткам, а не порядку классов, от 0..n последовательно. Кажется, что Scikit перетасовывает классы, но их можно сопоставить.

вот как это работает.

   say we have 5 classes with labels:
   classifier.classes_ = [0 1 2 3 4]
   target names = ['1', '2', '3', '6', '8']

предсказанные метки [2 0 1 0 4]

    classifier.predict_proba
    [[ 0.20734121  0.20451986  0.17262553  0.20768649  0.20782692]
     [ 0.19099348  0.2018391   0.20222314  0.20136784  0.20357644]
     [ 0.19982284  0.19497121  0.20399376  0.19824784  0.20296435]
     [ 0.19884577  0.1999416   0.19998889  0.20092702  0.20029672]
     [ 0.20328893  0.2025956   0.20500402  0.20383255  0.1852789 ]]

    Confusion matrix:
    [[1 0 0 0 0]
     [0 1 0 0 0]
     [0 0 1 0 0]
     [1 0 0 0 0]
     [0 0 0 0 1]]

    y_test [2 0 1 3 4]
    pred [2 0 1 0 4]
    classifier.classes_ = [0 1 2 3 4]

ничего, кроме третьего класса, является совпадением. согласно прогнозируемым меткам в см, класс 0 предсказан, а фактический класс       0 argmax (pred_prob). Но его отображение на

     y_test [2 0 1 3 4]

поэтому найдите второй класс

    0              1             2          3          4
    [ 0.20734121  0.20451986  0.17262553  0.20768649  0.20782692]
    and the winner is **0.17262553**

сделайте это снова. посмотрите на результат вычисления ошибки 4, где фактический lebel 4, предсказанный 1 в соответствии с cm.

    BUT y_test [2 0 1 3 4] pred [2 0 1 0 4]
    which translates to actual label 3 predicted label 0
    0             1             2            3        4
    ]0.19884577  0.1999416   0.19998889  0.20092702  0.20029672]
    look at label number 0, and the winner is **0.19884577**

Это мои 0,02.