搜索
查看: 627|回复: 0

[R] R for data science 第17章 使用modelr实现基础模型

[复制链接]

39

主题

40

帖子

289

积分

中级会员

Rank: 3Rank: 3

积分
289
发表于 2018-11-29 16:04:09 | 显示全部楼层 |阅读模式
R for data science  第17章  使用modelr实现基础模型
模型
  • 模型的作用是提供一个简单的、低维度的数据集摘要。理想情况下,模型可以捕获真正的“信号”(即由我们感兴趣的现象生成的模式),并忽略“噪声”(即我们不感兴趣的随机变动)。
  • 预测”模型,顾名思义,也就是能够生成预测的模型
  • “数据发现”模型。这种模型的目标不是进行预测,而是帮助我们发现数据中有趣的关系。
    • 进行验证性分析,一种方法是在进行分析前将数据分成 3 个部分。

      • 将 60% 的数据作为训练集,或称探索集。你可以对这部分数据进行任意操作,比如可 视化,或者用数据拟合多个模型。
      • 将 20% 的数据作为查询集。你可以使用这部分数据来比较模型或者进行手动可视化, 但不能将其用于自动化过程。
      • 将 20% 的数据留作测试集。这部分数据只能使用一次,用于测试最终模型。

    • 可以使用训练集数据进行探索,偶尔生成候选假设,并使用 查询集数据进行验证。确信已经得到正确的模型后,你就可以使用测试集数据进行一次 验证了。


17.1 简介
  • 建模过程可以分为两个阶段。
    • 首先,你需要定义一个模型族来表示一种精确但一般性的模式,这种模式就是我们想要捕获的。
    • 接下来你要生成一个拟合模型,方法是从模型族中找出最接近数据的一个模型。这个阶 段使得一般性的模型族具体化为特定模型

  • 拟合模型只是模型族中与数据最接近的一个模型。这意味着你找到了“最佳”模型(按照某些标准),但并不意味着你找到了良好的模型,而且也绝不代表这个模型是“真的”。

  • 准备工作
    • library(tidyverse)
      library(modelr)
      options(na.action=na.warn)

17.2 一个简单模型
  • 模拟数据集 sim1,它包含两个连续型变量 x 和 y。我们将这两个变量绘制出来,以查看二者间的关系:

  • R中有专门用于拟合线性模型的工具,即 lm() 函数。lm() 用一种特殊方法来表示模型族:公式。公式的形式为 y ~ x,lm() 会将这种形式的公式转换成类似 y = a_1 + a_2 * x 的函数。我们使用 lm() 来拟合这个模型,并检查输出

sim1_mod<-lm(y~x, data=sim1)
coef(sim1_mod)
  • lm() 使用了一种非常复杂的算法,通过几何学、微积分和线性代数间的一些关系,它只需要一个步骤就可以找出最近似的模型。这种方法的速度非常快,而且一定能找到全局最小值。

17.3 模型可视化
  • 通过预测来理解模型。这种方法的一大优点是,每种类型的预测模型都要进行预测
  • 找出模型未捕获的信息也是非常有用的,即所谓的残差,它是数据去除预测值后剩余的部分。残差是非常强大的,因为它允许我们使用模型去除数据中显著的模式,以便对剩余的微妙趋势进行研究。
  • 预测
    • 要想对模型的预测进行可视化表示,首先要生成一个分布均匀的数值网格,以覆盖数据所在区域。完成这个任务最简单的方式就是使用 modelr::data_grid() 函数,其第一个参数是一个数据框,对于随后的每个参数,它都会找出其中的唯一值,然后生成所有组合
    • 接着添加预测值。我们使用的是 modelr::add_predictions() 函数,其参数是一个数据框和一个模型。这个函数可以将模型的预测值作为一个新列添加到数据框中
    • grid<-grid%>%
             add_predictions(sim1_mod)
      grid
    • 下一步是绘制预测值。

  • 与预测值相对的是残差。预测值可以告诉我们模型捕获的模式,残差则表示模型漏掉的部分。残差就是我们前面计算过的观测值与预测值间的距离。
    • 使用 add_residuals() 函数将残差添加到数据中,这个函数与 add_predictions()非常相似。但注意,我们使用的是原始数据,不是生成的网格,因为计算残差需要使用实际的 y 值
    • sim1<-sim1%>%
            add_residuals(sim1_mod)
      sim1
    • 对于残差可以反映出模型的哪些信息
      • 简单地绘制频率多边形图,以帮助我们理解残差的分布
        • 这种方法可以反映出模型的质量:模型预测值与实际观测值的差别有多大?注意,残差的平均值总是为 0。
        • 使用残差代替原来的预测变量来重新绘图。




