特征筛选(随机森林)

作者: 叫我老村长 | 来源:发表于2019-09-20 00:23 被阅读0次

    随机森林能够度量每个特征的重要性,我们可以依据这个重要性指标进而选择最重要的特征。sklearn中已经实现了用随机森林评估特征重要性,在训练好随机森林模型后,直接调用feature_importances属性就能得到每个特征的重要性。

    特征筛选(随机森林)

    一般情况下,数据集的特征成百上千,因此有必要从中选取对结果影响较大的特征来进行进一步建模,相关的方法有:主成分分析、lasso等,这里我们介绍的是通过随机森林来进行筛选。

    用随机森林进行特征重要性评估的思想比较简单,主要是看每个特征在随机森林中的每棵树上做了多大的贡献,然后取平均值,最后比较不同特征之间的贡献大小。

    贡献度的衡量指标包括:基尼指数(gini)、袋外数据(OOB)错误率作为评价指标来衡量。

    衍生知识点:权重随机森林的应用(用于增加小样本的识别概率,从而提高总体的分类准确率)

    随机森林/CART树在使用时一般通过gini值作为切分节点的标准,而在加权随机森林(WRF)中,权重的本质是赋给小类较大的权重,给大类较小的权重。也就是给小类更大的惩罚。权重的作用有2个,第1点是用于切分点选择中加权计算gini值,表达式如下:

    image

    其中,N表示未分离的节点,NL和NR分别表示分离后的左侧节点和右侧节点,Wi为c类样本的类权重,ni表示节点内各类样本的数量,Δi是不纯度减少量,该值越大表明分离点的分离效果越好。

    第2点是在终节点,类权重用来决定其类标签,表达式如下:

    image

    参考文献:随机森林针对小样本数据类权重设置 https://wenku.baidu.com/view/07ba98cca0c7aa00b52acfc789eb172ded639998.html

    这里介绍通过gini值来进行评价,我们将变量的重要性评分用VIM来表示,gini值用GI表示,假设有m个特征X1,X2,...Xc,现在要计算出每个特征Xj的gini指数评分VIMj,即第j个特征在随机森林所有决策树中节点分裂不纯度的平均改变量,gini指数的计算公式如下表示:

    image

    其中,k表示有k个类别,pmk表示节点m(将特征m逐个对节点计算gini值变化量)中类别k所占的比例。

    特征Xj在节点m的重要性,即节点m分枝前后的gini指数变化量为:

    image

    其中GIl和GIr分别表示分枝后两个新节点的gini指数。

    如果特征Xj在决策树i中出现的节点在集合M中,那么Xj在第i棵树的重要性为:

    image

    假设随机森林共有n棵树,那么:

    image

    最后把所有求得的重要性评分进行归一化处理就得到重要性的评分:

    image

    通过sklearn中的随机森林返回特征的重要性:

    值得庆幸的是,sklearnsklearn已经帮我们封装好了一切,我们只需要调用其中的函数即可。
    我们以UCI上葡萄酒的例子为例,首先导入数据集。

    import pandas as pd
    url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data'
    df = pd.read_csv(url, header = None)
    df.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash', 
                  'Alcalinity of ash', 'Magnesium', 'Total phenols', 
                  'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 
                  'Color intensity', 'Hue', 'OD280/OD315 of diluted wines', 'Proline']
    

    然后,我们来大致看下这时一个怎么样的数据集

    import numpy as np
    np.unique(df['Class label'])
    

    输出为

    array([1, 2, 3], dtype=int64)
    

    可见共有3个类别。然后再来看下数据的信息:

    df.info()
    

    输出为

    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 178 entries, 0 to 177
    Data columns (total 14 columns):
    Class label                     178 non-null int64
    Alcohol                         178 non-null float64
    Malic acid                      178 non-null float64
    Ash                             178 non-null float64
    Alcalinity of ash               178 non-null float64
    Magnesium                       178 non-null int64
    Total phenols                   178 non-null float64
    Flavanoids                      178 non-null float64
    Nonflavanoid phenols            178 non-null float64
    Proanthocyanins                 178 non-null float64
    Color intensity                 178 non-null float64
    Hue                             178 non-null float64
    OD280/OD315 of diluted wines    178 non-null float64
    Proline                         178 non-null int64
    dtypes: float64(11), int64(3)
    memory usage: 19.5 KB
    

    可见除去class label之外共有13个特征,数据集的大小为178。
    按照常规做法,将数据集分为训练集和测试集。

    from sklearn.cross_validation import train_test_split
    from sklearn.ensemble import RandomForestClassifier
    x, y = df.iloc[:, 1:].values, df.iloc[:, 0].values
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0)
    feat_labels = df.columns[1:]
    forest = RandomForestClassifier(n_estimators=10000, random_state=0, n_jobs=-1)
    forest.fit(x_train, y_train)
    

    好了,这样一来随机森林就训练好了,其中已经把特征的重要性评估也做好了,我们拿出来看下。

    importances = forest.feature_importances_
    indices = np.argsort(importances)[::-1]
    for f in range(x_train.shape[1]):
        print("%2d) %-*s %f" % (f + 1, 30, feat_labels[indices[f]], importances[indices[f]]))
    

    输出的结果为

     1) Color intensity                0.182483 2) Proline                        0.158610 3) Flavanoids                     0.150948 4) OD280/OD315 of diluted wines   0.131987 5) Alcohol                        0.106589 6) Hue                            0.078243 7) Total phenols                  0.060718 8) Alcalinity of ash              0.032033 9) Malic acid                     0.02540010) Proanthocyanins                0.02235111) Magnesium                      0.02207812) Nonflavanoid phenols           0.01464513) Ash                            0.013916 1) Color intensity                0.182483
     2) Proline                        0.158610
     3) Flavanoids                     0.150948
     4) OD280/OD315 of diluted wines   0.131987
     5) Alcohol                        0.106589
     6) Hue                            0.078243
     7) Total phenols                  0.060718
     8) Alcalinity of ash              0.032033
     9) Malic acid                     0.025400
    10) Proanthocyanins                0.022351
    11) Magnesium                      0.022078
    12) Nonflavanoid phenols           0.014645
    13) Ash                            0.013916
    

    对的就是这么方便。
    如果要筛选出重要性比较高的变量的话,这么做就可以

    threshold = 0.15
    x_selected = x_train[:, importances > threshold]
    x_selected.shape
    

    输出为

    (124, 3)
    

    瞧,这不,帮我们选好了3个重要性大于0.15的特征了吗~

    参考文献

    [1] Raschka S. Python Machine Learning[M]. Packt Publishing, 2015.
    [2] 杨凯, 侯艳, 李康. 随机森林变量重要性评分及其研究进展[J]. 2015.

    相关文章

      网友评论

        本文标题:特征筛选(随机森林)

        本文链接:https://www.haomeiwen.com/subject/ghpmmqtx.html