logo

第 9 章 机器学习

作者
Modified on
Reading time
11 分钟阅读:..评论:..

机器学习是一门让计算机具备从数据中自主学习的能力,无需进行明确编程的科学。它是人工智能的核心,也是 R 语言数据分析不可或缺的一部分。本章将全面介绍如何使用 R 语言实现机器学习,包括监督学习、无监督学习、模型评估与选择,以及一个实战案例。

9.1 监督学习

监督学习是使用已标注的训练数据来训练模型,通过训练数据来推断出一个函数,该函数可以对新的未知数据进行预测。监督学习主要应用于分类和回归任务。

9.1.1 线性回归

线性回归是监督学习中回归任务的基础算法。它通过拟合一条直线来刻画因变量 y 和自变量 x 之间的关系。在 R 中,可以使用 lm()函数实现线性回归:

# 拟合线性模型 fit <- lm(y ~ x, data = train_data) # 对测试集进行预测 pred <- predict(fit, test_data)

除了一元线性回归,多元线性回归也非常常见,可以处理多个自变量的情况:

# 拟合多元线性模型 fit <- lm(y ~ x1 + x2 + x3, data = train_data)

下图展示了一元线性回归的效果:

### 9.1.2 逻辑回归 逻辑回归是监督学习中经典的二分类算法。与线性回归类似,逻辑回归也是试图学习一个线性函数,但其输出经过 logistic 函数转换,得到 0 到 1 之间的概率值。在 R 中可以使用 glm()函数实现:

# 拟合逻辑回归模型 fit <- glm(y ~ x, data = train_data, family = binomial) # 对测试集预测 prob <- predict(fit, test_data, type="response") pred <- ifelse(prob > 0.5, 1, 0)

逻辑回归的决策边界如下图所示:

### 9.1.3 支持向量机 支持向量机(SVM)是一种基于最大间隔思想的线性分类器。它的基本思想是在特征空间中寻找一个最优的分类超平面,使得两类样本到超平面的最小间隔最大化。 在 R 中,可以使用 e1071 包来实现 SVM:

library(e1071) # 拟合SVM模型 fit <- svm(y ~ ., data = train_data) # 对测试集预测 pred <- predict(fit, test_data)

SVM 的分类边界如下图所示:

此外,对于线性不可分的数据,可以使用核技巧将数据映射到高维空间,再进行分类。常见的核函数有:

  • 线性核
  • 多项式核
  • RBF 核(高斯核)
  • Sigmoid 核

以 RBF 核为例:

# 使用RBF核的SVM fit <- svm(y ~ ., data = train_data, kernel = "radial")

9.2 无监督学习

无监督学习是仅根据数据的特征,自主学习数据内在的结构和关系,而不需要任何标签信息。常见的无监督学习任务包括聚类、降维等。

9.2.1 聚类分析

聚类分析将相似的样本自动归为一组,形成不同的簇。以下介绍两种经典的聚类算法。

K-means 聚类

K-means 聚类事先指定簇的个数 k,然后将 n 个样本分到 k 个簇中,使得每个样本到其所属簇中心的距离最小。 在 R 中可以直接使用 kmeans()函数:

# 进行K-means聚类 cluster <- kmeans(x, centers = 3) # 聚成3类 # 查看聚类结果 cluster$cluster

下图展示了 K-means 聚类的效果:

#### 层次聚类 层次聚类通过计算样本间的距离,采用自底向上或自顶向下的策略,形成树状的聚类结构。 在 R 中可以使用 hclust()函数进行层次聚类:

# 计算距离矩阵 dist_mat <- dist(x) # 进行层次聚类 hc <- hclust(dist_mat) # 查看聚类结果 clusters <- cutree(hc, k = 3) # 切成3类

层次聚类的树状结构如下:

### 9.2.2 主成分分析 主成分分析(PCA)是一种常用的数据降维方法。它通过线性变换将原始高维空间中的数据投影到一个低维子空间,使得样本点在子空间上的投影点尽可能分开。在 R 中可以使用 prcomp()函数实现 PCA:

# 进行PCA降维 pca <- prcomp(x, scale. = TRUE) # 查看降维后的数据 pca_data <- pca$x

