美文网首页数据-R语言-图表-决策-Linux-Python
小洁详解《R数据科学》--第17章 使用modelr实现基础模型

小洁详解《R数据科学》--第17章 使用modelr实现基础模型

作者: 小洁忘了怎么分身 | 来源:发表于2018-11-20 23:46 被阅读165次

建模过程:选定模型族- 拟合模型

1.准备工作

library(tidyverse)
## -- Attaching packages -------------------

## √ ggplot2 3.1.0     √ purrr   0.2.5
## √ tibble  1.4.2     √ dplyr   0.7.7
## √ tidyr   0.8.2     √ stringr 1.3.1
## √ readr   1.1.1     √ forcats 0.3.0

## -- Conflicts --- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(modelr)
options(na.action = na.warn)

2.简单模型

认识一下sim

sim1
## # A tibble: 30 x 2
##        x     y
##    <int> <dbl>
##  1     1  4.20
##  2     1  7.51
##  3     1  2.13
##  4     2  8.99
##  5     2 10.2 
##  6     2 11.3 
##  7     3  7.36
##  8     3 10.5 
##  9     3 10.5 
## 10     4 12.4 
## # ... with 20 more rows
class(sim1)
## [1] "tbl_df"     "tbl"        "data.frame"
str(sim1)
## Classes 'tbl_df', 'tbl' and 'data.frame':    30 obs. of  2 variables:
##  $ x: int  1 1 1 2 2 2 3 3 3 4 ...
##  $ y: num  4.2 7.51 2.13 8.99 10.24 ...

散点图

ggplot(sim1, aes(x, y)) +
       geom_point()

确定模型的基本形式

--线性--y= a_0 + a_1 * x

models <- tibble(
       a1 = runif(250, -20, 40),
       a2 = runif(250, -5, 5)
)
ggplot(sim1, aes(x, y)) +
       geom_abline(
         aes(intercept = a1, slope = a2),
data = models, alpha = 1/4 )+
       geom_point()

计算出的y值:预测值 y实际值:响应变量

计算预测值与实际值之间的差异

model1 <- function(a, data) {
       a[1] + data$x * a[2]
}
model1(c(7, 1.5), sim1)
##  [1]  8.5  8.5  8.5 10.0 10.0 10.0 11.5 11.5 11.5 13.0 13.0 13.0 14.5 14.5
## [15] 14.5 16.0 16.0 16.0 17.5 17.5 17.5 19.0 19.0 19.0 20.5 20.5 20.5 22.0
## [29] 22.0 22.0

这里的a有两个元素,分别是模型的两个参数。

给出了30个距离,实际上应该用均方根误差来表示,量化为一个数值。

measure_distance <- function(mod, data) {
       diff <- data$y - model1(mod, data)
       sqrt(mean(diff ^ 2))
}
measure_distance(c(7, 1.5), sim1)
## [1] 2.665212

使用purrr计算所有模型的均方根误差

sim1_dist <- function(a1, a2) {
       measure_distance(c(a1, a2), sim1)
}
models <- models %>%
  mutate(dist = purrr::map2_dbl(a1, a2, sim1_dist))
models
## # A tibble: 250 x 3
##        a1     a2  dist
##     <dbl>  <dbl> <dbl>
##  1 -19.1   0.176 34.1 
##  2 -14.1  -3.37  50.6 
##  3   6.48  3.08   8.73
##  4   9.80  2.08   6.12
##  5   5.49 -3.74  34.9 
##  6  36.9  -4.82  20.5 
##  7  34.0   1.90  29.0 
##  8  22.3   1.65  16.1 
##  9   2.46 -4.19  40.3 
## 10  37.0   3.49  40.9 
## # ... with 240 more rows

将最好的(dist最小的)10个模型覆盖到数据上。

ggplot(sim1, aes(x, y)) +
       geom_point(size = 2, color = "grey30") +
       geom_abline(
         aes(intercept = a1, slope = a2, color = -dist),
         data = filter(models, rank(dist) <= 10)
       )

