【问题标题】:How to get most informative features for scikit-learn classifiers?如何为 scikit-learn 分类器获取信息量最大的特征?
【发布时间】:2012-06-22 10:06:03
【问题描述】:

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 中的分类器实现了类似的功能。我搜索了文档,但找不到类似的东西。

如果还没有这样的功能,有人知道如何获得这些值吗?

【问题讨论】:

  • 你的意思是最有区别的参数?
  • 我不确定你的参数是什么意思。我的意思是最具辨别力的特征,比如在垃圾邮件分类的词袋模型中,哪些词为每个类别提供了最多的证据。不是我理解为分类器“设置”的参数——比如学习率等。
  • @eowl:在机器学习用语中,参数是学习过程根据你的训练集的特征生成的设置。学习率等是超参数

标签: python machine-learning classification scikit-learn


【解决方案1】:

分类器本身不记录特征名称,它们只看到数字数组。但是,如果您使用 Vectorizer/CountVectorizer/TfidfVectorizer/DictVectorizer 提取特征,并且您使用的是线性模型(例如 LinearSVC 或朴素贝叶斯),那么您可以应用document classification example 使用的相同技巧。示例(未经测试,可能包含一两个错误):

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 进行排序。

【讨论】:

  • 是的,在我的情况下,我只有两个类,但是通过您的代码,我能够想出我想要的东西。非常感谢!
  • 对于 2 个类,看起来是 coef_ 而不是 coef_[0]
  • @RyanRosario:正确。在二进制情况下,coef_ 被展平以节省空间。
  • class_labels 是如何确定的?我想知道类标签的顺序。
  • 您可以使用class_labels=clf.classes_从分类器中获取有序类
【解决方案2】:

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

【讨论】:

  • 如何从 main 方法调用函数? f1 和 f2 代表什么?我正在尝试使用 scikit-learn 从决策树分类器中调用该函数。
  • 此代码仅适用于具有coef_ 数组的线性分类器,因此不幸的是,我认为它不能与 sklearn 的决策树分类器一起使用。 fn_1fn_2 代表功能名称。
【解决方案3】:

要添加更新,RandomForestClassifier 现在支持 .feature_importances_ 属性。这个attribute 告诉您观察到的方差中有多少是由该特征解释的。显然,所有这些值的总和必须

我发现这个属性在执行特征工程时非常有用。

感谢 scikit-learn 团队和贡献者实现此功能!

edit:这适用于 RandomForest 和 GradientBoosting。所以RandomForestClassifierRandomForestRegressorGradientBoostingClassifierGradientBoostingRegressor 都支持这一点。

【讨论】:

    【解决方案4】:

    我们最近发布了一个库 (https://github.com/TeamHG-Memex/eli5),它允许这样做:它处理来自 scikit-learn、二进制/多类案例的各种分类器,允许根据特征值突出显示文本,与 IPython 集成等。

    【讨论】:

    • 如果有人需要启动 sn-p: from eli5 import show_weights show_weights(model, vec=tfidf)
    【解决方案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 版本中。但是,请参阅 Recursive feature elimination on Random Forest using scikit-learn 中的 RandomForestClassifierWithCoef 类。这可能会为您提供一些解决上述限制的想法。

        【讨论】:

          【解决方案8】:

          不完全是您要查找的内容,而是一种快速获取最大量级系数的方法(假设 pandas 数据框列是您的特征名称):

          你训练了这样的模型:

          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 个最大的负系数值(或更改为 reverse=True 以获得最大的正),例如:

          sorted(list(zip(feature_df.columns, lr.coef_)), key=lambda x: x[1], 
          reverse=False)[:10]
          

          【讨论】:

            【解决方案9】:

            首先做一个列表,我给这个列表命名标签。之后提取所有特征名称和列名称,我将其添加到标签列表中。这里我使用朴素贝叶斯模型。在朴素贝叶斯模型中,feature_log_prob_给出特征的概率。

            def top20(model,label):
            
              feature_prob=(abs(model.feature_log_prob_))
            
              for i in range(len(feature_prob)):
            
                print ('top 20 features for {} class'.format(i))
            
                clas = feature_prob[i,:]
            
                dictonary={}
            
                for count,ele in enumerate(clas,0): 
            
                  dictonary[count]=ele
            
                dictonary=dict(sorted(dictonary.items(), key=lambda x: x[1], reverse=True)[:20])
            
                keys=list(dictonary.keys())
            
                for i in keys:
            
                  print(label[i])
            
                print('*'*1000)
            

            【讨论】:

              猜你喜欢
              • 2016-12-29
              • 2015-07-13
              • 2020-10-31
              • 2018-06-01
              • 2015-01-12
              • 1970-01-01
              • 2014-02-17
              • 2018-11-23
              相关资源
              最近更新 更多