2015-05-03 5 views
16

Im triying per ottenere le funzioni più informative da un textual corpus. Da questo ben risposto question So che questo compito potrebbe essere fatto come segue:I problemi con le funzionalità più informative con scikit vengono appresi?

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 

Poi:

most_informative_feature_for_class(tfidf_vect, clf, 5) 

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

Il problema è l'uscita di 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 

Non restituisce l'etichetta né le parole. Perché questo sta accadendo e come posso stampare le parole e le etichette ?. Ragazzi, questo sta succedendo da quando utilizzo i panda per leggere i dati? Un'altra cosa che ho provato è il seguente, formano questo 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) 

ma ottengo questo traceback:

Traceback (chiamata più recente scorso):

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 

Qualsiasi idea di come risolvere questo, al fine di ottenere le caratteristiche con i valori più alti dei coefficienti ?.

risposta

12

Per risolvere questo problema specifico per SVM lineare, dobbiamo prima capire la formulazione di SVM in sklearn e le differenze che ha con MultinomialNB.

Il motivo per cui le most_informative_feature_for_class lavori per MultinomialNB è perché l'uscita del coef_ è essenzialmente la probabilità registro di caratteristiche in una classe (e quindi sarebbero di dimensioni [nclass, n_features], a causa della formulazione del problema Bayes naive. Ma se controlliamo la documentation per SVM, il coef_ non è così semplice. Invece coef_ per SVM (lineare) è [n_classes * (n_classes -1)/2, n_features] poiché ciascuno dei modelli binari sono montati ogni classe possibile.

Se facciamo possedere qualche conoscenza su quale particolare coefficiente ci interessa, potremmo modificare la funzione in modo che assomigli al seguente:

def most_informative_feature_for_class_svm(vectorizer, classifier, classlabel, n=10): 
    labelid = ?? # 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 

Questo funzionerebbe come previsto e stamperà le etichette e le prime n caratteristiche in base al vettore di coefficiente che si sta cercando.

Come per ottenere l'output corretto per una particolare classe, ciò dipenderebbe dalle ipotesi e da ciò che si mira a produrre. Suggerisco di leggere la documentazione multi-classe all'interno della documentazione SVM per avere un'idea di ciò che state cercando.

Quindi, utilizzando il train.txtfile che è stato descritto in questo question, possiamo ottenere un qualche tipo di uscita, anche se in questa situazione non è particolarmente descrittivo o utile per interpretare. Spero che questo ti aiuti.

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) 

con uscita:

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

Grazie fot questa risposta straordinaria. Che ne dici di applicare la stessa procedura ma con un kernel polinomiale o rbf ?. –

+1

Dalla mia comprensione, non sono molto sicuro se il kernel polinomiale o rbf possa essere generalizzato _e_ usato in un senso di classificazione delle funzionalità. Penso che la domanda [qui] (http://stats.stackexchange.com/questions/39243/how-doesone-interpret-svm-feature-weights) possa darti una migliore intuizione dietro SVM e il significato dei pesi. In generale, i risultati per SVM diversi da quelli lineari non sono banali, motivo per cui l'attributo 'coef' non è presente per i kernel polinomiali o rbf all'interno di sklearn. – chappers

+0

Grazie per il supporto! –

Problemi correlati