精华内容
下载资源
问答
  • 本文是对随机森林如何用在特征选择上做一个简单的介绍。随机森林(RF)简介只要了解决策树的算法,那么随机森林是相当容易理解的。随机森林的算法可以用如下几个步骤概括:用有抽样放回的方法(bootstrap...

    前言

    随机森林是以决策树为基学习器的集成学习算法。随机森林非常简单,易于实现,计算开销也很小,更令人惊奇的是它在分类和回归上表现出了十分惊人的性能,因此,随机森林也被誉为“代表集成学习技术水平的方法”。

    本文是对随机森林如何用在特征选择上做一个简单的介绍。

    随机森林(RF)简介

    只要了解决策树的算法,那么随机森林是相当容易理解的。随机森林的算法可以用如下几个步骤概括:

    用有抽样放回的方法(bootstrap)从样本集中选取n个样本作为一个训练集

    用抽样得到的样本集生成一棵决策树。在生成的每一个结点:

    随机不重复地选择d个特征

    利用这d个特征分别对样本集进行划分,找到最佳的划分特征(可用基尼系数、增益率或者信息增益判别)

    重复步骤1到步骤2共k次,k即为随机森林中决策树的个数。

    用训练得到的随机森林对测试样本进行预测,并用票选法决定预测的结果。

    下图比较直观地展示了随机森林算法:

    1e2562f3e33b

    图1:随机森林算法示意图

    没错,就是这个到处都是随机取值的算法,在分类和回归上有着极佳的效果,是不是觉得强的没法解释~

    然而本文的重点不是这个,而是接下来的特征重要性评估。

    特征重要性评估

    sklearn 已经帮我们封装好了一切,我们只需要调用其中的函数即可。 我们以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()

    输出为:

    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。

    按照常规做法,将数据集分为训练集和测试集。此处注意:sklearn.cross_validation 模块在0.18版本中被弃用,支持所有重构的类和函数都被移动到了model_selection模块。从sklearn.model_selection引入train_test_split

    from sklearn.model_selection 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.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的特征。

    展开全文
  • R包randomForest的随机森林回归模型以及对重要变量选择​mp.weixin.qq.comR包randomForest的随机森林回归模型以及对重要变量选择关于随机森林(random forest),前文“随机森林分类以及对重要变量选择”中...

    c77053d6dccb487ad11919fde9abc46b.png
    R包randomForest的随机森林回归模型以及对重要变量的选择mp.weixin.qq.com
    831060e33ac891172239391523122742.png

    R包randomForest的随机森林回归模型以及对重要变量的选择

    6fa420b4b6f9b74a54827cd7b53c1b05.gif

    关于随机森林(random forest),前文“随机森林分类以及对重要变量的选择”中已经对其基本原理作了简单概括。在前文中,响应变量是一组类别变量(代表了样本的分组信息),此时随机森林用于执行监督分类的功能,模型的精度在于通过选定的预测变量组合将样本正确划分归类的概率。而当响应变量是一组连续变量时,可将回归森林用于回归。此时,回归模型的精度体现了选定的预测变量对响应变量数值改变有关方差的整体解释率(可以理解为回归的R2)。本篇则简介随机森林的回归功能。

    文献中使用随机森林回归的一个实例

    首先来看一篇与植物根系微生物组有关研究,将文中涉及到随机森林回归的部分内容节选出来以帮助大家理解。

    Edwards等(2018)分析了来自两个地区(加利福尼亚州、阿肯色州)以及三个连续种植季(2014、2015、2016)的水稻根系微生物组,意在阐述水稻根系微生物群落的时间动态特征,并解释驱动微生物群落组建的成因。文中部分内容使用到随机森林的回归模型建立微生物丰度和水稻生长时期的关系,用以识别重要的时间响应微生物类群。

    68345028d2da9ad44ac7e9a24c6887d6.png

    作者首先分析了水稻根系微生物群落的组成结构,显示其受到地理区域(土壤环境)、植物生长时期以及植物根系不同部位的多重影响。随后分析各个因素的相对效应,发现水稻生长过程中能够逐渐对其根系菌群进行选择,植物生长时期的效应越来越明显,根系菌群朝向一组保守的物种组成趋势发展,同时地理环境效应的比重逐渐减弱。主要体现在:

    (1)不同地理区域种植的水稻,随着水稻生长时期的推移,根际和根内菌群的相似度逐渐增加,并在后期趋于稳定,与种植季节无关:

    (2)对于水稻根际和根内菌群,地区间独特OTU的相对丰度均随时间推移而不断下降,剩余的OTU中,两地区间共有OTU的比重上升。

    08b4414b7932f333382454c243c0311d.png

    图A-C,水稻根系微生物群落的PCoA,分别突出了群落组成相似度与根系区域(A)、地理区域(B)或植物生长时间(C)的关系。

    图D,根区、根际和根内样本中,微生物群落相似度随植物生长的关系。

    总之存在一类具有显著时间特征的微生物类群,它们的丰度变化与水稻的生长时期密切相关,无论是增加(根系富集)或减少(根系排斥)。随后,作者期望寻找可用于区分水稻生长时期的微生物OTU组合,包括根际和根内菌群,就使用了随机森林。

    作者选择了一部分的样本(加利福尼亚州2014年和阿肯色州2016年的部分数据)用作训练集,通过随机森林分别将根际和根内所有微生物OTU的相对丰度与水稻生长时期进行了回归,并根据各个OTU对模型预测准确性的相对贡献按重要性进行排名。十折交叉验证用于评估模型中OTU数量与模型误差的关系,并按重要性排名对OTU进行选择,删除了大部分不重要OTU后,最终保留的OTU用于构建最终的随机森林回归模型。

    结果中,共确定了85个最重要的与水稻生长时期密切关联的OTU。训练集的数据显示,通过这85个OTU构建的随机森林回归模型分别解释了根际和根内菌群对植物年龄有关方差的91.5%和88.4%,表明它们的丰度组合能够准确预测水稻的生长时期。此外,测试集以及验证集数据(涉及了训练集样本外的其它采样时间、地理区域的样本)也一致地表明,通过这85个OTU构建的随机森林回归模型同样准确预测了水稻的生长时期,凸显了水稻根际和根内存在特定的微生物类群,在跨地理区域和季节的水稻植物的生命周期中表现出一致的模式。

    792e7d57b3d2d98eae7d69843413818f.png

    图A,横坐标是水稻的实际生长时期,纵坐标是随机森林模型通过根际或根内微生物丰度预测的水稻生长时期,模型具有很高的精度。

    图B,重要的85个OTU在水稻根际或根内的丰度与时间的关系。

    图C,85个OTU根据丰度的时间响应模式,可分为早期定植(丰度早期很高,但随时间降低)或晚期定植(丰度早期很低,但随时间增加)以及复合型(早期晚期定植区分不明显)类群,柱形图展示了3种类群中OTU平均丰度变化趋势。

    文中后续还有内容涉及到随机森林模型的应用,这里就不再展示了。节选的部分章节想必也足以能够帮助大家了解这个方法的实际应用了。

    此外,该文献的补充材料中提供了有关OTU丰度表、分析过程的R代码等非常全面的数据,大家若有兴趣参考原文即可。

    接下来,展示随机森林回归及对重要变量选择在R语言中的实现方法。

    通过R包randomForest的随机森林执行回归

    对于随机森林应用在类别型响应变量中的分类功能,前文“随机森林分类模型以及对重要变量的选择”中,已经以R包randomForest中的方法为例展示了如何通过随机森林构建分类预测模型(分类模型的训练和测试),以及筛选对区分已知分类具有高度鉴别模式的变量组合(评估变量的相对重要性)。

    在下文中,将响应变量更换为连续型变量,继续展示R包randomForest的随机森林回归方法以及实现对重要变量的选择。其实无论执行的分类还是回归,过程中使用的方法都是一样的,R函数还是那些R函数,区别只在于对部分函数的参数设置以及结果的解读方式上。

    下文的测试数据,R代码等的百度盘链接(提取码,fljz):

    https://pan.baidu.com/s/1Lfk21hGrWDehodWchBiIIg

    若百度盘失效,也可在GitHub的备份中获取:

    https://github.com/lyao222lll/sheng-xin-xiao-bai-yu

    示例数据

    植物根系菌群结构与植物生长密切相关,到目前为止,已经在许多研究中都有报道了,这已经是个共识。因此,下文的示例数据也同样来自某植物根际区域细菌群落组成的16S扩增子测序数据,类似地,仿照上文文献中的过程,通过随机森林建立微生物与植物生长时期的响应关系,根据微生物丰度推断植物生长时期,并寻找一组重要的时间特征类群。

    示例数据“otu_table.txt”中,共记录了45个连续生长时间中植物根际土壤样本中细菌OTU的相对丰度信息。

    040fa265f8ac8b4110c71eb226396826.png

    “plant_age.txt”中,记录了这45个根际土壤样本对应的植物生长时间,时间单位是天。

    68631d64bfb8cd904ff8e23ba677013c.png

    随机森林回归模型的初步构建

    将OTU丰度数据读入R中,可以事先作一些预处理,例如剔除低丰度类群等。

    随后,对应OTU丰度样本与植物生长时间的关系,加载randomForest包并运行随机森林。

    ##数据预处理
    #读取 OTUs 丰度表
    otu <- read.delim('otu_table.txt', row.names = 1)
     
    #过滤低丰度 OTUs 类群,它们对分类贡献度低,且影响计算效率
    #例如剔除总丰度低于 0.05% 的值
    otu <- otu[which(rowSums(otu) >= 0.0005), ]
     
    #合并有关于植物生长时间的信息
    plant <- read.delim('plant_age.txt', row.names = 1)
     
    otu <- data.frame(t(otu))
    otu <- otu[rownames(plant), ]
    otu <- cbind(otu, plant)
     
    #为了方便后续评估随机森林模型的性能
    #将总数据集分为训练集(占 70%)和测试集(占 30%)
    set.seed(123)
    train <- sample(nrow(otu), nrow(otu)*0.7)
    otu_train <- otu[train, ]
    otu_test <- otu[-train, ]
     
    ##randomForest 包的随机森林
    library(randomForest)
     
    #随机森林计算(默认生成 500 棵决策树),详情 ?randomForest
    set.seed(123)
    otu_train.forest <- randomForest(plant_age~., data = otu_train, importance = TRUE)
    otu_train.forest
    

    4600c70155ca85a93767036d39ac2882.png

    结果中,% Var explained体现了预测变量(用于回归的所有OTU)对响应变量(植物年龄)有关方差的整体解释率。在本示例中,剔除了低丰度的OTU后,剩余的OTU(约2600个左右)解释了约89.17%的总方差,可以理解为该回归的R2=0.8917,相当可观的一个数值,表明该植物根际细菌的群落结构随植物生长密切相关。

    查看该模型的预测性能,可以看到具有较高的精度。

    #使用训练集,查看预测精度
    plant_predict <- predict(otu_train.forest, otu_train)
     
    plot(otu_train$plant_age, plant_predict, main = '训练集',
        xlab = 'Plant age (days)', ylab = 'Predict')
    abline(1, 1)
     
    #使用测试集,评估预测性能
    plant_predict <- predict(otu_train.forest, otu_test)
     
    plot(otu_test$plant_age, plant_predict, main = '测试集',
        xlab = 'Plant age (days)', ylab = 'Predict')
    abline(1, 1)
    

    72f021e88c5b75acb1684e64f16fff90.png

    重要的预测变量选择

    但是,并非这所有的2600余个OTU都对回归的精度具有可观的贡献。有些OTU丰度的时间特征并不明显,可能在回归中产生较大噪声,对模型精度带来较高的误差。因此,最好将低贡献的OTU去除。

    评估预测变量的重要性

    基于已经构建好的随机森林回归模型,可以从中评估OTU的重要性。将OTU按重要程度高低进行排名后,选择排名靠前的一部分OTU,这些重要的OTU是明显的与植物生长时间密切关联的一些细菌类群。

    ##OTU 的重要性评估
    #查看表示每个预测变量(细菌 OTU)重要性的得分
    #summary(otu_train.forest)
    importance_otu <- otu_train.forest$importance
    head(importance_otu)
     
    #或者使用函数 importance()
    importance_otu <- data.frame(importance(otu_train.forest), check.names = FALSE)
    head(importance_otu)
     
    #作图展示 top30 重要的 OTUs
    varImpPlot(otu_train.forest, n.var = min(30, nrow(otu_train.forest$importance)),
        main = 'Top 30 - variable importance')
    

    8c6692348534378a5f89cbc4e5abd9f0.png

    “%IncMSE”即increase in mean squared error,通过对每一个预测变量随机赋值,如果该预测变量更为重要,那么其值被随机替换后模型预测的误差会增大。因此,该值越大表示该变量的重要性越大;

    “IncNodePurity”即increase in node purity,通过残差平方和来度量,代表了每个变量对分类树每个节点上观测值的异质性的影响,从而比较变量的重要性。该值越大表示该变量的重要性越大。

    对于“%IncMSE”或“IncNodePurity”,二选一作为判断预测变量重要性的指标。需注意的是,二者的排名存在一定的差异。

    #可以根据某种重要性的高低排个序,例如根据“IncNodePurity”指标
    importance_otu <- importance_otu[order(importance_otu$IncNodePurity, decreasing = TRUE), ]
    head(importance_otu)
     
    #输出表格
    #write.table(importance_otu, 'importance_otu.txt', sep = 't', col.names = NA, quote = FALSE)
    

    8c642cd5b40426ad570e16ae39c5994c.png

    交叉验证

    那么,最终选择多少重要的预测变量(本示例为OTUs)是更合适的呢?

    可通过执行十折交叉验证,根据交叉验证曲线对OTU进行取舍。交叉验证法的作用就是尝试利用不同的训练集/验证集划分来对模型做多组不同的训练/验证,来应对单独测试结果过于片面以及训练数据不足的问题。此处使用训练集本身进行交叉验证。

    ##交叉验证辅助评估选择特定数量的 OTU
    #5 次重复十折交叉验证
    set.seed(123)
    otu_train.cv <- replicate(5, rfcv(otu_train[-ncol(otu_train)], otu_train$plant_age, cv.fold = 10, step = 1.5), simplify = FALSE)
    otu_train.cv
     
    #提取验证结果绘图
    otu_train.cv <- data.frame(sapply(otu_train.cv, '[[', 'error.cv'))
    otu_train.cv$otus <- rownames(otu_train.cv)
    otu_train.cv <- reshape2::melt(otu_train.cv, id = 'otus')
    otu_train.cv$otus <- as.numeric(as.character(otu_train.cv$otus))
     
    otu_train.cv.mean <- aggregate(otu_train.cv$value, by = list(otu_train.cv$otus), FUN = mean)
    head(otu_train.cv.mean, 10)
     
    #拟合线图
    library(ggplot2)
     
    ggplot(otu_train.cv.mean, aes(Group.1, x)) +
    geom_line() +
    theme(panel.grid = element_blank(), panel.background = element_rect(color = 'black', fill = 'transparent')) +
    labs(title = '',x = 'Number of OTUs', y = 'Cross-validation error')
    

    2bf4ed24be62ed147627d8a33449ed65.png

    交叉验证曲线展示了模型误差与用于拟合的OTU数量之间的关系。误差首先会随OTUs数量的增加而减少,开始时下降非常明显,但到了特定范围处,下降幅度将不再有显著变化,甚至有所增加。

    根据交叉验证曲线,提示保留9-13个重要的OTU即可以获得理想的回归结果,因为此时的误差达到最小。

    因此,根据计算得到的各OUT重要性的值(如“IncNodePurity”),将OTU由高往低排序后,最后大约选择前9-13个OTU就可以了。

    #提示保留 9-13 个重要的 OTU,可以使随机森林回归的精度最大化
    #首先根据某种重要性的高低排个序,例如根据“IncNodePurity”指标
    importance_otu <- importance_otu[order(importance_otu$IncNodePurity, decreasing = TRUE), ]
     
    #然后取出排名靠前的 OTU,例如 top10 最重要的 OTU
    importance_otu.select <- importance_otu[1:10, ]
    importance_otu.select
     
    #输出表格
    #write.table(importance_otu.select, 'importance_otu.select.txt', sep = 't', col.names = NA, quote = FALSE)
     
    #有关 OTU 的物种分类信息等其它细节,可后续自行补充
    

    ea182780ad09b984b00e6b486ffab7cf.png
    #不妨简单查看下这些重要的 OTU 丰度与植物生长时间的关系
    #可以看到趋势非常明显,包括根际富集或排斥等都有涉及
    otu_id.select <- rownames(importance_otu.select)
    otu.select <- otu[ ,c(otu_id.select, 'plant_age')]
    otu.select <- reshape2::melt(otu.select, id = 'plant_age')
     
    ggplot(otu.select, aes(x = plant_age, y = value)) +
    geom_point() +
    geom_smooth() +
    facet_wrap(~variable, ncol = 3, scale = 'free_y') +
    labs(title = '',x = 'Plant age (days)', y = 'Relative abundance')
    

    2090b55306e7fae9c9a322a19999899a.png

    最终模型的确定

    现在来看,只使用选择的10个重要的OTU构建回归模型,效果如何。

    ##只包含 10 个重要预测变量的简约回归
    otu.select <- otu[ ,c(otu_id.select, 'plant_age')]
     
    #为了方便后续评估随机森林模型的性能,将总数据集分为训练集(占 70%)和测试集(占 30%)
    set.seed(123)
    train <- sample(nrow(otu.select), nrow(otu.select)*0.7)
    otu_train.select <- otu.select[train, ]
    otu_test.select <- otu.select[-train, ]
     
    #随机森林计算(默认生成 500 棵决策树),详情 ?randomForest
    set.seed(123)
    otu_train.select.forest <- randomForest(plant_age~., data = otu_train.select, importance = TRUE)
    otu_train.select.forest
     
    #使用训练集,查看预测精度
    plant_predict <- predict(otu_train.select.forest, otu_train.select)
     
    plot(otu_train.select$plant_age, plant_predict, main = '训练集',
        xlab = 'Plant age (days)', ylab = 'Predict')
    abline(1, 1)
     
    #使用测试集,评估预测性能
    plant_predict <- predict(otu_train.select.forest, otu_test.select)
     
    plot(otu_test.select$plant_age, plant_predict, main = '测试集',
        xlab = 'Plant age (days)', ylab = 'Predict')
    abline(1, 1)
    

    1944217f8cf2949ab149420710829154.png

    结果显示,与先前使用全部的OTU(去除低丰度后约2600多个)相比,只使用这10个更重要OTU的随机森林回归模型,获得了更出色的效果。

    一是体现在% Var explained,模型中预测变量(这10个重要的OTU)对响应变量(植物年龄)有关方差的整体解释率达到了96.49%,大于先前的89.17%,这得益于排除了不重要或者高噪声的OTU。二是预测性能更佳,特别是对于测试集,与先前的分布图相比较(见上文),植物实际生长时间与通过根际菌群预测的植物年龄更趋一致。

    如果不涉及预测,只是评估变量的重要性

    上文过程中,为了评估随机森林回归模型的预测性能,将数据拆分为训练集和测试集分开讨论。但如果目的不涉及预测,只是为了寻找重要的预测变量,完全可以直接使用所有数据代入回归,无需再区分训练集与测试集,这也是很多文献中经常提到的方法。

    例如另一篇类似的研究,Zhang等(2018)寻找水稻根系中与植物生长期密切相关的biomarkers时,同样使用的随机森林回归。但区别是文中没有涉及预测,关注的重点在于识别重要的微生物类群。

    0b1f3330b8087bf9c8c4a731e4f624bd.png

    参考文献

    Edwards J, Santosmedellin C, Liechty Z, et al. Compositional shifts in root-associated bacterial and archaeal microbiota track the plant life cycle in field-grown rice. PLOS Biology, 2018, 16(2).Zhang J, Zhang N, Liu Y, et al. Root microbiota shift in rice correlates with resident time in the field and developmental stage. Science China-life Sciences, 2018, 61(6): 613-621.

    展开全文
  • 目录一、介绍随机森林模型不仅在预测问题上有着广泛的应用,在特征选择中也有一定的应用,这是因为,随机森林模型在拟合数据后,会对数据属性列,有一个变量重要性的度量,在sklearn中即为随机森林模型的 feature_...

    目录

    一、介绍

    随机森林模型不仅在预测问题上有着广泛的应用,在特征选择中也有一定的应用,这是因为,随机森林模型在拟合数据后,会对数据属性列,有一个变量重要性的度量,在sklearn中即为随机森林模型的 feature_importances_参数,这个参数将返回一个numpy数组对象,数组里的元素对应为随机森林模型在拟合后认为的所给训练属性列的重要程度,是数值类型数据,数组中元素之和为1。变量重要性度量数组中,数值越大的属性列对于预测的准确性更加重要。

    二、实验

    2.1 实验数据

    这里选用kaggle上的入门比赛,Housing Prices Competition for Kaggle Learn Users的数据集作为实验对象,这是一个预测房价的回归问题,数据集如下:

    c44958b575afd60e3e7800a8d57c8516.png

    这个数据有81个属性列,1460条数据。

    2.2 特征选择

    载入数据

    #getData函数为自定义的函数,其实就是调用了pandas的read_csv函数

    train, test = getData('./data/train.csv', './data/test.csv')

    1. 使用皮尔逊相关系数选择特征

    #根据皮尔逊相关系数选择与要预测的属性列SalePrice相关性最高的10个属性

    #[:11],选出11个是因为SalePrice自己与自己的相关性最高,所以要将它去除故选择排序后的前11个属性,再去除SalePrice

    features = train.corr()['SalePrice'].abs().sort_values(ascending=False)[:11]

    features.drop('SalePrice', axis=0, inplace=True)

    features = features.index

    结果如下

    482f5ab02947c2c6594fd382175ca9c7.png

    2. 使用随机森林模型选择特征

    #先用皮尔逊系数粗略的选择出相关性系数的绝对值大于0.3的属性列,这样不需要训练过多不重要的属性列

    #可以这么做而且不会破坏实验的控制变量原则,因为根据皮尔逊相关系数选择出的重要性排名前10的属性列

    #它们与要预测的属性列的皮尔逊相关系数均大于0.3,可以当成步骤1中也进行了同样的取相关系数为0.3的操作

    features = train.corr().columns[train.corr()['SalePrice'].abs()> .3]

    features = features.drop('SalePrice')

    #使用随机森林模型进行拟合的过程

    X_train = train[features]

    y_train = train['SalePrice']

    feat_labels = X_train.columns

    rf = RandomForestRegressor(n_estimators=100,max_depth=None)

    rf_pipe = Pipeline([('imputer', SimpleImputer(strategy='median')), ('standardize', StandardScaler()), ('rf', rf)])

    rf_pipe.fit(X_train, y_train)

    #根据随机森林模型的拟合结果选择特征

    rf = rf_pipe.__getitem__('rf')

    importance = rf.feature_importances_

    #np.argsort()返回待排序集合从下到大的索引值,[::-1]实现倒序,即最终imp_result内保存的是从大到小的索引值

    imp_result = np.argsort(importance)[::-1][:10]

    #按重要性从高到低输出属性列名和其重要性

    for i in range(len(imp_result)):

    print("%2d. %-*s %f" % (i + 1, 30, feat_labels[imp_result[i]], importance[imp_result[i]]))

    #对属性列,按属性重要性从高到低进行排序

    feat_labels = [feat_labels[i] for i in imp_result]

    #绘制特征重要性图像

    plt.title('Feature Importance')

    plt.bar(range(len(imp_result)), importance[imp_result], color='lightblue', align='center')

    plt.xticks(range(len(imp_result)), feat_labels, rotation=90)

    plt.xlim([-1, len(imp_result)])

    plt.tight_layout()

    plt.show()

    结果如下图:

    3354ac0d0875f473ecdc0412b64d25b0.png

    69d766131e332f366cbeda44735c489a.png

    可以看出,步骤2与步骤1中选择出来的属性列差别不大,不过步骤2表明随机森林模型在拟合后觉得OverallQual属性列的重要性很高。

    3. 使用同一个模型进行对比训练

    经实验,对于随机森林模型RandomForestRegressor(n_estimators=100,max_depth=None)而言,使用步骤1中的通过皮尔逊相关系数获得的属性列进行训练,得分为0.9778667641397033;而使用随机森林选择的特征进行训练,得分为0.9800629050754925。可以看出使用随机森林做特征选择,在这个数据集上对于提高模型的能力还是有一定的作用的。

    展开全文
  • R包randomForest的随机森林回归模型以及对重要变量选择​mp.weixin.qq.comR包randomForest的随机森林回归模型以及对重要变量选择关于随机森林(random forest),前文“随机森林分类以及对重要变量选择”中已经...

    R包randomForest的随机森林回归模型以及对重要变量的选择​mp.weixin.qq.com

    R包randomForest的随机森林回归模型以及对重要变量的选择

    关于随机森林(random forest),前文“随机森林分类以及对重要变量的选择”中已经对其基本原理作了简单概括。在前文中,响应变量是一组类别变量(代表了样本的分组信息),此时随机森林用于执行监督分类的功能,模型的精度在于通过选定的预测变量组合将样本正确划分归类的概率。而当响应变量是一组连续变量时,可将回归森林用于回归。此时,回归模型的精度体现了选定的预测变量对响应变量数值改变有关方差的整体解释率(可以理解为回归的R2)。本篇则简介随机森林的回归功能。

    文献中使用随机森林回归的一个实例

    首先来看一篇与植物根系微生物组有关研究,将文中涉及到随机森林回归的部分内容节选出来以帮助大家理解。

    Edwards等(2018)分析了来自两个地区(加利福尼亚州、阿肯色州)以及三个连续种植季(2014、2015、2016)的水稻根系微生物组,意在阐述水稻根系微生物群落的时间动态特征,并解释驱动微生物群落组建的成因。文中部分内容使用到随机森林的回归模型建立微生物丰度和水稻生长时期的关系,用以识别重要的时间响应微生物类群。

    作者首先分析了水稻根系微生物群落的组成结构,显示其受到地理区域(土壤环境)、植物生长时期以及植物根系不同部位的多重影响。随后分析各个因素的相对效应,发现水稻生长过程中能够逐渐对其根系菌群进行选择,植物生长时期的效应越来越明显,根系菌群朝向一组保守的物种组成趋势发展,同时地理环境效应的比重逐渐减弱。主要体现在:

    (1)不同地理区域种植的水稻,随着水稻生长时期的推移,根际和根内菌群的相似度逐渐增加,并在后期趋于稳定,与种植季节无关:

    (2)对于水稻根际和根内菌群,地区间独特OTU的相对丰度均随时间推移而不断下降,剩余的OTU中,两地区间共有OTU的比重上升。

    图A-C,水稻根系微生物群落的PCoA,分别突出了群落组成相似度与根系区域(A)、地理区域(B)或植物生长时间(C)的关系。

    图D,根区、根际和根内样本中,微生物群落相似度随植物生长的关系。

    总之存在一类具有显著时间特征的微生物类群,它们的丰度变化与水稻的生长时期密切相关,无论是增加(根系富集)或减少(根系排斥)。随后,作者期望寻找可用于区分水稻生长时期的微生物OTU组合,包括根际和根内菌群,就使用了随机森林。

    作者选择了一部分的样本(加利福尼亚州2014年和阿肯色州2016年的部分数据)用作训练集,通过随机森林分别将根际和根内所有微生物OTU的相对丰度与水稻生长时期进行了回归,并根据各个OTU对模型预测准确性的相对贡献按重要性进行排名。十折交叉验证用于评估模型中OTU数量与模型误差的关系,并按重要性排名对OTU进行选择,删除了大部分不重要OTU后,最终保留的OTU用于构建最终的随机森林回归模型。

    结果中,共确定了85个最重要的与水稻生长时期密切关联的OTU。训练集的数据显示,通过这85个OTU构建的随机森林回归模型分别解释了根际和根内菌群对植物年龄有关方差的91.5%和88.4%,表明它们的丰度组合能够准确预测水稻的生长时期。此外,测试集以及验证集数据(涉及了训练集样本外的其它采样时间、地理区域的样本)也一致地表明,通过这85个OTU构建的随机森林回归模型同样准确预测了水稻的生长时期,凸显了水稻根际和根内存在特定的微生物类群,在跨地理区域和季节的水稻植物的生命周期中表现出一致的模式。

    图A,横坐标是水稻的实际生长时期,纵坐标是随机森林模型通过根际或根内微生物丰度预测的水稻生长时期,模型具有很高的精度。

    图B,重要的85个OTU在水稻根际或根内的丰度与时间的关系。

    图C,85个OTU根据丰度的时间响应模式,可分为早期定植(丰度早期很高,但随时间降低)或晚期定植(丰度早期很低,但随时间增加)以及复合型(早期晚期定植区分不明显)类群,柱形图展示了3种类群中OTU平均丰度变化趋势。

    文中后续还有内容涉及到随机森林模型的应用,这里就不再展示了。节选的部分章节想必也足以能够帮助大家了解这个方法的实际应用了。

    此外,该文献的补充材料中提供了有关OTU丰度表、分析过程的R代码等非常全面的数据,大家若有兴趣参考原文即可。

    接下来,展示随机森林回归及对重要变量选择在R语言中的实现方法。

    通过R包randomForest的随机森林执行回归

    对于随机森林应用在类别型响应变量中的分类功能,前文“随机森林分类模型以及对重要变量的选择”中,已经以R包randomForest中的方法为例展示了如何通过随机森林构建分类预测模型(分类模型的训练和测试),以及筛选对区分已知分类具有高度鉴别模式的变量组合(评估变量的相对重要性)。

    在下文中,将响应变量更换为连续型变量,继续展示R包randomForest的随机森林回归方法以及实现对重要变量的选择。其实无论执行的分类还是回归,过程中使用的方法都是一样的,R函数还是那些R函数,区别只在于对部分函数的参数设置以及结果的解读方式上。

    下文的测试数据,R代码等的百度盘链接(提取码,fljz):

    若百度盘失效,也可在GitHub的备份中获取:

    示例数据

    植物根系菌群结构与植物生长密切相关,到目前为止,已经在许多研究中都有报道了,这已经是个共识。因此,下文的示例数据也同样来自某植物根际区域细菌群落组成的16S扩增子测序数据,类似地,仿照上文文献中的过程,通过随机森林建立微生物与植物生长时期的响应关系,根据微生物丰度推断植物生长时期,并寻找一组重要的时间特征类群。

    示例数据“otu_table.txt”中,共记录了45个连续生长时间中植物根际土壤样本中细菌OTU的相对丰度信息。

    “plant_age.txt”中,记录了这45个根际土壤样本对应的植物生长时间,时间单位是天。

    随机森林回归模型的初步构建

    将OTU丰度数据读入R中,可以事先作一些预处理,例如剔除低丰度类群等。

    随后,对应OTU丰度样本与植物生长时间的关系,加载randomForest包并运行随机森林。

    ##数据预处理

    #读取 OTUs 丰度表

    otu

    #过滤低丰度 OTUs 类群,它们对分类贡献度低,且影响计算效率

    #例如剔除总丰度低于 0.05% 的值

    otu = 0.0005), ]

    #合并有关于植物生长时间的信息

    plant

    otu

    otu

    otu

    #为了方便后续评估随机森林模型的性能

    #将总数据集分为训练集(占 70%)和测试集(占 30%)

    set.seed(123)

    train

    otu_train

    otu_test

    ##randomForest 包的随机森林

    library(randomForest)

    #随机森林计算(默认生成 500 棵决策树),详情 ?randomForest

    set.seed(123)

    otu_train.forest

    otu_train.forest

    结果中,% Var explained体现了预测变量(用于回归的所有OTU)对响应变量(植物年龄)有关方差的整体解释率。在本示例中,剔除了低丰度的OTU后,剩余的OTU(约2600个左右)解释了约89.17%的总方差,可以理解为该回归的R2=0.8917,相当可观的一个数值,表明该植物根际细菌的群落结构随植物生长密切相关。

    查看该模型的预测性能,可以看到具有较高的精度。

    #使用训练集,查看预测精度

    plant_predict

    plot(otu_train$plant_age, plant_predict, main = '训练集',

    xlab = 'Plant age (days)', ylab = 'Predict')

    abline(1, 1)

    #使用测试集,评估预测性能

    plant_predict

    plot(otu_test$plant_age, plant_predict, main = '测试集',

    xlab = 'Plant age (days)', ylab = 'Predict')

    abline(1, 1)

    重要的预测变量选择

    但是,并非这所有的2600余个OTU都对回归的精度具有可观的贡献。有些OTU丰度的时间特征并不明显,可能在回归中产生较大噪声,对模型精度带来较高的误差。因此,最好将低贡献的OTU去除。

    评估预测变量的重要性

    基于已经构建好的随机森林回归模型,可以从中评估OTU的重要性。将OTU按重要程度高低进行排名后,选择排名靠前的一部分OTU,这些重要的OTU是明显的与植物生长时间密切关联的一些细菌类群。

    ##OTU 的重要性评估

    #查看表示每个预测变量(细菌 OTU)重要性的得分

    #summary(otu_train.forest)

    importance_otu

    head(importance_otu)

    #或者使用函数 importance()

    importance_otu

    head(importance_otu)

    #作图展示 top30 重要的 OTUs

    varImpPlot(otu_train.forest, n.var = min(30, nrow(otu_train.forest$importance)),

    main = 'Top 30 - variable importance')

    “%IncMSE”即increase in mean squared error,通过对每一个预测变量随机赋值,如果该预测变量更为重要,那么其值被随机替换后模型预测的误差会增大。因此,该值越大表示该变量的重要性越大;

    “IncNodePurity”即increase in node purity,通过残差平方和来度量,代表了每个变量对分类树每个节点上观测值的异质性的影响,从而比较变量的重要性。该值越大表示该变量的重要性越大。

    对于“%IncMSE”或“IncNodePurity”,二选一作为判断预测变量重要性的指标。需注意的是,二者的排名存在一定的差异。

    #可以根据某种重要性的高低排个序,例如根据“IncNodePurity”指标

    importance_otu

    head(importance_otu)

    #输出表格

    #write.table(importance_otu, 'importance_otu.txt', sep = '\t', col.names = NA, quote = FALSE)

    交叉验证

    那么,最终选择多少重要的预测变量(本示例为OTUs)是更合适的呢?

    可通过执行十折交叉验证,根据交叉验证曲线对OTU进行取舍。交叉验证法的作用就是尝试利用不同的训练集/验证集划分来对模型做多组不同的训练/验证,来应对单独测试结果过于片面以及训练数据不足的问题。此处使用训练集本身进行交叉验证。

    ##交叉验证辅助评估选择特定数量的 OTU

    #5 次重复十折交叉验证

    set.seed(123)

    otu_train.cv

    otu_train.cv

    #提取验证结果绘图

    otu_train.cv

    otu_train.cv$otus

    otu_train.cv

    otu_train.cv$otus

    otu_train.cv.mean

    head(otu_train.cv.mean, 10)

    #拟合线图

    library(ggplot2)

    ggplot(otu_train.cv.mean, aes(Group.1, x)) +

    geom_line() +

    theme(panel.grid = element_blank(), panel.background = element_rect(color = 'black', fill = 'transparent')) +

    labs(title = '',x = 'Number of OTUs', y = 'Cross-validation error')

    交叉验证曲线展示了模型误差与用于拟合的OTU数量之间的关系。误差首先会随OTUs数量的增加而减少,开始时下降非常明显,但到了特定范围处,下降幅度将不再有显著变化,甚至有所增加。

    根据交叉验证曲线,提示保留9-13个重要的OTU即可以获得理想的回归结果,因为此时的误差达到最小。

    因此,根据计算得到的各OUT重要性的值(如“IncNodePurity”),将OTU由高往低排序后,最后大约选择前9-13个OTU就可以了。

    #提示保留 9-13 个重要的 OTU,可以使随机森林回归的精度最大化

    #首先根据某种重要性的高低排个序,例如根据“IncNodePurity”指标

    importance_otu

    #然后取出排名靠前的 OTU,例如 top10 最重要的 OTU

    importance_otu.select

    importance_otu.select

    #输出表格

    #write.table(importance_otu.select, 'importance_otu.select.txt', sep = '\t', col.names = NA, quote = FALSE)

    #有关 OTU 的物种分类信息等其它细节,可后续自行补充

    #不妨简单查看下这些重要的 OTU 丰度与植物生长时间的关系

    #可以看到趋势非常明显,包括根际富集或排斥等都有涉及

    otu_id.select

    otu.select

    otu.select

    ggplot(otu.select, aes(x = plant_age, y = value)) +

    geom_point() +

    geom_smooth() +

    facet_wrap(~variable, ncol = 3, scale = 'free_y') +

    labs(title = '',x = 'Plant age (days)', y = 'Relative abundance')

    最终模型的确定

    现在来看,只使用选择的10个重要的OTU构建回归模型,效果如何。

    ##只包含 10 个重要预测变量的简约回归

    otu.select

    #为了方便后续评估随机森林模型的性能,将总数据集分为训练集(占 70%)和测试集(占 30%)

    set.seed(123)

    train

    otu_train.select

    otu_test.select

    #随机森林计算(默认生成 500 棵决策树),详情 ?randomForest

    set.seed(123)

    otu_train.select.forest

    otu_train.select.forest

    #使用训练集,查看预测精度

    plant_predict

    plot(otu_train.select$plant_age, plant_predict, main = '训练集',

    xlab = 'Plant age (days)', ylab = 'Predict')

    abline(1, 1)

    #使用测试集,评估预测性能

    plant_predict

    plot(otu_test.select$plant_age, plant_predict, main = '测试集',

    xlab = 'Plant age (days)', ylab = 'Predict')

    abline(1, 1)

    结果显示,与先前使用全部的OTU(去除低丰度后约2600多个)相比,只使用这10个更重要OTU的随机森林回归模型,获得了更出色的效果。

    一是体现在% Var explained,模型中预测变量(这10个重要的OTU)对响应变量(植物年龄)有关方差的整体解释率达到了96.49%,大于先前的89.17%,这得益于排除了不重要或者高噪声的OTU。二是预测性能更佳,特别是对于测试集,与先前的分布图相比较(见上文),植物实际生长时间与通过根际菌群预测的植物年龄更趋一致。

    如果不涉及预测,只是评估变量的重要性

    上文过程中,为了评估随机森林回归模型的预测性能,将数据拆分为训练集和测试集分开讨论。但如果目的不涉及预测,只是为了寻找重要的预测变量,完全可以直接使用所有数据代入回归,无需再区分训练集与测试集,这也是很多文献中经常提到的方法。

    例如另一篇类似的研究,Zhang等(2018)寻找水稻根系中与植物生长期密切相关的biomarkers时,同样使用的随机森林回归。但区别是文中没有涉及预测,关注的重点在于识别重要的微生物类群。

    参考文献

    Edwards J, Santosmedellin C, Liechty Z, et al. Compositional shifts in root-associated bacterial and archaeal microbiota track the plant life cycle in field-grown rice. PLOS Biology, 2018, 16(2).Zhang J, Zhang N, Liu Y, et al. Root microbiota shift in rice correlates with resident time in the field and developmental stage. Science China-life Sciences, 2018, 61(6): 613-621.

    展开全文
  • R包randomForest的随机森林回归模型以及对重要变量选择关于随机森林(random forest),前文“随机森林分类以及对重要变量选择”中已经对其基本原理作了简单概括。在前文中,响应变量是一组类别变量(代表了样本的...
  • 一、决策树(类型、节点特征选择的算法原理、优缺点、随机森林算法产生的背景)1、分类树和回归树由目标变量是离散的还是连续的来决定的;目标变量是离散的,选择分类树;反之(目标变量是连续的,但自变量可以是分类的...
  • R包randomForest的随机森林分类模型以及对重要变量选择随机森林(random forest)是一种组成式的有监督学习方法,可视为决策树的扩展。随机森林通过对对象和变量进行抽样构建预测模型,即生成多个决策树,并依次对...
  • R包randomForest的随机森林回归模型以及对重要变量选择关于随机森林(random forest),前文“随机森林分类以及对重要变量选择”中已经对其基本原理作了简单概括。在前文中,响应变量是一组类别变量(代表了样本的...
  • 当数据集的特征过多时,容易产生过拟合,可以用随机森林来在训练之后可以产生一个各个特征重要性的数据集,利用这个数据集,确定一个阈值,选出来对模型训练帮助最大的一些特征,筛选出重要变量后可以再训练模型;...
  • 使用随机森林做特征选择

    千次阅读 2020-07-14 16:25:45
    随机森林模型不仅在预测问题上有着广泛的应用,在特征选择中也有一定的应用,这是因为,随机森林模型在拟合数据后,会对数据属性列,有一个变量重要性的度量,在sklearn中即为随机森林模型的 feature_importances_ ...
  • 前面机器学习第18篇 - Boruta特征变量筛选(2)已经完成了特征变量筛选,下面看下基于筛选的特征变量构建的模型准确性怎样?定义一个函数生成一些列用来测试的mtry (一系列不大于总变...
  • 当数据集的特征过多时,容易产生过拟合,可以用随机森林来在训练之后可以产生一个各个特征重要性的数据集,利用这个数据集,确定一个阈值,选出来对模型训练帮助最大的一些特征,筛选出重要变量后可以再训练模型;...
  • 随机森林用于特征选择

    千次阅读 2018-12-22 21:00:15
    随机森林可以计算单个特征变量的重要性。 计算特征X的重要性的方法: 对RF中的每一棵决策树,计算出OOB数据的误差,记作errOOB1errOOB1errOOB1 对所有OOB数据里的特征X加入噪声,然后计算OOB数据的误差,记作errOOB...
  • 随机森林之特征选择

    2013-11-28 10:41:00
    摘要:在随机森林介绍中提到了随机森林一个重要特征:能够计算单个特征变量的重要性。并且这一特征在很多方面能够得到应用,例如在银行贷款业务中能否正确的评估一个企业的信用度,关系到是否能够有效地回收贷款。但是...
  • 当数据集的特征过多时,容易产生过拟合,可以用随机森林来在训练之后可以产生一个各个特征重要性的数据集,利用这个数据集,确定一个阈值,选出来对模型训练帮助最大的一些特征,筛选出重要变量后可以再训练模型;...
  • 利用随机森林做特征选择

    千次阅读 2017-06-21 14:25:54
    摘要:在随机森林介绍中提到了随机森林一个重要特征:能够计算单个特征变量的重要性。并且这一特征在很多方面能够得到应用,例如在银行贷款业务中能否正确的评估一个企业的信用度,关系到是否能够有效地回收贷款。但是...
  • 目录1 什么是随机森林1.1 集成学习1.2 随机决策树1.3 随机森林1.4 投票2 为什么要用它3 使用方法3.1 变量选择3.2 分类3.3 回归4 一个简单的Python示例结语前言:随机森林是一个非常灵活的机器学习方法,从市场营销到...
  • R包randomForest的随机森林分类模型以及对重要变量选择随机森林(random forest)是一种组成式的有监督学习方法,可视为决策树的扩展。随机森林通过对对象和变量进行抽样构建预测模型,即生成多个决策树,并依次对...
  • 随机森林

    2017-04-01 12:27:24
    一、随机森林算法介绍  1、选择模型的数目m(即简单决策树的个数); 2、对i=1到m执行  3、从原始数据中生成一个bootstrap样本 4、在该样本上生成一个数模型 5、对每个分裂点执行  6、随机抽取k( 7、在这...
  • R包randomForest的随机森林分类模型以及对重要变量选择随机森林(random forest)是一种组成式的有监督学习方法,可视为决策树的扩展。随机森林通过对对象和变量进行抽样构建预测模型,即生成多个决策树,并依次对...
  • 当数据集的特征过多时,容易产生过拟合,可以用随机森林来在训练之后可以产生一个各个特征重要性的数据集,利用这个数据集,确定一个阈值,选出来对模型训练帮助最大的一些特征,筛选出重要变量后可以再训练模型;...
  • 随机森林工具箱

    2018-06-27 11:06:47
    随机森林工具箱,用于数据的训练和测试,可用于模式识别,变量选择等识别准确率较高。
  • 当数据集的特征过多时,容易产生过拟合,可以用随机森林来在训练之后可以产生一个各个特征重要性的数据集,利用这个数据集,确定一个阈值,选出来对模型训练帮助最大的一些特征,筛选出重要变量后可以再训练模型;...
  • 随机森林 RF

    2018-08-23 20:34:50
    Bagging与随机森林有什么区别呢? Bagging 随机有放回抽样。 RF在以决策树为基学习器构建Bagging集成的基础上,进一步在决策树的训练过程中引入随机属性选择。 传统决策树在选择划分属性时是在当前结点的属性...
  • 在这项研究中,我们开发了一种基于随机森林法预测RNA编辑的新方法。 基于最大相关最小冗余(mRMR)和增量特征选择(IFS)算法执行了仔细的特征选择过程。 从我们的数据集中的77个特征中选择了18个最佳特征,并用于...
  • [机器学习]漫谈随机森林算法

    千次阅读 2017-02-16 11:47:31
    目录1 什么是随机森林1.1 集成学习1.2 随机决策树1.3 随机森林1.4 投票2 为什么要用它3 使用方法3.1 变量选择3.2 分类3.3 回归4 一个简单的Python示例结语 前言: 随机森林是一个非常灵活的机器学习方法,从市场...
  • 随机森林综述随机性来源构成训练及预测超参数对模型性能的影响优点和...随机森林进一步在决策树训练时加入随机特征选择:如果有 M 个输入变量,每个节点都将随机选择 m(m<M)个特定的变量,然后运用这 m 个变量来确

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 172
精华内容 68
关键字:

随机森林变量选择