17.4 公式和模型族
  • R 中的绝大多数建模函数都使用一种标准转换将公式转换为表示模型族的方程。
    • 一个简单的转换:y ~ x 转换为 y = a_1 + a_2 * x。
    • 如果想看 R 到底进行了什么转换,可以使用 model_matrix() 函数。这个函数接受一个数据框和一个公式,并返回一个定义了模型方程的 tibble,其中每一列都关联到方程的一个系数,方程的形式总是类似于 y = a_1 * out1 + a_2 * out_2。
    • R 向模型加入截距项的方法是,加入一个值全是 1 的列。默认情况下,R 总是加入这一列。如果不想要截距项,那么你必须使用 -1 来明确丢弃它
    • 如果向模型中添加更多变量,那么模型矩阵当然也会随之增长
    • 分类变量
      • 带有分类变量 x 的模型会为每个分类预测出均值。(为什么?因为均值会使均方根距离最小化。)如果将预测值覆盖到原始数据上,就很容易看出这一点
      • 不能对未观测到的水平进行预测。因为有时会不小心进行这种预测,会有这条错误信息

    • 交互项(连续变量与分类变量)
      • 要想对这样的模型进行可视化,需要两种新技巧。
        • 因为有两个预测变量,所以我们需要将这两个变量都传给 data_grid() 函数。这个函数会找出 x1 和 x2 中的所有唯一值,并生成所有组合。
        • 要想为以上的两个模型同时生成预测,可以使用 gather_predictions() 函数,它可 以将每个预测作为一行加入数据框。与 gather_predictions() 互补的函数是 spread_ predictions(),后者可以将每个预测作为一列加入数据框。




  • 交互项(两个连续变量)
    • seq_range() 的 3 个有用的参数
      • pretty = TRUE 会生成一个“漂亮的”序列
      • trim = 0.1会截断10%的尾部值。如果变量具有长尾分布,而你希望尽量生成中心附 近的值,那么就可以使用这个参数
      • expand = 0.1 从某种程度上来说是 trim() 的反函数,它可以将取值范围扩大 10%


  • 变量转换
    • 如果搞不清模型在做什么,可以使用 model_matrix() 函数查看 lm() 到底在拟合哪个方程
    • 变量转换非常有用,因为你可以使用它们来近似表示非线性函数。


17.5 缺失值
  • 对于变量间的关系,缺失值显然不能传达出任何信息,因此建模函数会丢弃包含缺失值的所有行。默认情况下,R 会不声不响地丢弃这种数据,但是 options(na.action = na.warn) (我们在准备工作中运行过这行代码)可以确保我们收到一条警告信息

  • 要想阻止错误信息,可以设置 na.action = na.exclude
    mod<-lm(y~x, data=df, na.action=na.exclude)
  • 通过 nobs() 函数,你可以知道模型实际使用了多少个观测

nobs(mod)17.6 其他模型族
  • 本章的重点完全在于线性模型,其假设变量间的关系是 y = a_1 * x1 + a_2 * x2 + ... +a_n * xn的形式。线性模型还假设残差服从正态分布
  • 广义线性模型,如 stats::glm() 函数。线性模型假设响应变量是连续的,并且误差服 从正态分布。广义线性模型将线性模型扩展为可以包括非连续型的响应变量(如二值数 据或计数)。它们基于似然这一统计思想,通过定义距离的度量来工作。
  • 广义可加模型,如 mgcv::gam() 函数。该模型可以扩展广义线性模型,使其包含任意的 平滑函数。这意味着,你可以写出y ~ s(x)这样的公式,它可以转化为y = f(x)这样 的方程,并使用 gam() 函数估计出方程的形式(由于某些平滑性条件的限制,这个问题 还是比较容易解决的)。
  • 带有惩罚项的线性模型,如 glmnet::glmnet() 函数。该模型向距离添加一个惩罚项,以 惩罚复杂的模型(使用参数向量和原点间的距离来定义)。在扩展到来自同一总体的新 数据集时,这种方法生成的模型更容易取得良好的效果。
  • 健壮线性模型,如 MASS:rlm()。该模型对过远的距离进行调整,以降低远距离的权重。 这样一来,模型对异常值就不会太敏感,但代价是当没有异常值时,效果不是特别好。
  • 树模型,如 rpart::rpart()。该模型使用与线性模型完全不同的方法来解决问题。树模 型拟合一个分段常数模型,将数据逐渐划分为越来越小的多个部分。树模型本身的效率 不是特别高,但如果使用随机森林(random forest,如 randomForest::randomForest() 函数) 或梯度提升机(gradient boosting machine,如 xgboost::xgboost() 函数)这样的模型将 它们聚合起来使用时,其功能是非常强大的。





上一篇:生信技能书
下一篇:慧美——R for data science 第18章 模型构建
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|生信技能树 ( 粤ICP备15016384号  

GMT+8, 2019-9-18 20:30 , Processed in 0.035527 second(s), 26 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.