基于SVM的中文邮件分类

这篇博客介绍了如何利用scikit-learn的SVM(支持向量机)对中文邮件进行分类。首先,文本分类被分为二分类、多分类和多标签分类,接着详细阐述了从数据导入、文本预处理、特征提取到模型训练的步骤。在数据预处理阶段,使用jieba进行分词并去除停用词,然后通过TfidfVectorizer提取特征。最后,利用SGDClassifier训练SVM分类器,并计算了分类准确率。整个过程在jupyter环境下进行,代码和数据可在提供的链接下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在学习自然语言处理相关的知识,这里记录一下使用scikit-learn库中的SVM(支持向量机)分类算法实现中文邮件的分类。

1.文本分类简介

文本分类是指在一定的规则下,根据内容自动确定文本类别这一过程。文本分类在实际场景中有诸多方面的应用,比如常见的有垃圾邮件分类,情感分析,新闻分类等。

文本分类主要可以分为二分类,多分类,多标签分类三大类。

1.二分类:顾名思义是将文本归为两种类别,比如将邮件划分问题,垃圾邮件或者正常邮件。一段影评,判断是好评还是差评的问题。

2.多分类:是将文本划分为多个类别,比如将新闻归为政治类,娱乐类,生活类等等。

3.多标签分类:是给文本贴上多个不同的标签,比如一部小说可以同时被划分为多个主题,可能既是修仙小说,又是玄幻小说。

文本分类主要有两种方法:传统机器学习文本分类算法、深度学习文本分类算法。

1.传统机器学习方法:特征提取 + 分类器。就是将文本转换成固定维度的向量,然后送到分类器中进行分类。

2.深度学习方法:可以自动提取特征,实现端到端的训练,有较强的特征表征能力,这也是深度学习进行文本分类的效果往往要好于传统的方法。

2.中文邮件分类

这里就不具体介绍SVM算法的基本思想了,想要了解SVM的算法原理可以自行百度搜索或者查看相关书籍,这里只需知道怎么使用scikit-learn库提供的SVM模型就可以了。

2.1 基本步骤

中文邮件分类

1.导入数据,划分训练集和测试集。
2.文本预处理。
3.将文本数据转化为数字特征数据。
4.构建分类器。
5.训练分类器。
6.测试分类器。

2.2 准备数据集

本次用到的数据包含 3 个文件, ham_data.txt 文件里面包含 5000 条正常邮件样本,spam_data.txt 文件里面包含 5001 个垃圾邮件样本,stopwords 是停用词表。

在这里插入图片描述先来看一下中文邮件的具体内容,这里打开垃圾邮件。

在这里插入图片描述

1.读取数据样本
path1 = 'ham_data.txt'  # 正常邮件存放地址
path2 = 'spam_data.txt'  # 垃圾邮件地址
#下面打开正常样本
h = open(path1, encoding='utf-8')
#另外因为准备的数据是每一行一封邮件,这里我们要用 readlines() 来以行来读取文本的内容。
h_data = h.readlines()
h_data[0:3]  # 显示前3封正常邮件

#同样方式处理垃圾样本
s = open(path2, encoding='utf-8')
s_data = s.readlines()
s_data[0:3]  # 显示前3个封垃圾邮件

在这里插入图片描述
读取样本之后,h_data 是由 5000 条邮件字符串组成的正常邮件样本集, s_data 是由 5001 条邮件字符串组成的垃圾邮件样本集。下面我们需要将两个样本组合起来,并贴上标签,将正常邮件的标签设置为 1,垃圾邮件的标签设置为 0。

2. 为样本集打上标签

使用numpy库生成一个 len(h_data) 长的的一维全 1 列表。

import numpy as np

h_labels = np.ones(len(h_data)).tolist()  # 生成一个len(h_data)长的的一维全1列表
h_labels[0:10]  # 显示前10个数据

再生成一个 len(h_data) 长的的一维全 0 列表。

s_labels = np.zeros(len(s_data)).tolist()
s_labels[0:10]  # 我们显示前10个数据

在这里插入图片描述
为了得到一个由所有邮件样本组合起来的样本集 datas 以及一个标签集 labels,我们需要拼接样本集和标签集。

datas = h_data + s_data  # 将正常样本和垃圾样本整合到datas当中
labels = h_labels + s_labels

由于没有提前准备测试集,所以这里需要在 10001 个样本当中,随机划出 25% 个样本和标签来作为我们的测试集,剩下的 75% 作为训练集来进行训练我们的分类器。这里可以使用 scikit-learn 工具里面的 train_test_split 类。

sklearn.model_selection.train_test_split(datas, labels, test_size=0.25, random_state=5 )

datas : 样本集
labels: 标签集
train_test_split:划分到测试集的比例
random_state:随机种子,取同一个的随机种子那么每次划分出的测试集是一样的。

from sklearn.model_selection import train_test_split

train_d, test_d, train_y, test_y = train_test_split(
    datas, labels, test_size=0.25, random_state=5)
#观察一下随机抽取之后的前 20 个标签
train_y[0:20]

在这里插入图片描述
调用这个函数之后,就可以得到: train_d:样本集、test_d:测试集、train_y:样本标签、test_y:测试标签。

2.3 文本预处理

分词
# 现在对文本进行分词
import jieba

