多分类场景下glmnet特征选择的结果解读及可行性探讨
多分类场景下glmnet的特征选择解读
glmnet是常用的特征选择工具,二分类场景下的用法清晰直观:
library(glmnet)
# 加载二分类数据集 data(BinomialExample) # 截取前10列缩小数据集规模 x <- BinomialExample$x[,1:10] y <- BinomialExample$y # 交叉验证拟合模型 cvfit = cv.glmnet(x, y, family = "binomial") # 提取系数 coefs <- coef(cvfit)
coefs中系数非零的特征(除截距项)就是被选中的特征,本例中V1和V7系数为.(即零),其余特征均被选中:
> coefs 11 x 1 sparse Matrix of class "dgCMatrix" s1 (Intercept) 0.1048257 V1 . V2 0.5901863 V3 -0.4060696 V4 -0.9627180 V5 -0.1067188 V6 -0.7813739 V7 . V8 -0.4106554 V9 0.5733065 V10 -1.0492793
但在类别数大于2的多分类场景下,coefs会返回每个类别对应的系数矩阵,这时候很多人会疑惑:该选哪一组作为最优特征集?glmnet还能用来做多分类特征选择吗?
先看多分类的示例代码:
# 加载多分类数据集 data(MultinomialExample) x <- MultinomialExample$x[,1:10] y <- MultinomialExample$y # 交叉验证拟合多分类模型 cvfit = cv.glmnet(x, y, family = "multinomial") # 提取系数 coefs <- coef(cvfit)
此时coefs是一个列表,每个元素对应一个类别的系数矩阵:
> coefs $`1` 11 x 1 sparse Matrix of class "dgCMatrix" 1 (Intercept) -0.03279324 V1 . V2 -0.08585827 V3 0.40882396 V4 -0.08639670 V5 -0.15763031 V6 0.22513768 V7 . V8 0.17657623 V9 . V10 . $`2` 11 x 1 sparse Matrix of class "dgCMatrix" 1 (Intercept) 0.01255996 V1 -0.21913800 V2 . V3 . V4 . V5 0.41329881 V6 . V7 . V8 . V9 -0.57131512 V10 0.52214739 $`3` 11 x 1 sparse Matrix of class "dgCMatrix" 1 (Intercept) 0.02023328 V1 0.09163282 V2 0.42655929 V3 . V4 0.29403632 V5 . V6 -0.12306560 V7 . V8 -0.44815059 V9 0.88580234 V10 -0.20920812
核心解答
glmnet完全可以用于多分类场景的特征选择,关键是理解多分类模型的逻辑:
- 多分类glmnet默认采用**一对多(one-vs-rest)**策略,为每个类别训练一个二分类模型,因此每个类别对应一组系数。
- 不存在“选某一组作为最优特征集”的说法,特征选择需要服务于整个多分类任务:只要某个特征在任意一个类别的系数不为0,就说明它对区分该类别与其他类别有贡献,应该被保留。
实操方法:提取所有有效特征
可以通过遍历所有类别的系数矩阵,提取所有非零且非截距项的特征,取去重后的并集作为最终特征集:
# 遍历每个类别的系数矩阵,筛选非零特征(排除截距项) selected_features <- unique(unlist(lapply(coefs, function(mat) { # 找出系数非零的行名,排除截距项 rownames(mat)[mat != 0 & rownames(mat) != "(Intercept)"] }))) # 查看选中的特征 selected_features
运行后会得到所有对多分类有贡献的特征,比如本例中除了V7之外的所有特征都会被选中——因为V7在三个类别的系数都是0,说明它对区分任何类别都没有帮助。
内容的提问来源于stack exchange,提问作者artgram
相关产品推荐
相关产品推荐

