8 votes

Probabilité de Naive Bayes toujours 1

J'ai commencé à utiliser sklearn.naive_bayes.GaussianNB pour la classification de textes, et j'ai obtenu de bons résultats initiaux. Je veux utiliser la probabilité renvoyée par le classificateur comme une mesure de confiance, mais le système de classification de l predict_proba() renvoie toujours "1.0" pour la classe choisie, et "0.0" pour toutes les autres.

Je sais (d'après ici ) que " ...les sorties de probabilité de predict_proba ne doivent pas être prises trop au sérieux ", mais jusqu'à quel point ? ! Le classificateur peut se tromper finance-investissement o accords-cordes mais le predict_proba() La sortie ne montre aucun signe d'hésitation...

Un peu de contexte :
- J'ai utilisé sklearn.feature_extraction.text.TfidfVectorizer pour l'extraction de caractéristiques, sans, pour commencer, restreindre le vocabulaire avec mots-clés o min/max_df --> J'ai obtenu de très gros vecteurs.
- J'ai entraîné le classifieur sur un arbre hiérarchique de catégories (peu profond : pas plus de 3 couches) avec 7 textes (catégorisés manuellement) par catégorie. Pour l'instant, c'est le cas, flat la formation : Je ne tiens pas compte de la hiérarchie.

Le résultat GaussianNB est très gros (~300MB), et la prédiction est plutôt lente : environ 1 seconde pour un texte.
Cela peut-il être lié ? Les énormes vecteurs sont-ils à l'origine de tout cela ?
Comment obtenir des prédictions significatives ? Dois-je utiliser un classificateur différent ?

Voici le code que j'utilise :

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import GaussianNB
import numpy as np
from sklearn.externals import joblib

Vectorizer = TfidfVectorizer(input = 'content')
vecs = Vectorizer.fit_transform(TextsList) # ~2000 strings
joblib.dump(Vectorizer, 'Vectorizer.pkl') 
gnb = GaussianNB()
Y = np.array(TargetList) # ~2000 categories 
gnb.fit(vecs.toarray(), Y)
joblib.dump(gnb, 'Classifier.pkl') 
...

#In a different function:
Vectorizer = joblib.load('Vectorizer.pkl')
Classifier = joblib.load('Classifier.pkl')
InputList = [Text] # One string
Vec = Vectorizer.transform(InputList)
Probs = Classifier.predict_proba([Vec.toarray()[0]])[0]
MaxProb = max(Probs)
MaxProbIndex = np.where(Probs==MaxProb)[0][0]
Category = Classifier.classes_[MaxProbIndex]
result = (Category, MaxProb)  

Mise à jour :
En suivant les conseils ci-dessous, j'ai essayé MultinomialeNB & Régression logistique . Ils renvoient tous deux des probabilités variables, et sont meilleurs à tous égards pour ma tâche : classification beaucoup plus précise, objets plus petits en mémoire et vitesse beaucoup plus élevée ( MultinomialeNB est rapide comme l'éclair !).

J'ai maintenant un nouveau problème : les probabilités renvoyées sont très faibles - généralement de l'ordre de 0,004-0,012. Cela concerne la catégorie prédite/gagnante (et la classification est précise).

14voto

larsmans Points 167484

"...les sorties de probabilité de predict_proba ne doivent pas être prises trop au sérieux"

Je suis le gars qui a écrit ça. Le fait est que Bayes naïf tend à prédire des probabilités qui sont presque toujours soit très proches de zéro, soit très proches de un ; exactement le comportement que vous observez. La régression logistique ( sklearn.linear_model.LogisticRegression o sklearn.linear_model.SGDClassifier(loss="log") ) produit des probabilités plus réalistes.

L'objet GaussianNB résultant est très gros (~300MB), et la prédiction est plutôt lente : environ 1 seconde pour un texte.

C'est parce que GaussianNB est un modèle non linéaire et ne prend pas en charge les matrices éparses (ce que vous avez déjà découvert, puisque vous utilisez le modèle toarray ). Utilisez MultinomialNB , BernoulliNB ou la régression logistique, qui sont beaucoup plus rapides en termes de temps de prédiction et également plus petites. Leurs hypothèses par rapport à l'entrée sont également plus réalistes pour les caractéristiques des termes. GaussianNB n'est vraiment pas un bon estimateur pour la classification de textes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X