intercept是截距,slope是斜率。

a1和a2组成散点图,红色边框显示前10个最佳模型

ggplot(models, aes(a1, a2)) +
       geom_point(
         data = filter(models, rank(dist) <= 10),
size = 4, color = "red" )+
       geom_point(aes(colour = -dist))

更加系统化的搜索模型参数的方法:

网格搜索法 这里的“系统”是相对于之前生成随机数的操作说的。

生成网格,显示最佳10个模型

grid <- expand.grid(
       a1 = seq(-5, 20, length = 25),
       a2 = seq(1, 3, length = 25)
) %>%
       mutate(dist = purrr::map2_dbl(a1, a2, sim1_dist))

grid %>%
       ggplot(aes(a1, a2)) +
       geom_point(
         data = filter(grid, rank(dist) <= 10),
size = 4, colour = "red" )+
       geom_point(aes(color = -dist))

!](https://img.haomeiwen.com/i9475888/bab16e1d583fb073.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

第三种方法:牛顿—拉夫逊搜索

best <- optim(c(0, 0), measure_distance, data = sim1) 
best$par
## [1] 4.222248 2.051204
ggplot(sim1, aes(x, y)) +
       geom_point(size = 2, color = "grey30") +
       geom_abline(intercept = best$par[1], slope = best$par[2])

线性模型拟合函数--lm()

sim1_mod <- lm(y ~ x, data = sim1)
coef(sim1_mod)
## (Intercept)           x 
##    4.220822    2.051533

emmm 所以lm这么厉害,我们为啥要学之前那三种奇怪的办法。有一种被大神耍了的感觉,是不是只是为了强调一下lm很厉害,😢。

3.模型可视化

(1)预测

data_grid() 生成一个数值范围,覆盖数据所在区域。

grid <- sim1 %>%
       data_grid(x)
grid
## # A tibble: 10 x 1
##        x
##    <int>
##  1     1
##  2     2
##  3     3
##  4     4
##  5     5
##  6     6
##  7     7
##  8     8
##  9     9
## 10    10

add_predictions() 添加预测值

grid <- grid %>%
        add_predictions(sim1_mod)
grid
## # A tibble: 10 x 2
##        x  pred
##    <int> <dbl>
##  1     1  6.27
##  2     2  8.32
##  3     3 10.4 
##  4     4 12.4 
##  5     5 14.5 
##  6     6 16.5 
##  7     7 18.6 
##  8     8 20.6 
##  9     9 22.7 
## 10    10 24.7
ggplot(sim1, aes(x)) +
        geom_point(aes(y = y)) +
        geom_line(
          aes(y = pred),
          data = grid,
          colour = "red",
          size = 1
)

(2)残差

--观测值与预测值之间的距离

--在原始数据种添加残差列

sim1 <- sim1 %>%
       add_residuals(sim1_mod)
sim1
## # A tibble: 30 x 3
##        x     y    resid
##    <int> <dbl>    <dbl>
##  1     1  4.20 -2.07   
##  2     1  7.51  1.24   
##  3     1  2.13 -4.15   
##  4     2  8.99  0.665  
##  5     2 10.2   1.92   
##  6     2 11.3   2.97   
##  7     3  7.36 -3.02   
##  8     3 10.5   0.130  
##  9     3 10.5   0.136  
## 10     4 12.4   0.00763
## # ... with 20 more rows

4.公式和模型族

df <- tribble(
       ~y, ~x1, ~x2,
       4, 2, 5,
       5, 1, 6
)
model_matrix(df, y ~ x1)
## # A tibble: 2 x 2
##   `(Intercept)`    x1
##           <dbl> <dbl>
## 1             1     2
## 2             1     1

model_matrix(df, y ~ x1 - 1)
## # A tibble: 2 x 1
##      x1
##   <dbl>
## 1     2
## 2     1

model_matrix(df, y ~ x1 + x2)
## # A tibble: 2 x 3
##   `(Intercept)`    x1    x2
##           <dbl> <dbl> <dbl>
## 1             1     2     5
## 2             1     1     6

???暂时不懂这有啥用。可能是例子不太好。

(1)分类变量

df <- tribble(
~ sex, ~ response,
"male", 1,
"female", 2,
"male", 1
)
model_matrix(df, response ~ sex)

## # A tibble: 3 x 2
##   `(Intercept)` sexmale
##           <dbl>   <dbl>
## 1             1       1
## 2             1       0
## 3             1       1

这里就可以类比到逻辑值和整数的转换,TRUE就是1,FALSE就是0,所以response的数值不管是几,转换后的值都是1和0,至于谁对应1,看结果第二列的列名,sex后面是谁。感觉这个例子很。。。

总结起来这一小节就说了一件事,分类变量模型预测值是观测值得均值。

(2)交互项

有两个预测变量(x1,x2)需要共同预测

mod1 <- lm(y ~ x1 + x2, data = sim3)
mod2 <- lm(y ~ x1 * x2, data = sim3)

grid <- sim3 %>%
data_grid(x1, x2) %>%
gather_predictions(mod1, mod2)
grid

## # A tibble: 80 x 4
##    model    x1 x2     pred
##    <chr> <int> <fct> <dbl>
##  1 mod1      1 a      1.67
##  2 mod1      1 b      4.56
##  3 mod1      1 c      6.48
##  4 mod1      1 d      4.03
##  5 mod1      2 a      1.48
##  6 mod1      2 b      4.37
##  7 mod1      2 c      6.28
##  8 mod1      2 d      3.84
##  9 mod1      3 a      1.28
## 10 mod1      3 b      4.17
## # ... with 70 more rows

两个模型的差别是:x1和x2是相互独立还是相互影响。

比较两个模型哪个更好

sim3 <- sim3 %>%
gather_residuals(mod1, mod2)
ggplot(sim3, aes(x1, resid, color = x2)) +
geom_point() +
facet_grid(model ~ x2)

用残差分布来比较。没有给出如何评价两个模型的方法,大概就是好的模型残差分布应该是比较均匀的(个人理解)。

引自评论soleil:残差那个应该是这样,响应值=可预测部分+不可预测的和随机误差。所以在去掉我们fit的模型即可预测的部分后,剩余的残差就应该是不可预测和随机误差,一般情况下是随机分布,即0上下随机,如果能看出有一定模式,就像mod1那个绿色,可能就说明有漏掉可预测部分,缺少交互项或者高价项。

(3) 交互项(两个连续变量)

seq_range()函数生成向量和最小值之间间隔相等的n个值。 参数: pretty 生成整齐一些的序列 trim/expand使数据集中一些或分散一些

mod1 <- lm(y ~ x1 + x2, data = sim4)
mod2 <- lm(y ~ x1 * x2, data = sim4)
grid <- sim4 %>%
data_grid(
x1 = seq_range(x1, 5),
x2 = seq_range(x2, 5)
) %>%
gather_predictions(mod1, mod2)
grid

## # A tibble: 50 x 4
##    model    x1    x2   pred
##    <chr> <dbl> <dbl>  <dbl>
##  1 mod1   -1    -1    0.996
##  2 mod1   -1    -0.5 -0.395
##  3 mod1   -1     0   -1.79 
##  4 mod1   -1     0.5 -3.18 
##  5 mod1   -1     1   -4.57 
##  6 mod1   -0.5  -1    1.91 
##  7 mod1   -0.5  -0.5  0.516
##  8 mod1   -0.5   0   -0.875
##  9 mod1   -0.5   0.5 -2.27 
## 10 mod1   -0.5   1   -3.66 
## # ... with 40 more rows

可视化比较两个模型

ggplot(grid, aes(x1, pred, color = x2, group = x2)) +
geom_line() +
facet_wrap(~ model)
ggplot(grid, aes(x2, pred, color = x1, group = x1)) +
geom_line() +
facet_wrap(~ model)

好像并没有太好的办法?大神说还可以逐步完善。(那你讲这干啥)

4.变量转换

大概就是一元多次方程的意思,x2,x3,x^n这样。一元一次方程对应的是直线,多次对应的是各种曲线。

I()包装+,*和^进行变量转换。

用poly简化x^n输入

df <- tribble(
~y, ~x,
1, 1,
2, 2,
3, 3
)
model_matrix(df, y ~ x^2 + x) #不包装时,x^2被删除
## # A tibble: 3 x 2
##   `(Intercept)`     x
##           <dbl> <dbl>
## 1             1     1
## 2             1     2
## 3             1     3

model_matrix(df, y ~ I(x^2) + x) #想要的结果

## # A tibble: 3 x 3
##   `(Intercept)` `I(x^2)`     x
##           <dbl>    <dbl> <dbl>
## 1             1        1     1
## 2             1        4     2
## 3             1        9     3

model_matrix(df, y ~ poly(x, 2)) #简化输入

## # A tibble: 3 x 3
##   `(Intercept)` `poly(x, 2)1` `poly(x, 2)2`
##           <dbl>         <dbl>         <dbl>
## 1             1     -7.07e- 1         0.408
## 2             1     -7.85e-17        -0.816
## 3             1      7.07e- 1         0.408


library(splines)
model_matrix(df, y ~ ns(x, 2)) #自然样条法 splines::ns()修正poly()超出数据范围的问题(还是不用poly直接用这个ns吧)

## # A tibble: 3 x 3
##   `(Intercept)` `ns(x, 2)1` `ns(x, 2)2`
##           <dbl>       <dbl>       <dbl>
## 1             1       0           0    
## 2             1       0.566      -0.211
## 3             1       0.344       0.771

非线性函数的模型拟合

#准备数据
sim5 <- tibble(
x = seq(0, 3.5 * pi, length = 50),
y = 4 * sin(x) + rnorm(length(x))
)
ggplot(sim5, aes(x, y)) +
geom_point()
#用5个模型拟合
mod1 <- lm(y ~ ns(x, 1), data = sim5)
mod2 <- lm(y ~ ns(x, 2), data = sim5)
mod3 <- lm(y ~ ns(x, 3), data = sim5)
mod4 <- lm(y ~ ns(x, 4), data = sim5)
mod5 <- lm(y ~ ns(x, 5), data = sim5)


grid <- sim5 %>%
data_grid(x = seq_range(x, n = 50, expand = 0.1)) %>%
gather_predictions(mod1, mod2, mod3, mod4, mod5, .pred = "y")

#可视化、分面对比
ggplot(sim5, aes(x, y)) +
geom_point() +
geom_line(data = grid, color = "red") +
facet_wrap(~ model)

5.缺失值

默认情况是产生警告信息

df <- tribble(
~x, ~y,
1, 2.2,
2, NA,
3, 3.5,
4, 8.3,
NA, 10
)
mod <- lm(y ~ x, data = df)

## Warning: Dropping 2 rows with missing values

不想看警告信息

mod <- lm(y ~ x, data = df, na.action = na.exclude)

看实际使用了多少个有效值(非缺失值)

nobs(mod)

微信公众号生信星球同步更新我的文章

友情链接:
生信技能树公益视频合辑:学习顺序是linux,r,软件安装,geo,小技巧,ngs组学!
B站链接:https://m.bilibili.com/space/338686099
YouTube链接:https://m.youtube.com/channel/UC67sImqK7V8tSWHMG8azIVA/playlists
生信工程师入门最佳指南:https://mp.weixin.qq.com/s/vaX4ttaLIa19MefD86WfUA
学徒培养:https://mp.weixin.qq.com/s/3jw3_PgZXYd7FomxEMxFmw
资料大全:https://mp.weixin.qq.com/s/QcES9u1vYh-l6LMXPgJIlA

相关文章

网友评论

    本文标题:小洁详解《R数据科学》--第17章 使用modelr实现基础模型

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