2015-05-03 2 views
16

Im triying, um die informativsten Eigenschaften von einem textual corpus zu erhalten. Von diesem gut question antwortete ich weiß, dass diese Aufgabe wie folgt getan werden könnte:Probleme beim Erlangen der meisten informativen Funktionen mit scikit lernen?

def most_informative_feature_for_class(vectorizer, classifier, classlabel, n=10): 
    labelid = list(classifier.classes_).index(classlabel) 
    feature_names = vectorizer.get_feature_names() 
    topn = sorted(zip(classifier.coef_[labelid], feature_names))[-n:] 

    for coef, feat in topn: 
     print classlabel, feat, coef 

Dann:

most_informative_feature_for_class(tfidf_vect, clf, 5) 

Für diese classfier:

X = tfidf_vect.fit_transform(df['content'].values) 
y = df['label'].values 


from sklearn import cross_validation 
X_train, X_test, y_train, y_test = cross_validation.train_test_split(X, 
                y, test_size=0.33) 
clf = SVC(kernel='linear', C=1) 
clf.fit(X, y) 
prediction = clf.predict(X_test) 

Das Problem ist die Ausgabe von most_informative_feature_for_class :

5 a_base_de_bien bastante (0, 2451) -0.210683496368 
    (0, 3533) -0.173621065386 
    (0, 8034) -0.135543062425 
    (0, 10346) -0.173621065386 
    (0, 15231) -0.154148294738 
    (0, 18261) -0.158890483047 
    (0, 21083) -0.297476572586 
    (0, 434) -0.0596263855375 
    (0, 446) -0.0753492277856 
    (0, 769) -0.0753492277856 
    (0, 1118) -0.0753492277856 
    (0, 1439) -0.0753492277856 
    (0, 1605) -0.0753492277856 
    (0, 1755) -0.0637950312345 
    (0, 3504) -0.0753492277856 
    (0, 3511) -0.115802483001 
    (0, 4382) -0.0668983049212 
    (0, 5247) -0.315713152154 
    (0, 5396) -0.0753492277856 
    (0, 5753) -0.0716096348446 
    (0, 6507) -0.130661516772 
    (0, 7978) -0.0753492277856 
    (0, 8296) -0.144739048504 
    (0, 8740) -0.0753492277856 
    (0, 8906) -0.0753492277856 
    : : 
    (0, 23282) 0.418623443832 
    (0, 4100) 0.385906085143 
    (0, 15735) 0.207958503155 
    (0, 16620) 0.385906085143 
    (0, 19974) 0.0936828782325 
    (0, 20304) 0.385906085143 
    (0, 21721) 0.385906085143 
    (0, 22308) 0.301270427482 
    (0, 14903) 0.314164150621 
    (0, 16904) 0.0653764031957 
    (0, 20805) 0.0597723455204 
    (0, 21878) 0.403750815828 
    (0, 22582) 0.0226150073272 
    (0, 6532) 0.525138162099 
    (0, 6670) 0.525138162099 
    (0, 10341) 0.525138162099 
    (0, 13627) 0.278332617058 
    (0, 1600) 0.326774799211 
    (0, 2074) 0.310556919237 
    (0, 5262) 0.176400451433 
    (0, 6373) 0.290124806858 
    (0, 8593) 0.290124806858 
    (0, 12002) 0.282832270298 
    (0, 15008) 0.290124806858 
    (0, 19207) 0.326774799211 

Es gibt weder das Etikett noch die Wörter zurück. Warum passiert das und wie kann ich die Wörter und die Etiketten drucken? Tust du das, weil ich Pandas benutze, um die Daten zu lesen? Eine andere Sache, die ich versuchte, ist die folgende, bilden diese question:

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))) 


print_top10(tfidf_vect,clf,y) 

Aber ich bekomme diese Zurückverfolgungs:

Traceback (jüngste Aufforderung zuletzt):

File "/Users/user/PycharmProjects/TESIS_FINAL/Classification/Supervised_learning/Final/experimentos/RBF/SVM_con_rbf.py", line 237, in <module> 
    print_top10(tfidf_vect,clf,5) 
    File "/Users/user/PycharmProjects/TESIS_FINAL/Classification/Supervised_learning/Final/experimentos/RBF/SVM_con_rbf.py", line 231, in print_top10 
    for i, class_label in enumerate(class_labels): 
TypeError: 'int' object is not iterable 

Jede Idee, wie zu lösen Dies, um die Features mit den höchsten Koeffizientenwerten zu erhalten.

Antwort

12

Um dies speziell für lineare SVM zu lösen, müssen wir zuerst die Formulierung der SVM in Sklearn und die Unterschiede, die es zu MultinomialNB hat, verstehen.