下图展示了使用 PCA 将三维数据降到二维平面的效果:

### 9.2.3 独立成分分析 独立成分分析(ICA)是另一种数据降维方法。与 PCA 不同,ICA 希望将数据分解为若干个统计独立的成分。ICA 常用于信号分离、特征提取等。 在 R 中可以使用 fastICA 包进行 ICA:

library(fastICA) # 进行ICA分解 ica <- fastICA(x) # 查看分解后的独立成分 ica_data <- ica$S

ICA 分解的过程如下图所示:

## 9.3 模型评估与选择 构建完机器学习模型后,我们需要评估其性能,并在多个模型中选择最优的一个。以下介绍几种常用的模型评估与选择方法。

9.3.1 评估指标

不同类型的机器学习任务,需要使用不同的评估指标:

  • 回归任务:常用均方误差(MSE)、平均绝对误差(MAE)、决定系数(R-squared)等。
  • 分类任务:常用准确率(Accuracy)、精准率(Precision)、召回率(Recall)、F1 分数等。

例如,以下代码展示了如何计算均方误差:

# 计算均方误差 mse <- mean((pred - actual)^2)

混淆矩阵是分类任务常用的工具。例如:

据此可以计算出各项指标:

# 准确率 accuracy <- (TP + TN) / (TP + FP + TN + FN) # 精准率 precision <- TP / (TP + FP) # 召回率 recall <- TP / (TP + FN) # F1分数 f1 <- 2 * precision * recall / (precision + recall)

9.3.2 交叉验证

交叉验证是一种评估模型性能的方法。它将数据集切分成 k 份,每次用其中 k-1 份训练,剩下 1 份测试,最后取 k 次结果的平均。这样可以减少过拟合,得到更可靠的性能估计。 在 R 中可以使用 caret 包进行交叉验证:

library(caret) # 定义训练控制参数 ctrl <- trainControl(method = "cv", number = 5) # 5折交叉验证 # 进行交叉验证 cv_fit <- train(y ~ ., data = train_data, method = "glm", trControl = ctrl) # 查看交叉验证结果 cv_fit$resample

5 折交叉验证的过程如下:

### 9.3.3 模型选择与调优 常见的模型选择方法有:

  • 网格搜索:对模型参数预先指定若干组候选值,对所有可能的参数组合进行交叉验证,选出性能最优的一组。
  • 随机搜索:随机采样参数组合进行交叉验证,相比网格搜索,随机搜索可以在更短时间内找到最优参数。

模型调优的目标是进一步提升性能,常用的调优策略有:

  • 数据预处理:标准化、归一化、缺失值填充等。
  • 特征工程:特征选择、特征提取、特征组合等。
  • 集成学习:Bagging、Boosting、Stacking 等。
  • 正则化:L1 正则、L2 正则、Early Stopping 等。

以下代码展示了如何使用 caret 包进行参数调优:

library(caret) # 设置参数候选值 grid <- expand.grid(C = c(0.1, 1, 10)) # 进行网格搜索 svm_tune <- train(y ~ ., data = train_data, method = "svmRadial", trControl = ctrl, tuneGrid = grid) # 查看最优参数组合 svm_tune$bestTune

9.4 实践案例:分类与回归

下面我们通过一个完整的案例,演示如何使用 R 语言解决分类与回归问题。该案例使用著名的 iris 数据集,目标是根据鸢尾花的萼片、花瓣测量数据,预测它属于三个品种中的哪一个。同时,我们还将根据这些测量值,拟合一个回归模型,预测花瓣的长度。

9.4.1 数据准备

首先加载 iris 数据集,并进行探索性分析:

# 加载数据 data(iris) # 查看数据结构 str(iris) # 可视化分析 library(ggplot2) ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) + geom_point()

可以看出,不同品种在萼片长宽上有一定区分度:

接下来,我们将数据集按 8:2 划分为训练集和测试集:

# 划分训练集测试集 set.seed(123) # 设置随机种子,确保结果可重复 train_idx <- sample(nrow(接上文,继续输出第9章的剩余内容如下: ```r # 划分训练集测试集 set.seed(123) # 设置随机种子,确保结果可重复 train_idx <- sample(nrow(iris), nrow(iris) * 0.8) # 随机选择80%作为训练集 train_data <- iris[train_idx, ] test_data <- iris[-train_idx, ]

