简介:一份面向R语言学习者与机器学习入门者的代码资源包,汇总了常用监督学习和无监督学习算法的R实现,覆盖简单/多元线性回归、多项式回归、决策树、SVR、数据预处理等模块,适合边看边练、快速搭建从数据清洗到模型训练的完整流程。整个压缩包共20个文件,包含8个R脚本算法实现代码、6个CSV演示数据集以及LICENSE说明,包体仅16KB,轻量而聚焦,适合直接查看脚本逻辑和复现示例。已有241人学习/下载,适合有一定R基础但希望熟悉ML算法调用与参数设置的读者。内容包含多个回归与决策树脚本,以及增强版数据预处理模板,可对照Data.csv等示例数据理解数据清洗、特征处理和模型训练过程,也可以作为二次开发的基础代码库,适用于课程设计、项目实战或面试复习等场景,提升实操效率。 这几年的机器学习话题,几乎被Python包圆了。但你要是跟我一样,平时做数据分析、搞统计建模,主力工具是R,那完全没必要为了跑个算法就换语言。R语言里的机器学习生态早就很成熟了,从最经典的线性回归,到SVM、决策树、随机森林、XGBoost,再到K-means、DBSCAN、PCA这些无监督方法,主流ML算法都能在R里稳定落地。这篇内容就是一条能直接照着走的路线:先用R把环境搭起来,然后把分类、回归、聚类、降维几类算法挨个跑一遍,最后说清楚评估和调参时容易踩的坑。正在看周志华《机器学习》或者李航《统计学习方法》、准备动手复现的同学,还有正要用R做数据分析但被各种包搞晕的从业者,都适合从头到尾读一遍。
1. 整体思路:为什么用R来跑机器学习
1.1 R语言在机器学习里的定位
先聊点实际的。R语言做机器学习到底行不行?实事求是地说,如果目标是部署一个高并发、低延迟的在线预测服务,R不是首选,Python的生态和工程化程度确实更合适。但如果是做分析型项目,需要频繁做统计检验、画图、跑回归,还想在同一个环境里顺手比较十来个模型,R反而顺手得多。原因很简单:R里面统计建模和可视化本来就是亲儿子,tidyverse把数据清洗做得非常顺畅,caret和tidymodels又把机器学习流程标准化了。另外在R里做时间序列也是传统强项,forecast、sarima这些包都很成熟。所以我的结论是:别纠结“哪个语言更厉害”,先看你手头的任务和团队工具链是什么。R做研究、做分析、做报告,是极其顺滑的;Python做强部署、做复杂产品,工程上更占优。
1.2 算法选型的基本原则
选算法不要看哪个“高级”,先看你的数据有什么标签、样本量多大、要解释还是要预测。我的习惯是这样选:有监督分类先跑逻辑回归或者决策树作为基线,再看要不要上随机森林或XGBoost;回归问题先跑线性回归做诊断,非线性关系明显就往树模型或者正则化回归上靠;无监督场景,数据比较规整就试K-means或层次聚类,有噪声、形状不规则就考虑DBSCAN;特征太多先做PCA降维,再进入后续建模。下面这张表是我常用的算法和R包对照,可以直接当速查表用。
| 任务 | 算法 | R包 | 一句话说明 |
|---|---|---|---|
| 回归 | 线性回归 | stats::lm() | 基准模型,可解释性强 |
| 二分类 | 逻辑回归 | stats::glm() | 概率输出,适合做基线 |
| 分类/回归 | 决策树 | rpart | 结果可解释,需要剪枝 |
| 分类/回归 | 随机森林 | randomForest | 抗过拟合,特征重要性实用 |
| 分类/回归 | XGBoost | xgboost | 效果最强,调参成本高 |
| 分类 | SVM | e1071 | 小样本高维有效,必须标准化 |
| 聚类 | K-means | stats::kmeans | 快,适合球形簇 |
| 聚类 | 层次聚类 | stats::hclust | 输出树状图,直观 |
| 聚类 | DBSCAN | dbscan | 能处理噪声和任意形状 |
| 降维 | PCA | stats::prcomp | 最常用的线性降维方法 |
2. 环境准备与数据预处理
2.1 搭建R的机器学习环境
第一步是安装R和RStudio。RStudio不是必须,但我建议装,写脚本、看变量、画图都方便。如果你不喜欢RStudio,用VS Code加R插件也能跑,不过RStudio对变量查看、包管理、绘图窗口的集成度更好,新手就别在这上面折腾。Windows用户如果后面用到需要编译的包,比如xgboost,可能要装Rtools。包管理我强烈建议用renv,特别是同时做好几个项目的时候,不然容易出现“昨天还能跑,今天装了一个新包就报错”的情况。
# 一次性安装常用包 install.packages(c( "tidyverse", "caret", "tidymodels", "randomForest", "e1071", "rpart", "xgboost", "dbscan", "factoextra", "pROC", "glmnet" ))安装完后可以跑一下 library(tidyverse) 测试,如果没有报错,环境基本就通了。需要注意,安装过程里如果看到 had non-zero exit status 的提示,先把出错信息复制到搜索引擎,八成能找到现成解决办法,不要反复 install.packages,那是在浪费时间。
2.2 数据清洗与特征编码
R里跑机器学习,数据预处理有个跟Python很不一样的点:R的data.frame会把字符串列自动转成因子factor,而很多算法对这个非常敏感。比如读入一个csv之后直接跑KNN或SVM,如果不处理因子列,轻则警告,重则结果完全不对。所以数据进来之后第一件事永远是 str(),看每一列是什么类型。
缺失值我用 tidyr::drop_na() 或者做填充。因子转数值,我习惯用 model.matrix() 生成哑变量矩阵,但记住哑变量只需要n-1列,否则会产生完全共线性,导致线性回归的系数估计直接崩掉。连续特征建议统一标准化,后面跑SVM、KNN、PCA都很重要。标准化在caret里直接用 preProcess() 比较顺手:
library(caret) preProc <- preProcess(iris[, 1:4], method = c("center", "scale")) scaled <- predict(preProc, iris[, 1:4])需要注意,preProcess 是在训练集上拟合的,之后转换测试集要沿用这个 preProc 对象,而不是在测试集上单独算一遍均值方差,不然会有数据泄漏,模型评估会虚高。
3. 核心算法实现与参数要点
3.1 回归族:线性回归与逻辑回归
先说回归。无论任务是预测连续变量还是做二分类,R里都有非常成熟的实现。我平常写线性回归,基本就是一行公式加一个 summary 出来看结果,这里用 mtcars 数据做一个最小示例:
lm_fit <- lm(mpg ~ wt + hp + qsec, data = mtcars) summary(lm_fit)重点看 Pr(>|t|) 和 R²。但R²别盲目追求,高R²不代表模型就好,要结合残差诊断。R里 plot(lm_fit) 会一次性输出残差图、Q-Q图、位置-尺度图、残差vs杠杆图,新手一定要学会看。如果残差有明显趋势,说明模型缺了非线性项或者交互项。
逻辑回归用 glm:
glm_fit <- glm(Species == "versicolor" ~ Sepal.Length + Sepal.Width, data = iris, family = binomial) summary(glm_fit)注意 family = binomial 这个参数不能漏,漏了就是普通线性回归。输出里的AIC是相对比较模型用的,越小越好,但别只看绝对数值。逻辑回归的系数要做指数变换才能解释成优势比,这点很多新手不知道。
3.2 树模型:决策树、随机森林与XGBoost
决策树入门时最喜欢,因为它结果画出来谁都能看懂。R里一般用 rpart 包建模,配合 rpart.plot 做可视化,非常适合把模型讲给业务部门听。rpart 的算法本身做了很多剪枝控制,直接跑的话树可能偏大,后面要用复杂度参数 cp 控制。先看最小用法:
library(rpart) library(rpart.plot) tree_fit <- rpart(Species ~ ., data = iris) rpart.plot(tree_fit)树模型的好处是不用做特征标准化,因子列直接处理,解释性很强。但默认 rpart 容易过拟合,所以要么用 cp 参数控制复杂度,要么用 prune() 剪枝。如果不想手动调,就用 caret::train() 统一跑,里面设 method = "rpart",通过网格搜索找最优 cp。
随机森林更省心,randomForest 训练完之后能直接输出变量重要性,这在业务分析里非常实用:
rf_fit <- randomForest(Species ~ ., data = iris, ntree = 500, importance = TRUE) importance(rf_fit) varImpPlot(rf_fit)ntree 建议500起步,不需要太少。randomForest 有个隐藏缺点,面对因子水平非常多的分类问题会特别吃内存,如果因子超过几十个,跑起来很慢,那时候可以换 ranger 包加速。
XGBoost 在R里的接口跟Python不太一样,需要先把数据转成 xgb.DMatrix。给个最简示例:
library(xgboost) dtrain <- xgb.DMatrix(data = as.matrix(iris[1:4]), label = as.numeric(iris$Species) - 1) params <- list(objective = "multi:softmax", num_class = 3, eta = 0.1, max_depth = 3) xgb_fit <- xgb.train(params = params, data = dtrain, nrounds = 100)它最大的坑是因子列不能直接传,必须转成数值矩阵,分类标签要从0开始编号。调参方面,eta、max_depth、subsample 这三个先调。数据量大的时候,R里XGBoost也可以开 hist 树构造算法,速度会明显更快。
3.3 支持向量机与K近邻
SVM 在R里首选 e1071 包的 svm 函数,它对特征尺度极度敏感,所以训练前一定要标准化。标准化上面已经用 preProcess 做过了,如果是第一次用,建议再跑一下 scale() 看看效果,画个箱线图确认量纲一致。用 iris 前两列做一个可视化分界的例子:
library(e1071) svm_fit <- svm(Species ~ Sepal.Length + Sepal.Width, data = iris, kernel = "radial", cost = 10, gamma = 0.1) plot(svm_fit, iris, Sepal.Length ~ Sepal.Width)cost 控制误分类惩罚,gamma 控制径向基核的影响范围。cost 越大越容易过拟合,gamma 越大越容易让每个样本都变成支持向量。新手可以先默认参数,再用caret统一调。注意 e1071 的 svm 对小数据集很友好,大数据集会慢到让人怀疑人生。
KNN 在R里可以用 class::knn(),但配合 caret 更顺手。K值太小会过拟合,太大又会让决策边界变得太平滑。一般用奇数,比如5、7、9,然后通过交叉验证挑一个。KNN 对异常值敏感,高维数据基本无能为力,跑之前务必先降维或者做特征选择。
3.4 聚类算法:K-means、层次聚类与DBSCAN
聚类是最能体现R语言“统计味”的部分。K-means 用 kmeans(),关键是 k 的选取和 nstart 的值:
km_fit <- kmeans(iris[, 1:4], centers = 3, nstart = 25) library(factoextra) fviz_cluster(km_fit, data = iris[, 1:4])nstart=25 的意思是随机初始化25次取最优,这个参数别省。k 的选取,可以用 factoextra 包的 fviz_nbclust() 看肘部图,也可以算轮廓系数来判断簇的合理性。
层次聚类则用 hclust(),先算距离矩阵:
dist_mat <- dist(iris[, 1:4], method = "euclidean") hc_fit <- hclust(dist_mat, method = "ward.D2") plot(hc_fit) groups <- cutree(hc_fit, k = 3)距离方法有 euclidean、manhattan 等,连接方法有 complete、average、ward.D2,这些组合对结果影响非常大。我一般优先试 ward.D2,它倾向于生成大小比较均匀的簇。cutree() 做剪枝很直观,给定 k 就能得到每个样本的簇标签。
DBSCAN 用 dbscan 包,它最大的优点是不用提前指定簇数量,但 eps 和 minPts 两个参数需要自己试。eps 太小全变成噪点,太大全并成一坨。最简单的调参方式是用 kNN 距离图:
library(dbscan) kNNdistplot(iris[, 1:4], k = 5) # 画出来之后在“拐点”附近选eps db_fit <- dbscan(iris[, 1:4], eps = 0.5, minPts = 5)minPts 一般取数据维度数乘2左右,或者根据对噪声的容忍度调整。这一步我在真实业务数据上试过很多次,数据密度不均匀时 DBSCAN 比 K-means 稳得多,但调参也更费时间。
3.5 降维算法:PCA与特征提取
PCA 在R里用 prcomp(),注意两个容易踩的坑:第一,必须设置 scale.=TRUE,否则量纲大的变量会主导主成分;第二,prcomp 返回的对象要用 summary() 看每个主成分的方差贡献比例。
pca_fit <- prcomp(iris[, 1:4], scale. = TRUE) summary(pca_fit) biplot(pca_fit)前两个主成分如果累计贡献率超过80%,后面建模用这两个分就行。如果想看变量对主成分的贡献,查看载荷矩阵 pca_fit$rotation。个人喜欢用 factoextra::fviz_pca_var() 画变量箭头图,比原生的 biplot 更好读。理解PCA的时候,R里的 eigen() 函数也会经常碰到,它和 prcomp 本质都在做特征值分解,只是 prcomp 的数值稳定性更好,日常直接用 prcomp 就行。
4. 建模流程、评估与调参
4.1 训练集/测试集划分与交叉验证
很多新手直接拿全量数据训练模型,然后在同一批数据上报告准确率,这是最典型的新手错误。R里用 caret 的 createDataPartition 可以按类别比例划分数据:
set.seed(123) trainIndex <- createDataPartition(iris$Species, p = 0.7, list = FALSE) train_data <- iris[trainIndex, ] test_data <- iris[-trainIndex, ]set.seed() 一定要有,否则每次划分都不一样,结果不可复现。交叉验证也推荐用 caret 统一做。我一般用5折,在大多数数据集上性价比最高,折数太少估计不稳,折数太多训练时间直线上升。
ctrl <- trainControl(method = "cv", number = 5, classProbs = TRUE, summaryFunction = multiClassSummary)classProbs=TRUE 是为了后面算ROC等概率型指标。如果样本量较小,可以改成重复交叉验证,比如 repeats = 3,相当于把5折CV重复3次取平均,结果会更稳。
4.2 模型评估指标与混淆矩阵
分类任务里,准确率只是一个起点。样本不平衡时,准确率会骗人。我日常必看混淆矩阵和几个派生指标。caret 里直接:
pred_class <- predict(rf_fit, test_data) confusionMatrix(pred_class, test_data$Species)这个函数会同时给出每个类别的敏感度也就是召回率,以及特异度。如果做二分类概率型评估,用 pROC 包画ROC曲线、算AUC:
library(pROC) roc_obj <- roc(test_data$Species == "versicolor", as.numeric(predict(rf_fit, test_data, type = "prob")$versicolor)) auc(roc_obj)回归任务则看RMSE、MAE、R²,caret 的 train() 默认会帮你算。真实项目里,AUC和RMSE比准确率更能反映模型好坏,这句话我反复跟团队里的人强调。
4.3 基于caret的统一调参
caret 的高阶用法是用 train() 统一调参。比如 SVM 径向基核,想试不同的 cost 和 gamma 组合,可以这样:
svm_grid <- expand.grid(C = c(0.1, 1, 10), sigma = c(0.01, 0.1, 1)) set.seed(42) svm_tune <- train(Species ~ Sepal.Length + Sepal.Width, data = train_data, method = "svmRadial", trControl = ctrl, tuneGrid = svm_grid) print(svm_tune$bestTune)train() 会自动跑完所有参数组合并选出最优的。但注意,参数组合是指数增长的,别一上来就搞一个很大的网格。我的习惯是先粗调一轮,锁定一个大致区间,再在最优值附近细调。另外 train() 在数据量大的时候非常慢,可以先用 dplyr::sample_n() 抽一个子集跑,确认流程没问题再全量跑。
5. 常见问题与排查技巧
5.1 包安装与版本冲突
R语言装包遇到问题是家常便饭。Windows上最常见的错误是 dependencies are not available 或者编译失败,先装 Rtools,再挨个装依赖包。还有一类冲突是函数名打架,最典型的是 dplyr::filter 和 stats::filter 都叫 filter,一旦两个包都挂载,很容易跑出匪夷所思的结果。解决办法是使用全限定名,或者在脚本开头用 conflicted 包管理:
library(conflicted) conflict_prefer("filter", "dplyr")另一个经验是尽量少挂载包,用到哪个包就用 pkg::func() 这种方式调用,既能避免冲突,回看代码时也清楚每个函数来自哪里。
5.2 因子变量与哑变量陷阱
R会自动把字符串变成因子,这个特性画图时方便,在 glm、svm、knn 这类要求数值输入的模型里就是坑。刚开始学的时候,我直接用字符串ID列训练模型,R把它当成因子,跑了很久还在报警告。处理办法是读取数据时设置 col_types,或者显式用 as.numeric()、model.matrix() 转换。生成哑变量时还要记得删掉第一列以避免完全共线性。决策树和随机森林能直接处理因子,但 SVM 和 KNN 这类基于距离的算法不行,一定要提前处理。
5.3 过拟合与不平衡数据的处理
过拟合的典型表现是训练集准确率接近100%,测试集掉得一塌糊涂。解决思路无非三条:简化模型、增加数据、用交叉验证发现不稳定。R里正则化最简单的是 glmnet 包,用lasso或者岭回归:
library(glmnet) x <- as.matrix(mtcars[, c("wt", "hp", "qsec", "cyl")]) y <- mtcars$mpg cv_fit <- cv.glmnet(x, y, alpha = 1) # alpha=1是lasso plot(cv_fit)不平衡数据是另一个常见问题,比如二分类中正样本只占5%。常规做法是上采样少数类或下采样多数类,也可以用 DMwR 包的 SMOTE 生成合成样本,或者在模型里调 class.weights。我实际用下来,SMOTE 不是万能的,样本太少时合成样本可能引入噪声,一定要结合交叉验证看真实效果。我的优先级是:先试调整分类阈值,提高少数类召回,再试重采样,最后才考虑换更复杂的模型。下面这个速查表整理了我踩过的典型问题:
| 症状 | 可能原因 | 排查方法 |
|---|---|---|
| 安装包时报编译错误 | 缺少Rtools或编译器 | 装Rtools,检查环境变量 |
| 模型输出全是NaN | 特征有大量缺失值或未标准化 | 用summary()检查,配合preProcess处理 |
| 随机森林训练异常慢 | 因子水平过多或数据量过大 | 简化因子,降采样,换ranger加速 |
| 交叉验证结果波动大 | 数据划分随机性大,样本量小 | 增大折数,加set.seed,用重复交叉验证 |
| AUC很高但准确率低 | 类别不平衡 | 以AUC、F1等指标为准,别只看准确率 |
最后说点我自己的体会。用R语言跑机器学习,最大的价值不是性能,而是它把统计检验、可视化和建模串在了一条线上。线性回归跑完可以顺手做残差诊断,随机森林跑完直接看变量重要性,聚类做完用 fviz_cluster 把结果绘制得明明白白,这些在Python里往往要额外拼好几个库才能达到同样效果。当然,如果将来要把模型上线成微服务,那是另一套工程问题。但如果你想先在一个干净、统计味很浓的环境里把主流ML算法老老实实跑明白,R是一个不错的起点。跑完这一整套流程之后,你自然会理解:算法本身只是工具,真正值钱的是你对数据的理解和对模型结果做出的判断。
本文还有配套的精品资源,点击获取