python - sklearn - ¿Cómo obtener la mayoría de las características informativas para los clasificadores scikit-learn?
scikit learn guide (7)
Con la ayuda del código de larsmans se me ocurrió este código para el caso binario:
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)
Los clasificadores en paquetes de aprendizaje automático como liblinear y nltk ofrecen un método show_most_informative_features()
, que es realmente útil para las funciones de depuración:
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
Mi pregunta es si se implementa algo similar para los clasificadores en scikit-learn. Busqué en la documentación, pero no pude encontrar nada igual.
Si aún no existe esa función, ¿alguien sabe una solución alternativa para llegar a esos valores?
¡Muchas gracias!
De hecho, tuve que averiguar Importancia de funciones en mi clasificador NaiveBayes y aunque utilicé las funciones anteriores, no pude obtener la importancia de las funciones en función de las clases. Revisé la documentación de scikit learn y modifiqué un poco las funciones anteriores para encontrar que funcionaba para mi problema. Espero que te ayude también!
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)
Tenga en cuenta que su clasificador (en mi caso es NaiveBayes) debe tener el atributo feature_count_ para que esto funcione.
Los propios clasificadores no registran los nombres de las funciones, solo ven las matrices numéricas. Sin embargo, si extrajo sus características utilizando un Vectorizer
/ CountVectorizer
/ TfidfVectorizer
/ DictVectorizer
, y está utilizando un modelo lineal (por ejemplo, LinearSVC
o Naive Bayes), puede aplicar el mismo truco que usa el ejemplo de clasificación de documentos . Ejemplo ( no probado , puede contener un error o dos):
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)))
Esto es para la clasificación multiclase; para el caso binario, creo que debería usar clf.coef_[0]
solamente. Puede que tengas que ordenar class_labels
.
Para agregar una actualización, RandomForestClassifier
ahora admite el atributo .feature_importances_
. Este attribute te dice qué parte de la varianza observada se explica con esa característica. Obviamente, la suma de todos estos valores debe ser <= 1.
Encuentro este atributo muy útil cuando realizo la ingeniería de características.
¡Gracias al equipo de scikit-learn y a los colaboradores por implementar esto!
editar: Esto funciona tanto para RandomForest como para GradientBoosting. Así que RandomForestClassifier
, RandomForestRegressor
, GradientBoostingClassifier
y GradientBoostingRegressor
compatibles con esto.
Recientemente hemos lanzado una biblioteca ( https://github.com/TeamHG-Memex/eli5 ) que permite hacer eso: maneja varios clasificadores de scikit-learn, casos binarios / multiclass, permite resaltar el texto según los valores de las características , se integra con IPython, etc.
También puede hacer algo como esto para crear un gráfico de características importantes por orden:
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()
RandomForestClassifier
todavía no tiene un coef_
, pero lo hará en la versión 0.17, creo. Sin embargo, consulte la clase RandomForestClassifierWithCoef
en Eliminación de características recursivas en Random Forest utilizando scikit-learn . Esto puede brindarle algunas ideas para evitar la limitación anterior.