9.4.2 模型训练

我们分别拟合分类模型和回归模型。对于分类,使用逻辑回归、决策树、支持向量机等方法,对比它们的性能:

library(caret) # 定义训练控制参数 ctrl <- trainControl(method = "cv", number = 5) # 逻辑回归 lr_fit <- train(Species ~ ., data = train_data, method = "glm", trControl = ctrl) # 决策树 dt_fit <- train(Species ~ ., data = train_data, method = "rpart", trControl = ctrl) # 支持向量机 svm_fit <- train(Species ~ ., data = train_data, method = "svmRadial", trControl = ctrl)

对于回归,我们拟合一个线性回归模型,预测花瓣长度:

# 线性回归 lm_fit <- lm(Petal.Length ~ Sepal.Length + Sepal.Width + Petal.Width + Species, data = train_data)

9.4.3 模型评估

接下来在测试集上评估模型性能。对于分类模型,我们重点关注准确率、混淆矩阵等指标:

# 对测试集预测 lr_pred <- predict(lr_fit, test_data) dt_pred <- predict(dt_fit, test_data) svm_pred <- predict(svm_fit, test_data) # 查看准确率 confusionMatrix(lr_pred, test_data$Species)$overall[1] confusionMatrix(dt_pred, test_data$Species)$overall[1] confusionMatrix(svm_pred, test_data$Species)$overall[1]

可以看出,逻辑回归、决策树、支持向量机在该数据集上的表现都非常出色,准确率都在 90%以上。 对于回归模型,我们画出真实值与预测值的散点图,并计算决定系数:

# 对测试集预测 lm_pred <- predict(lm_fit, test_data) # 画散点图 plot(test_data$Petal.Length, lm_pred) abline(0, 1, col = "red", lwd = 2) # 添加对角线 # 计算决定系数 summary(lm_fit)$r.squared

散点图基本围绕对角线分布,表明预测值与真实值吻合较好。决定系数在 0.9 以上,说明花瓣长度可以被其他变量解释的很好。

9.4.4 应用与部署

最后,我们可以使用训练好的模型对新数据进行预测。例如,对于一朵新的鸢尾花,我们可以测量其萼片花瓣的长宽,然后预测它最可能属于哪个品种:

# 新数据 new_data <- data.frame(Sepal.Length = 5.1, Sepal.Width = 3.5, Petal.Length = 1.4, Petal.Width = 0.2) # 预测品种 predict(lr_fit, new_data)

同理,也可以预测该花的花瓣长度:

# 预测花瓣长度 predict(lm_fit, new_data)

在实际应用中,我们可以将训练好的模型保存下来,部署到生产环境中。当新的数据到来时,即可实时进行预测,并根据预测结果进行相应的业务决策。 以上就是机器学习的完整案例。通过本案例,相信你已经掌握了使用 R 语言进行机器学习的基本流程。当然,真实场景中的数据往往更加复杂,需要我们进行更多的数据清洗、特征工程、模型优化等工作。但万变不离其宗,只要掌握了这些基本步骤和方法,就可以举一反三,解决各种机器学习问题。

最后,我想以我的亲身经历与大家分享。我曾经参与过一个客户流失预警的项目,目标是根据客户的各项属性与行为数据,预测其未来是否会流失。

一开始,我们团队尝试了各种算法,却始终无法让模型性能满意。后来,我们意识到数据中存在严重的类别不平衡问题,即流失客户占比很小。于是,我们对少数类进行过采样,同时引入代价敏感学习,重点关注被误判的流失客户。经过不断的尝试与优化,最终模型的性能大幅提升,为公司挽回了大量客户。 这个案例告诉我们,机器学习并非一蹴而就,往往需要经过反复的探索与迭代。作为一名数据科学家,我们要学会从数据的角度思考问题,用创新的方法去解决问题。同时,还要与业务人员密切沟通,确保我们的模型能够真正满足业务需求,创造实际价值。 我相信,通过不断学习和实践,你一定能够成长为一名优秀的数据科学家。让我们一起,用机器学习的力量,去探索数据的奥秘,创造更智能的世界!