def tokenize_words(corpus):
    tokenized_words = jieba.cut(corpus)
    tokenized_words = [token.strip() for token in tokenized_words]
    return tokenized_words
去除停用词

因为有一些词是没有实际意义的,比如:【的】【了】等,因此需要将其剔除。
首先加载停用词表。这里也可以自行在网上下载,编码格式为 utf-8,每行一个停用词。

def remove_stopwords(corpus):  # 函数输入为样本集
    sw = open('stop_word.txt', encoding='utf-8')  # stopwords 停词表
    sw_list = [l.strip() for l in sw]  # 去掉文本中的回车符,然后存放到 sw_list 当中
    # 调用前面定义好的分词函数返回到 tokenized_data 当中
    tokenized_data = tokenize_words(corpus)
    # 过滤停用词,对每个在 tokenized_data 中的词 data 进行判断
    # 如果 data 不在 sw_list 则添加到 filtered_data 当中
    filtered_data = [data for data in tokenized_data if data not in sw_list]
    # 用''将 filtered_data 串起来赋值给 filtered_datas
    filtered_datas = ' '.join(filtered_data)
    return filtered_datas  # 返回去停用词之后的 datas
# 接下来,完成分词与去停用词
from tqdm.notebook import tqdm

def preprocessing_datas(datas):
    preprocessed_datas = []
    # 对 datas 当中的每一个 data 进行去停用词操作
    # 并添加到上面刚刚建立的 preprocessed_datas 当中
    for data in tqdm(datas):
        data = remove_stopwords(data)
        preprocessed_datas.append(data)
    return preprocessed_datas  # 返回去停用词之后的新的样本集

通过分词与去停用词这两步,我们得到了分词过后并且去除停用词了的样本集 pred_train_d 和 测试集 pred_test_d。

#对训练集进行预处理
pred_train_d = preprocessing_datas(train_d)
pred_train_d[0]

#对测试集进行预处理
pred_test_d = preprocessing_datas(test_d)
pred_test_d[0]

在这里插入图片描述

2.4 特征提取

这里使用的是IF-IDF算法来进行文本特征提取的。同样,此处不会细讲该算法的原理细节,想要深入了解该算法原理可以自行百度搜索或者查看相关书籍,通过 scikit-learn 来实现 TF-IDF 模型。

sklearn.feature_extraction.text.TfidfVectorizer(min_df=1,norm=‘l2’,smooth_idf=True,use_idf=True,ngram_range=(1,1))

min_df: 忽略掉词频严格低于定阈值的词。
norm :标准化词条向量所用的规范。
smooth_idf:添加一个平滑 IDF 权重,即 IDF 的分母是否使用平滑,防止 0 权重的出现。
use_idf: 启用 IDF 逆文档频率重新加权。
ngram_range:同词袋模型

首先加载 TfidfVectorizer 类,并定义 TF-IDF 模型训练器 vectorizer,对预处理过后的样本进行特征提取。

#首先加载 TfidfVectorizer 类,并定义 TF-IDF 模型训练器 vectorizer
from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = TfidfVectorizer(
    min_df=1, norm='l2', smooth_idf=True, use_idf=True, ngram_range=(1, 1))

#对预处理过后的 pred_train_d 进行特征提取
tfidf_train_features = vectorizer.fit_transform(pred_train_d)
tfidf_train_features

tfidf_test_features = vectorizer.transform(pred_test_d)
tfidf_test_features

通过这一步,我们得到了 7500 个 28335 维数的向量作为我们的训练特征集, 2501 个 28335 维数的向量作为我们的测试特征集。

注意:用训练集训练好特征后的 vectorizer 来提取测试集的特征: 注意这里不能用 vectorizer.fit_transform() 要用 vectorizer.transform()否则,将会对测试集单独训练 TF-IDF 模型,而不是在训练集的词数量基础上做训练。这样词总量跟训练集不一样多,排序也不一样,将会导致维数不同,最终无法完成测试。

在这里插入图片描述

2.5 分类

在获得 TF-IDF 特征之后,我们可以调用 SGDClassifier() 类来训练 SVM 分类器。

sklearn.linear_model.SGDClassifier(loss=‘hinge’)

SGDClassifier 是一个多个分类器的组合,当参数 loss=‘hinge’ 时是一个支持向量机分类器。

加载 SVM 分类器,并调整 loss = ‘hinge’,然后我们将之前准备好的样本集和样本标签送进 SVM 分类器进行训练。接下来我们用测试集来测试一下分类器的效果。

#加载 SVM 分类器,并调整 loss = 'hinge'
from sklearn.linear_model import SGDClassifier

svm = SGDClassifier(loss='hinge')

#然后我们将之前准备好的样本集和样本标签送进 SVM 分类器进行训练。
svm.fit(tfidf_train_features, train_y)

#接下来我们用测试集来测试一下分类器的效果
predictions = svm.predict(tfidf_test_features)
predictions

在这里插入图片描述

计算分类准确率
from sklearn import metrics

accuracy_score = np.round(metrics.accuracy_score(test_y, predictions), 2)
accuracy_score

在这里插入图片描述
至此,一个中文邮件分类的任务就告一段落了,这里总结一下:本文使用的机器学习库为scikit-learn,代码编写的环境为jupyter。中间也用到了一些python的第三方库:如jieba等。

demo完整代码与样本数据下载地址:demo完整代码与样本数据下载地址

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

picacho_pkq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值