web-dev-qa-db-de.com

Wie bekomme ich die informativsten Funktionen für Klassifizierer von Scikit-Learn?

Die Klassifizierer in maschinellen Lernpaketen wie liblinear und nltk bieten die Methode show_most_informative_features() an, die für das Debuggen von Funktionen sehr hilfreich ist:

viagra = None          ok : spam     =      4.5 : 1.0
hello = True           ok : spam     =      4.5 : 1.0
hello = None           spam : ok     =      3.3 : 1.0
viagra = True          spam : ok     =      3.3 : 1.0
casino = True          spam : ok     =      2.0 : 1.0
casino = None          ok : spam     =      1.5 : 1.0

Meine Frage ist, ob etwas Ähnliches für die Klassifikatoren in scikit-learn implementiert wird. Ich durchsuchte die Dokumentation, konnte aber nichts dergleichen finden.

Wenn es noch keine solche Funktion gibt, kennt jemand eine Problemumgehung, um zu diesen Werten zu gelangen?

Danke vielmals!

60
tobigue

Mit Hilfe von larsmans code habe ich diesen Code für den binären Fall gefunden:

def show_most_informative_features(vectorizer, clf, n=20):
    feature_names = vectorizer.get_feature_names()
    coefs_with_fns = sorted(Zip(clf.coef_[0], feature_names))
    top = Zip(coefs_with_fns[:n], coefs_with_fns[:-(n + 1):-1])
    for (coef_1, fn_1), (coef_2, fn_2) in top:
        print "\t%.4f\t%-15s\t\t%.4f\t%-15s" % (coef_1, fn_1, coef_2, fn_2)
45
tobigue

Die Klassifizierer selbst zeichnen keine Feature-Namen auf, sondern sehen nur numerische Arrays. Wenn Sie Ihre Features jedoch mit einem Vectorizer/CountVectorizer/TfidfVectorizer/DictVectorizer extrahiert haben, und Wenn Sie ein lineares Modell verwenden (z. B. LinearSVC oder Naive Bayes), können Sie denselben Trick anwenden, den das Beispiel für die Dokumentklassifizierung verwendet. Beispiel ( ungetestet , kann einen oder zwei Fehler enthalten):

def print_top10(vectorizer, clf, class_labels):
    """Prints features with the highest coefficient values, per class"""
    feature_names = vectorizer.get_feature_names()
    for i, class_label in enumerate(class_labels):
        top10 = np.argsort(clf.coef_[i])[-10:]
        print("%s: %s" % (class_label,
              " ".join(feature_names[j] for j in top10)))

Dies ist eine Klassifizierung für mehrere Klassen. Für den Binärfall sollten Sie meines Erachtens nur clf.coef_[0] verwenden. Möglicherweise müssen Sie den class_labels sortieren.

58
Fred Foo

Um ein Update hinzuzufügen, unterstützt RandomForestClassifier jetzt das .feature_importances_-Attribut. Dieses Attribut gibt an, wie viel von der beobachteten Varianz durch dieses Merkmal erklärt wird. Offensichtlich muss die Summe all dieser Werte <= 1 sein. 

Ich finde dieses Attribut sehr nützlich beim Durchführen von Feature-Engineering. 

Danke an das Team von scikit-learn und Mitwirkende für die Umsetzung!

edit: Dies funktioniert sowohl für RandomForest als auch für GradientBoosting. Daher unterstützen RandomForestClassifier, RandomForestRegressor, GradientBoostingClassifier und GradientBoostingRegressor dies. 

14
ClimbsRocks

Wir haben kürzlich eine Bibliothek ( https://github.com/TeamHG-Memex/eli5 ) veröffentlicht, die dies ermöglicht: Sie verarbeitet verschiedene Klassifizierer aus Scikit-Learn, Binär-/Multiklassen-Fälle und ermöglicht das Markieren von Text Integriert sich nach Feature-Werten in IPython usw.

9
Mikhail Korobov

Ich musste eigentlich die Funktionswichtigkeit in meinem NaiveBayes-Klassifizierer herausfinden und obwohl ich die obigen Funktionen verwendet habe, konnte ich die Funktionswichtigkeit nicht anhand der Klassen ermitteln. Ich habe die Dokumentation des Scikit Learn durchgelesen und die obigen Funktionen ein wenig angepasst, damit sie für mein Problem funktionieren. Hoffe es hilft dir auch!

def important_features(vectorizer,classifier,n=20):
class_labels = classifier.classes_
feature_names =vectorizer.get_feature_names()
topn_class1 = sorted(Zip(classifier.feature_count_[0], feature_names),reverse=True)[:n]
topn_class2 = sorted(Zip(classifier.feature_count_[1], feature_names),reverse=True)[:n]
print("Important words in negative reviews")
for coef, feat in topn_class1:
    print(class_labels[0], coef, feat)
print("-----------------------------------------")
print("Important words in positive reviews")
for coef, feat in topn_class2:
    print(class_labels[1], coef, feat) 

Beachten Sie, dass Ihr Klassifizierer (in meinem Fall NaiveBayes) das Attribut feature_count_ haben muss, damit dies funktioniert.

2
Sai Sandeep

Nicht genau das, wonach Sie suchen, aber eine schnelle Möglichkeit, die größten Größenkoeffizienten zu erhalten (vorausgesetzt, die Pandas-Dataframe-Spalten sind Ihre Feature-Namen): 

Sie haben das Modell wie folgt trainiert: 

lr = LinearRegression()
X_train, X_test, y_train, y_test = train_test_split(df, Y, test_size=0.25)
lr.fit(X_train, y_train)

Holen Sie sich die 10 größten negativen Koeffizientenwerte (oder wechseln Sie in den umgekehrten Wert = True für das größte positive Ergebnis) wie folgt: 

sorted(list(Zip(feature_df.columns, lr.coef_)), key=lambda x: x[1], 
reverse=False)[:10]
0
slevin886

RandomForestClassifier hat noch keinen coef_-Attribut, aber es wird in der Version 0.17 erscheinen, denke ich. Siehe jedoch die RandomForestClassifierWithCoef-Klasse in Rekursive Funktionen in Random Forest mit scikit-learn . Dies kann Ihnen einige Ideen geben, um die oben genannte Einschränkung zu umgehen.

0
Daisuke Aramaki

Sie können auch so etwas tun, um ein Diagramm mit wichtigen Features in der Reihenfolge zu erstellen:

importances = clf.feature_importances_
std = np.std([tree.feature_importances_ for tree in clf.estimators_],
         axis=0)
indices = np.argsort(importances)[::-1]

# Print the feature ranking
#print("Feature ranking:")


# Plot the feature importances of the forest
plt.figure()
plt.title("Feature importances")
plt.bar(range(train[features].shape[1]), importances[indices],
   color="r", yerr=std[indices], align="center")
plt.xticks(range(train[features].shape[1]), indices)
plt.xlim([-1, train[features].shape[1]])
plt.show()
0
Oleole