在当今数字化时代,垃圾信息成为了一个普遍存在的问题,它不仅给人们带来困扰,还可能造成经济损失。发送垃圾信息会消耗存储空间、计算能力和速度,并且需要花费时间去清理。为了解决这个问题,已经开发出了许多过滤垃圾信息的方法,其中一些取得了不同程度的成功。本文将探讨朴素贝叶斯分类器和支持向量机这两种机器学习模型,并实现它们来过滤垃圾文本信息,最后比较结果。
朴素贝叶斯是一种用于分类问题的监督式机器学习算法,它基于贝叶斯定理。之所以被称为“朴素”,是因为它对预测变量之间的条件独立性做出了朴素的假设。这种算法假设一个类别中的所有特征都是相互无关的。为了解释朴素贝叶斯算法,首先需要了解贝叶斯定理。
贝叶斯定理:假设有两个事件A和B,可以使用以下公式来计算后验概率P(B|A),其中P(B)是先验概率,P(A)是事件A的概率,P(A|B)是在B发生的条件下A发生的概率。
当只有一个特征时,计算后验概率相对简单。但是,当有两个或更多特征时,计算后验概率就变得复杂了,有时甚至会出现零概率问题。因此,采用朴素的假设来计算后验概率。
假设有预测变量[X1, X2]和目标Y,计算后验概率的公式如下:
P(X1, X2|Y=1)
这是使用朴素贝叶斯分类器计算后验概率的公式。
支持向量机是一种监督式机器学习算法,可以用于回归和分类。在SVM中,数据点被绘制在n维空间中,其中n是特征的数量。然后通过选择一个合适的超平面来分类两个类别。在n维空间中,超平面的维度是(n-1)。假设类别是线性可分的。
方程的符号有助于分类类别,而方程的大小有助于理解观察值离超平面的距离。当大小较高时,对类别分配的确定性更高。数据点到超平面的最小距离称为边际。需要有最大的边际,以便它具有高的大小。因此,这个超平面被称为最大边际分类器。
位于边际上或违反边际的观察值被称为支持向量。支持向量支持超平面。在支持向量分类器中,有一个最大边际分类器,它有一个软边际(这个边际可以被一些观察值违反)。
本文使用的数据集是UCI机器学习库中的SMS Spam Collection数据集。这是一个公共的SMS标记消息集合,收集于2012年,用于移动电话垃圾信息研究。该数据集包含5572条消息,其中4825条是正常消息,747条是垃圾信息。在这个数据集中,每一行都以消息的标签开始,后面跟着文本。
数据集链接:
数据集包含两列:数据的标签类别(正常或垃圾)和文本消息。移除了其他不需要的列。
# 导入包
import pandas as pd
import numpy as np
# 读取数据集
sms_data = pd.read_csv("spam", encoding='latin-1', sep='\t')
print(sms_data.head())
# 移除不需要的列
sms_data.drop(labels=['Unnamed: 2','Unnamed: 3','Unnamed: 4','length'], axis=1, inplace=True)
sms_data.head()
接下来,将创建一个语料库并附加消息,在附加消息到语料库之前,需要执行某些预处理步骤。导入‘re’包并移除标点符号、特殊字符,并将所有字符转换为小写。然后,需要将消息分割成单词以移除停用词,并执行词干提取。
# 导入包
import re
import nltk
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
# 创建一个精炼消息的语料库
stemming = PorterStemmer()
corpus = []
for i in range(0, len(sms_data)):
s1 = re.sub('[^a-zA-Z]', repl=' ', string=sms_data['v2'][i])
s1.lower()
s1 = s1.split()
s1 = [stemming.stem(word) for word in s1 if word not in set(stopwords.words('english'))]
s1 = ' '.join(s1)
corpus.append(s1)
corpus[50]
将导入Scikit-learn库中的Count-Vectorizer来标记化和向量化文本。
# 导入包
from sklearn.feature_extraction.text import CountVectorizer
countvectorizer = CountVectorizer()
使用这个Count-Vectorizer,将标记化一系列文本文档并构建词汇表,这个词汇表也用于编码新文档。要使用这个Count-Vectorizer,首先,将创建一个Count-Vectorizer类的实例。然后,fit()函数用于从文档中学习词汇,transform()函数用于编码为向量。
x = countvectorizer.fit_transform(corpus).toarray()
print(x)
y = sms_data['v1'].values
print(y)
这个向量表示整个词汇表的长度和每个词在文档中出现的次数。现在有一个从文本字符串转换来的数值向量。
# 分割训练和测试数据
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, stratify=y, random_state=100)
# 1. 多项式朴素贝叶斯
from sklearn.naive_bayes import MultinomialNB
multinomialnb = MultinomialNB()
multinomialnb.fit(x_train, y_train)
# 在测试数据上预测
y_pred = multinomialnb.predict(x_test)
# 2. SVM
from sklearn.svm import LinearSVC
linearsvc = LinearSVC()
linearsvc.fit(x_train, y_train)
# 在测试数据上预测
y_pred = linearsvc.predict(x_test)
# 导入包
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.metrics import accuracy_score
print(classification_report(y_test, y_pred))
accuracy_score(y_test, y_pred)