使用R语言进行支持向量机(SVM)垃圾邮件分类教程

使用R语言进行支持向量机(SVM)垃圾邮件分类教程

2025-06-30

Table of Contents

1. 简介

什么是支持向量机 (SVM)?

支持向量机(Support Vector Machine, SVM)是一种强大且灵活的监督学习算法,可用于分类和回归分析。其核心思想是在特征空间中找到一个能将不同类别样本最大程度分开的决策边界(对于线性可分数据,这个边界是一个超平面)。SVM的目标是找到距离最近的训练数据点(即”支持向量”)最远的那个超平面,这个距离被称为”间隔”(margin)。最大化间隔有助于提高模型的泛化能力。

对于非线性可分的数据,SVM使用一种称为”核技巧”(kernel trick)的方法,将数据映射到更高维度的空间,使其在这个高维空间中变得线性可分。

在本教程中,我们将模拟一个垃圾邮件(Spam)和正常邮件(Ham)的数据集,并使用SVM来构建一个分类器。

2. 准备工作

加载必要的R包

我们将使用 e1071 包来实现SVM,dplyr 用于数据处理,ggplot2 用于数据可视化,caTools 用于数据切分。

# 如果尚未安装,请取消注释并运行以下代码
# install.packages("e1071")
# install.packages("dplyr")
# install.packages("ggplot2")
# install.packages("caTools")
showtext::showtext_auto()
library(e1071)
library(dplyr)
library(ggplot2)
library(caTools)

3. 生成模拟数据

为了演示,我们自己创建一个数据集。真实世界的垃圾邮件分类会使用成千上万个特征(如词频、n-grams等)。在这里,我们简化为几个典型的特征:

  • word_freq_free: “免费”一词的出现频率。
  • char_freq_dollar: $ 符号的出现频率。
  • capital_run_length: 连续大写字母的平均长度。
  • is_spam: 目标变量,标记邮件是否为垃圾邮件 (spam 或 ham)。

我们假设垃圾邮件通常含有更多的”免费”、“$”符号和更长的大写字母序列。

