Как получить наиболее информативные функции для классификаторов scikit-learn?
Классификаторы пакетов машинного обучения, такие как liblinear и nltk, предлагают метод show_most_informative_features()
, который действительно полезен для функций отладки:
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
Мой вопрос: если что-то подобное реализовано для классификаторов в scikit-learn. Я искал документацию, но не мог найти ничего подобного.
Если такой функции еще нет, кто-нибудь знает обходное решение, как добраться до этих значений?
Спасибо, много!
Ответы
Ответ 1
С помощью кода larsmans я придумал этот код для двоичного случая:
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)
Ответ 2
Классификаторы сами не записывают имена функций, они просто видят числовые массивы. Однако, если вы извлекли свои функции с помощью Vectorizer
/CountVectorizer
/TfidfVectorizer
/DictVectorizer
, и вы используете линейную модель (например, LinearSVC
или Naive Bayes), вы можете применить тот же трюк, что пример классификации документов. Пример (непроверенный, может содержать ошибку или два):
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)))
Это для классификации многоклассов; для двоичного случая, я думаю, вы должны использовать только clf.coef_[0]
. Возможно, вам придется отсортировать class_labels
.
Ответ 3
Чтобы добавить обновление, RandomForestClassifier
теперь поддерживает атрибут .feature_importances_
. Этот атрибут показывает вам, какая часть наблюдаемой дисперсии объясняется этой функцией. Очевидно, что сумма всех этих значений должна быть равна <= 1.
Я считаю, что этот атрибут очень полезен при разработке функций.
Спасибо команде scikit-learn и вкладчикам за ее реализацию!
edit: Это работает как для RandomForest, так и для GradientBoosting. Таким образом, RandomForestClassifier
, RandomForestRegressor
, GradientBoostingClassifier
и GradientBoostingRegressor
поддерживают это.
Ответ 4
Недавно мы выпустили библиотеку (https://github.com/TeamHG-Memex/eli5), которая позволяет это сделать: она обрабатывает классификаторы variuos из scikit-learn, двоичного /multiclass, позволяет выделять текст в соответствии со значениями функций, интегрируется с IPython и т.д.
Ответ 5
Мне действительно пришлось выяснить важность функций в моем классификаторе NaiveBayes, и хотя я использовал вышеупомянутые функции, я не смог получить важность функций на основе классов. Я просмотрел документацию по scikit-learn и немного подправил вышеуказанные функции, чтобы убедиться, что она работает для моей проблемы. Надеюсь, это вам тоже поможет!
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)
Обратите внимание, что ваш классификатор (в моем случае это NaiveBayes) должен иметь атрибут feature_count_, чтобы это работало.
Ответ 6
Вы также можете сделать что-то подобное, чтобы создать график важных функций по порядку:
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()
Ответ 7
RandomForestClassifier
пока не имеет атрибута coef_
, но, по-моему, он будет в выпуске 0,17. Тем не менее, см. Класс RandomForestClassifierWithCoef
в Рекурсивная функция исключения в Random Forest с использованием scikit-learn. Это может дать вам некоторые идеи для решения вышеописанных ограничений.
Ответ 8
Не совсем то, что вы ищете, но быстрый способ получить коэффициенты наибольшей величины (предполагая, что столбцы pandas dataframe - ваши имена объектов):
Вы тренировали модель как:
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)
Получите 10 самых больших отрицательных значений коэффициента (или измените на обратный = True для наибольшего положительного значения), например:
sorted(list(zip(feature_df.columns, lr.coef_)), key=lambda x: x[1],
reverse=False)[:10]