python - tfidfvectorizer - ¿Problemas para obtener la mayoría de las características informativas con scikit aprender?
text classification machine learning (1)
Estoy tratando de obtener las características más informativas de un corpus textual . De esta question bien respondida, sé que esta tarea se podría hacer de la siguiente manera:
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
Entonces:
most_informative_feature_for_class(tfidf_vect, clf, 5)
Para esta clase:
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)
El problema es la salida de 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
No está devolviendo la etiqueta ni las palabras. ¿Por qué sucede esto y cómo puedo imprimir las palabras y las etiquetas? Chicos, esto está ocurriendo ya que estoy usando pandas para leer los datos? Otra cosa que probé es la siguiente, formule esta 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)
Pero me sale este rastro:
Rastreo (llamadas recientes más última):
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
¿Alguna idea de cómo resolver esto, para obtener las características con los valores de coeficiente más altos?
Para resolver esto específicamente para SVM lineal, primero tenemos que entender la formulación de SVM en sklearn y las diferencias que tiene con MultinomialNB.
La razón por la que most_informative_feature_for_class
funciona para MultinomialNB es porque la salida de coef_
es esencialmente la probabilidad de registro de características dadas una clase (y por lo tanto sería de tamaño [nclass, n_features]
, debido a la formulación del problema naive bayes. Pero si verificamos la documentation para SVM, el coef_
no es tan simple, en su lugar coef_
para (lineal) SVM es [n_classes * (n_classes -1)/2, n_features]
porque cada uno de los modelos binarios se ajusta a cada clase posible.
Si poseemos algún conocimiento sobre qué coeficiente particular nos interesa, podríamos modificar la función para que se parezca a lo siguiente:
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
Esto funcionaría según lo previsto e imprimirá las etiquetas y las principales n características de acuerdo con el vector de coeficiente que está buscando.
En cuanto a obtener la salida correcta para una clase en particular, eso dependería de las suposiciones y de lo que pretende obtener. Sugiero leer la documentación en varias clases dentro de la documentación de SVM para tener una idea de lo que está buscando.
Entonces, al utilizar el file train.txt
que se describió en esta question , podemos obtener algún tipo de resultado, aunque en esta situación no es particularmente descriptivo o útil de interpretar. Esperemos que esto te ayude.
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 salida:
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