Der Grund, warum die most_informative_feature_for_class Werke für MultinomialNB, weil der Ausgang der coef_ im Wesentlichen die Log-Wahrscheinlichkeit von Merkmalen einer Klasse gegeben ist (und damit die Größe [nclass, n_features] aufgrund der Formulierung des naiven Bayes-Problems wäre. Aber wenn wir überprüfen die documentation für SVM, die coef_ nicht so einfach ist. Statt coef_ für (linear) SVM ist [n_classes * (n_classes -1)/2, n_features], da jeder der binären Modelle zu jeder möglichen Klasse ausgestattet sind.

Wenn wir einige Kenntnisse besitzen zu tun, auf dem bestimmten Koeffizienten Wir sind daran interessiert, wir könnten die Funktion so ändern, dass sie wie folgt aussieht:

Dies würde wie vorgesehen funktionieren und die Beschriftungen und die Top-n-Funktionen entsprechend dem Koeffizientenvektor ausgeben, nach dem Sie suchen.

Um die richtige Ausgabe für eine bestimmte Klasse zu erhalten, hängt das von den Annahmen und der Ausgabe ab. Ich schlage vor, die Dokumentation in der SVM-Dokumentation zu lesen, um ein Gefühl dafür zu bekommen, wonach Sie suchen.

So die train.txtfile verwendet, die in diesen question beschrieben wurden, können wir eine Art von Leistung, obwohl in dieser Situation ist es nicht besonders beschreibend oder hilfreich zu interpretieren bekommen. Hoffentlich hilft dir das.

import codecs, re, time 
from itertools import chain 

import numpy as np 

from sklearn.feature_extraction.text import CountVectorizer 
from sklearn.naive_bayes import MultinomialNB 

trainfile = 'train.txt' 

# Vectorizing data. 
train = [] 
word_vectorizer = CountVectorizer(analyzer='word') 
trainset = word_vectorizer.fit_transform(codecs.open(trainfile,'r','utf8')) 
tags = ['bs','pt','es','sr'] 

# Training NB 
mnb = MultinomialNB() 
mnb.fit(trainset, tags) 

from sklearn.svm import SVC 
svcc = SVC(kernel='linear', C=1) 
svcc.fit(trainset, tags) 

def most_informative_feature_for_class(vectorizer, classifier, classlabel, n=10): 
    labelid = list(classifier.classes_).index(classlabel) 
    feature_names = vectorizer.get_feature_names() 
    topn = sorted(zip(classifier.coef_[labelid], feature_names))[-n:] 

    for coef, feat in topn: 
     print classlabel, feat, coef 

def most_informative_feature_for_class_svm(vectorizer, classifier, n=10): 
    labelid = 3 # this is the coef we're interested in. 
    feature_names = vectorizer.get_feature_names() 
    svm_coef = classifier.coef_.toarray() 
    topn = sorted(zip(svm_coef[labelid], feature_names))[-n:] 

    for coef, feat in topn: 
     print feat, coef 

most_informative_feature_for_class(word_vectorizer, mnb, 'pt') 
print 
most_informative_feature_for_class_svm(word_vectorizer, svcc) 

mit Ausgang:

pt teve -4.63472898823 
pt tive -4.63472898823 
pt todas -4.63472898823 
pt vida -4.63472898823 
pt de -4.22926388012 
pt foi -4.22926388012 
pt mais -4.22926388012 
pt me -4.22926388012 
pt as -3.94158180767 
pt que -3.94158180767 

no 0.0204081632653 
parecer 0.0204081632653 
pone 0.0204081632653 
por 0.0204081632653 
relación 0.0204081632653 
una 0.0204081632653 
visto 0.0204081632653 
ya 0.0204081632653 
es 0.0408163265306 
lo 0.0408163265306 
+0

Dank fot diese erstaunliche Antwort. Wie wäre es mit der gleichen Prozedur, aber mit einem Polynom oder rbf Kernel? –

+1

Aus meiner Sicht bin ich mir nicht sicher, ob der Polynom- oder der rbf-Kern verallgemeinert und in einem Feature-Ranking-Sinn verwendet werden kann. Ich denke, die Frage [hier] (http://stats.stackexchange.com/questions/39243/how-does-one-interpret-svm-feature-weights) kann Ihnen eine bessere Intuition hinter SVM und die Bedeutung der Gewichte geben. Im Allgemeinen sind die Ergebnisse für SVMs, die nicht linear sind, nicht trivial, weshalb das "coef" -Attribut für polynomiale oder rbf-Kernel in sklearn nicht vorhanden ist. – chappers

+0

Danke für die Unterstützung! –