线性模型高级特征选择与更多分类技术
立即解锁
发布时间: 2025-09-09 01:52:01 阅读量: 5 订阅数: 21 AIGC 


精通R语言机器学习
### 线性模型高级特征选择与更多分类技术
#### 1. LASSO 回归
LASSO 回归的运行十分简单,只需将岭回归模型中的一个参数进行修改,即在 `glmnet()` 语法里把 `alpha=0` 改为 `alpha=1`。以下是具体代码及模型输出查看,我们会查看前 5 个和后 10 个结果:
```R
lasso <- glmnet(x, y, family = "gaussian", alpha = 1)
print(lasso)
```
输出结果如下:
```
Call: glmnet(x = x, y = y, family = "gaussian", alpha = 1)
Df %Dev Lambda
[1,] 0 0.00000 0.878900
[2,] 1 0.09126 0.800800
[3,] 1 0.16700 0.729700
[4,] 1 0.22990 0.664800
[5,] 1 0.28220 0.605800
........................
[60,] 8 0.70170 0.003632
[61,] 8 0.70170 0.003309
[62,] 8 0.70170 0.003015
[63,] 8 0.70170 0.002747
[64,] 8 0.70180 0.002503
[65,] 8 0.70180 0.002281
[66,] 8 0.70180 0.002078
[67,] 8 0.70180 0.001893
[68,] 8 0.70180 0.001725
[69,] 8 0.70180 0.001572
```
需要注意的是,模型构建过程在第 69 步停止了,因为随着 `lambda` 的减小,解释偏差不再改善。同时,`Df` 列会随着 `lambda` 的变化而改变。乍一看,当 `lambda` 为 0.001572 时,似乎所有 8 个特征都应包含在模型中。不过,为了便于讨论,我们尝试寻找并测试一个特征数量较少(约 7 个)的模型。观察输出行,我们发现当 `lambda` 约为 0.045 时,模型包含 7 个特征而非 8 个。因此,我们将此 `lambda` 用于测试集评估,如下所示:
```
[31,] 7 0.67240 0.053930
[32,] 7 0.67460 0.049140
[33,] 7 0.67650 0.044770
[34,] 8 0.67970 0.040790
[35,] 8 0.68340 0.037170
```
和岭回归一样,我们可以绘制结果:
```R
plot(lasso, xvar = "lambda", label = TRUE)
```
这个图很有趣,它直观地展示了 LASSO 回归的工作原理。注意标记为 8、3 和 6 的线条的变化,它们分别对应 `pgg45`、`age` 和 `lcp` 特征。看起来 `lcp` 的系数在它作为最后一个特征被加入之前一直处于或接近零。我们可以像处理岭回归那样,通过将其代入 `coef()` 函数来查看包含 7 个特征的模型的系数值:
```R
lasso.coef <- coef(lasso, s = 0.045, exact = TRUE)
lasso.coef
```
输出结果:
```
9 x 1 sparse Matrix of class "dgCMatrix"
1
(Intercept) -0.1305852115
lcavol 0.4479676523
lweight 0.5910362316
age -0.0073156274
lbph 0.0974129976
svi 0.4746795823
lcp .
gleason 0.2968395802
pgg45 0.0009790322
```
在 `lambda` 为 0.045 时,LASSO 算法将 `lcp` 的系数归零。以下是该模型在测试数据上的表现:
```R
lasso.y <- predict(lasso, newx = newx, type = "response", s = 0.045)
plot(lasso.y, test$lpsa, xlab = "Predicted", ylab = "Actual", main = "LASSO")
```
我们像之前一样计算均方误差(MSE):
```R
lasso.resid <- lasso.y - test$lpsa
mean(lasso.resid^2)
```
输出结果:
```
[1] 0.4437209
```
看起来我们得到了和之前类似的图,MSE 仅有轻微改善。我们最后大幅提升模型性能的希望寄托在弹性网络(Elastic Net)上。为此,我们仍然使用 `glmnet` 包,不同的是,我们要同时求解 `lambda` 和弹性网络参数 `alpha`。回顾一下,`alpha = 0` 是岭回归惩罚,`alpha = 1` 是 LASSO 惩罚,弹性网络参数的取值范围是 `0 ≤ alpha ≤ 1`。同时求解两个不同的参数可能会很复杂且令人沮丧,但我们可以借助 R 中的 `caret` 包来辅助完成。
#### 2. 弹性网络(Elastic Net)
`caret` 包即分类与回归训练包,它有一个很棒的配套网站,可帮助我们了解其所有功能:[http://topepo.github.io/caret/index.html](http://topepo.github.io/caret/index.html)。该包有许多不同的函数可供使用,这里我们的目标是找到 `lambda` 和弹性网络混合参数 `alpha` 的最优组合。这可以通过以下简单的三步流程实现:
1. **创建参数组合向量**:使用基础 R 中的 `expand.grid()` 函数创建一个包含所有我们想要研究的 `alpha` 和 `lambda` 可能组合的向量。我们尝试的超参数值如下:
- `alpha` 从 0 到 1,以 0.2 为增量递增(注意取值范围在 0 到 1 之间)。
- `lambda` 从 0.00 到 0.2,以 0.02 为步长递增,这个范围是为了和之前岭回归(`lambda=0.1`)和 LASSO(`lambda=0.045`)的结果有所缓冲。
代码如下:
```R
grid <- expand.grid(.alpha = seq(0, 1, by = .2), .lambda = seq(0.00, 0.2, by = 0.02))
```
使用 `table()` 函数可以查看这 66 种组合的完整集合:
```R
table(grid)
```
输出结果:
|.lambda | 0 | 0.02 | 0.04 | 0.06 | 0.08 | 0.1 | 0.12 | 0.14 | 0.16 | 0.18 | 0.2 |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 0.2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 0.4 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 0.6 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 0.8 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
我们可以确认这就是我们想要的 `alpha` 从 0 到 1,`lambda` 从 0 到 0.2 的组合。
2. **确定重采样方法**:使用 `caret` 包中的 `trainControl()` 函数确定重采样方法,这里我们使用留一法交叉验证(LOOCV)。同时,可以使用 `selectionFunction()` 在 `trainControl()` 中指定模型选择标准。对于定量响应,算法默认会根据均方根误差(RMSE)进行选择,这正符合我们的需求。
```R
control <- trainControl(method = "LOOCV")
```
3. **训练模型并确定最优参数**:现在使用 `train()` 函数来确定最优的弹性网络参数。该函数类似于 `lm()`,我们只需添加以下语法:`method="glmnet"`、`trControl=control` 和 `tuneGrid=grid`。将结果存
0
0
复制全文
相关推荐