set.seed(42# 为了结果的可重复性

# 生成1000封正常邮件 (ham)
ham_data <- data.frame(
  word_freq_free = rnorm(1000mean = 0.5sd = 0.3),
  char_freq_dollar = rnorm(1000mean = 0.1sd = 0.05),
  capital_run_length = rnorm(1000mean = 2sd = 1),
  is_spam = "ham"
)

# 生成800封垃圾邮件 (spam)
spam_data <- data.frame(
  word_freq_free = rnorm(800mean = 2.0sd = 0.8),
  char_freq_dollar = rnorm(800mean = 0.8sd = 0.4),
  capital_run_length = rnorm(800mean = 10sd = 5),
  is_spam = "spam"
)

# 合并数据并打乱顺序
full_data <- rbind(ham_data, spam_data)
full_data <- full_data[sample(nrow(full_data)), ]

# 将目标变量转换为因子类型
full_data$is_spam <- as.factor(full_data$is_spam)

# 查看数据结构
str(full_data)

## 'data.frame':    1800 obs. of  4 variables:
##  $ word_freq_free    : num  2.11 0.154 3.222 0.622 2.624 ...
##  $ char_freq_dollar  : num  1.0614 0.0668 1.2138 0.6152 0.4506 ...
##  $ capital_run_length: num  13.064 3.223 7.576 0.675 10.285 ...
##  $ is_spam           : Factor w/ 2 levels "ham","spam": 2 1 2 2 2 1 1 2 2 2 ...

summary(full_data)

##  word_freq_free    char_freq_dollar  capital_run_length is_spam    
##  Min.   :-0.5115   Min.   :-0.4556   Min.   :-6.654     ham :1000  
##  1st Qu.: 0.4411   1st Qu.: 0.0888   1st Qu.: 1.757     spam: 800  
##  Median : 0.7996   Median : 0.1501   Median : 2.937                
##  Mean   : 1.1577   Mean   : 0.4039   Mean   : 5.568                
##  3rd Qu.: 1.8530   3rd Qu.: 0.7276   3rd Qu.: 9.315                
##  Max.   : 4.5396   Max.   : 1.9956   Max.   :25.129

4. 探索性数据分析 (EDA)

在建模之前,我们先通过可视化来观察数据的大致分布,看看不同类别的数据是否在视觉上可分。

ggplot(full_data, aes(x = word_freq_free, y = char_freq_dollar, color = is_spam)) +
  geom_point(alpha = 0.6+
  labs(title = "邮件特征分布: '免费' vs '$' 符号",
       x = "免费一词的频率",
       y = "$符号的频率"+
  theme_minimal()

 从图中可以看出,两个类别的数据存在一定的重叠,但总体趋势上是可分的。这为我们使用SVM进行分类提供了基础。

5. 数据准备:划分训练集与测试集

我们将数据按7:3的比例划分为训练集和测试集。

sample_split <- sample.split(full_data$is_spam, SplitRatio = 0.7)
train_set <- subset(full_data, sample_split == TRUE)
test_set <- subset(full_data, sample_split == FALSE)

cat("训练集大小:"nrow(train_set), "\n")

## 训练集大小: 1260

cat("测试集大小:"nrow(test_set), "\n")

## 测试集大小: 540

6. 构建与评估SVM模型

6.1. 基础线性SVM模型

我们首先尝试使用一个简单的线性核SVM。cost参数是”惩罚”系数,它控制着对分类错误的惩罚程度。较高的cost会使模型更努力地正确分类所有训练样本,可能导致过拟合。

# 使用线性核训练模型
svm_linear <- svm(is_spam ~ ., data = train_set, kernel = "linear"cost = 1)

# 在测试集上进行预测
pred_linear <- predict(svm_linear, newdata = test_set)

# 创建混淆矩阵
confusion_matrix_linear <- table(Predicted = pred_linear, Actual = test_set$is_spam)
print("线性SVM混淆矩阵:")

## [1] "线性SVM混淆矩阵:"

print(confusion_matrix_linear)

##          Actual
## Predicted ham spam
##      ham  300    3
##      spam   0  237

# 计算准确率
accuracy_linear <- sum(diag(confusion_matrix_linear)) / sum(confusion_matrix_linear)
cat("线性SVM准确率:", accuracy_linear, "\n")

## 线性SVM准确率: 0.9944444

6.2. 使用非线性核 (径向基核 - RBF)

真实世界的数据往往不是线性可分的。我们尝试使用更灵活的径向基核(Radial Basis Function, RBF),这是SVM中最常用的核之一。

# 使用径向基核训练模型
svm_radial <- svm(is_spam ~ ., data = train_set, kernel = "radial")

# 预测
pred_radial <- predict(svm_radial, newdata = test_set)

# 混淆矩阵
confusion_matrix_radial <- table(Predicted = pred_radial, Actual = test_set$is_spam)
print("径向基核SVM混淆矩阵:")

## [1] "径向基核SVM混淆矩阵:"

print(confusion_matrix_radial)

##          Actual
## Predicted ham spam
##      ham  300    0
##      spam   0  240

# 准确率
accuracy_radial <- sum(diag(confusion_matrix_radial)) / sum(confusion_matrix_radial)
cat("径向基核SVM准确率:", accuracy_radial, "\n")

## 径向基核SVM准确率: 1

可以看到,对于这个数据集,径向基核的表现比线性核要好得多。

7. 模型调优 (Hyperparameter Tuning)

为了获得最佳性能,我们需要对模型的超参数进行调优。对于RBF核的SVM,最重要的两个超参数是: * cost: 惩罚系数。 * gamma: RBF核的参数,决定了单个训练样本的影响范围。

我们将使用 tune() 函数进行10折交叉验证来寻找最佳的 cost 和 gamma 组合。

# 进行调优
# 注意:这可能会花费一些时间
tuned_svm <- tune(svm, is_spam ~ ., data = train_set,
                  kernel = "radial",
                  ranges = list(
                    cost = c(0.1110100),
                    gamma = c(0.10.512)
                  ))

# 查看最佳模型和参数
summary(tuned_svm)

## 
## Parameter tuning of 'svm':
## 
## - sampling method: 10-fold cross validation 
## 
## - best parameters:
##  cost gamma
##   0.1     2
## 
## - best performance: 0.003174603 
## 
## - Detailed performance results:
##     cost gamma       error  dispersion
## 1    0.1   0.1 0.013492063 0.007529233
## 2    1.0   0.1 0.004761905 0.004098395
## 3   10.0   0.1 0.004761905 0.004098395
## 4  100.0   0.1 0.003968254 0.004182907
## 5    0.1   0.5 0.003968254 0.004182907
## 6    1.0   0.5 0.003968254 0.004182907
## 7   10.0   0.5 0.003968254 0.004182907
## 8  100.0   0.5 0.005555556 0.005356735
## 9    0.1   1.0 0.003968254 0.004182907
## 10   1.0   1.0 0.003968254 0.004182907
## 11  10.0   1.0 0.004761905 0.004098395
## 12 100.0   1.0 0.008730159 0.004505129
## 13   0.1   2.0 0.003174603 0.004098395
## 14   1.0   2.0 0.003968254 0.004182907
## 15  10.0   2.0 0.005555556 0.003833698
## 16 100.0   2.0 0.010317460 0.005356735

# 使用最佳参数训练最终模型
best_model <- tuned_svm$best.model

评估最终调优后的模型

# 预测
pred_tuned <- predict(best_model, newdata = test_set)

# 混淆矩阵
confusion_matrix_tuned <- table(Predicted = pred_tuned, Actual = test_set$is_spam)
print("调优后SVM混淆矩阵:")

## [1] "调优后SVM混淆矩阵:"

print(confusion_matrix_tuned)

##          Actual
## Predicted ham spam
##      ham  299    0
##      spam   1  240

# 准确率
accuracy_tuned <- sum(diag(confusion_matrix_tuned)) / sum(confusion_matrix_tuned)
cat("调优后SVM准确率:", accuracy_tuned, "\n")

## 调优后SVM准确率: 0.9981481

有问题咨询

www.rdaima.com www.rdaizuo.com

专业R语言辅导 | Python编程 | 数据分析 Data analysis | 统计分析 Statistics | 数据挖掘 Data mining | 机器学习 Machine learning | 留学生作业代做代写|6.864|9.520|6-867|CS229|CS231n|CS236|CS224n|STATS 202|STATS 203|STAT 110|STAT 104|CS109|BIOS221|10-701|10-605|10-607|10-601|10-603|10-604|STAT 705|STAT 707|COMS4771|COMS5771|COMS5733|COMS4733|STAT4203|STAT4204|STAT4205|STAT4206|STAT 133|STAT 134|DATA C88|CS 265|STAT 101A|STAT 100A|CS273A|CSE250A|COGS118A|CS-GY.6923|BUSF-GB.2397|CS 542|STAT 581|MLMI 201|MLMI 202|COMP0087|COMP0088|COMP01011|COMP3008|INFR11136|INFR11218|DATA1001|CSC311H1|CSC411|CSC413|CSC414|CSC412|STA302|STA2453H|STAT 302|DSCI511|DSCI512|DSCI513|DSCI514|STAT 540|STAT 541|CPSC 587|STAT 517|COMP 551|COMP 520|STAT 520|STAT 521|STAT 4500|STAT 5805|STAT 5806|STAT 4600|COMP5805|COMP90051|COMP90053|COMP90054|COMP90057|MATH90010|MATH90011|MATH90012|STAT30001|COMP1730|STAT3001|STAT3002|STAT3003|STAT3004|STAT3005|STAT3006|MATH3001|COMP5311|COMP5312|COMP5313|COMP5314|COMP5315|COMP5316|COMP5317|COMP5318|STAT5001|STAT5002|STAT5003|STAT5004|FIT5097|FIT5098|FIT5099|FIT5100|MTH5001|MTH5002|MTH5003

请咨询 www.daixie.it.com www.rcodedaixie.com

8. 结论

在本教程中,我们学习了如何使用R语言和e1071包来构建一个支持向量机(SVM)分类器,并将其应用于模拟的垃圾邮件分类任务。

我们完成了以下步骤: 1. 生成了一个包含典型垃圾邮件特征的模拟数据集。 2. 通过探索性数据分析(EDA)对数据进行了可视化。 3. 将数据划分为训练集和测试集。 4. 分别训练了线性和非线性(径向基核)的SVM模型,并比较了它们的性能。 5. 使用交叉验证对非线性模型的超参数(cost和gamma)进行了调优,找到了最佳模型。 6. 评估了最终模型的性能,它在测试集上达到了很高的准确率。

这个例子展示了SVM在分类问题上的强大能力,尤其是当结合了核技巧和超参数调优时。在真实世界的应用中,特征工程(选择和创建有意义的特征)和更广泛的超参数搜索将是进一步提升模型性能的关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值