美文网首页
用SVM算法构造垃圾邮件分类器

用SVM算法构造垃圾邮件分类器

作者: 此间不留白 | 来源:发表于2019-03-14 22:15 被阅读0次

前言

在之前的学习中,已经学习过了支持向量机的算法,在这部分内容中,需要使用2维数据实现带有高斯核函数的支持向量机算法,并利用支持向量机算法实现垃圾邮件的分类,具体实现如下。

使用线性核函数的svm算法

  • 数据集1的线性决策边界
    首先,加载一个2维数据集,该数据集可以被线性边界分割为正样本和负样本,具体实现代码和效果如下所示:
import matplotlib.pyplot as plt
import numpy as np
import scipy.io as scio
from sklearn import svm
plt.ion()
np.set_printoptions(formatter={'float': '{: 0.6f}'.format})

data = scio.loadmat('ex6data1.mat')
X = data['X']
y = data['y'].flatten()
m = y.size

绘图函数实现代码如下所示,根据y值的不同,得到两种不同的散点图。

def plot_data(X, y):
    plt.figure()

    pos = np.where(y == 1)[0]
    neg = np.where(y == 0)[0]

    plt.scatter(X[pos, 0], X[pos, 1], marker="+", c='b')
    plt.scatter(X[neg, 0], X[neg, 1], marker="o", c='y', s=15)

实现效果如下所示


通过使用sklearnpython包中的svm模块,利用svm算法实现线性分类,由之前的学习可知,变量C所起的作用于逻辑回归中的正则化参数\frac{1}{\lambda}相似,不同的C值对决策边界有不同的影响,具体如下所示:

def visualize_boundary(clf, X, x_min, x_max, y_min, y_max):
    h = 0.02
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    plt.contour(xx, yy, Z, levels=[0], colors='r')

c = 1
clf = svm.SVC(c, kernel='linear', tol=1e-3)
clf.fit(X, y)

plot_data(X, y)
visualize_boundary(clf, X, 0, 4.5, 1.5, 5)

C=1时,决策边界如下所示:

C=1

C=1000时,所绘制的决策边界如下所示:

C=1000

可以由以上图片看出,C的大小影响着线性决策边界,其所起的作

用于逻辑回归中正则化参数一样,C太大,可能会导致过拟合问题。

使用高斯核函数的SVM算法

对于非线性的分类任务,常用带有高斯核函数的SVM算法来实现,具体如下所示:

  • 高斯核函数
    根据高斯核函数的原理,具体实现代码如下所示
def gaussian_kernel(x1, x2, sigma):
    x1 = x1.flatten()
    x2 = x2.flatten()
    sim = 0
    sim = np.exp(np.sum((x1 - x2) ** 2) / (-2*sigma**2))
    return sim
  • 绘制非线性决策边界
    如下代码所示,加载数据集2,并绘制其散点图,可以很明显地看出是非线性的数据
data = scio.loadmat('ex6data2.mat')
X = data['X']
y = data['y'].flatten()
m = y.size
plot_data(X, y)


如下代码所示,使用带有高斯核函数的svm算法绘制非线性的决策边界,如下所示:

c = 1
sigma = 0.1


def gaussian_kernel(x_1, x_2):
    n1 = x_1.shape[0]
    n2 = x_2.shape[0]
    result = np.zeros((n1, n2))

    for i in range(n1):
        for j in range(n2):
            result[i, j] = gk.gaussian_kernel(x_1[i], x_2[j], sigma)

    return result


clf = svm.SVC(c, kernel='rbf', gamma=np.power(sigma, -2))
clf.fit(X, y)
plot_data(X, y)
visualize_boundary(clf, X, 0, 1, .4, 1.0)

实现效果如下所示:


用SVM算法实现邮件分类

许多邮件服务商能够对垃圾邮件的识别具有很高的精确度,通过SVM算法,可以实现自己的邮件过滤器,具体实现,如下所示。
利用SVM算法,通过训练能够区分给定的邮件(变量x),是垃圾邮件(y=1)还是正常邮件(y=0)。在这个过程中,需要将每份邮件转化为特征向量x \in R^n

邮件处理

一封邮件格式如下所示,需要对文本邮件做必要处理。


  • 小写转化
    需要将文本格式的邮件中的大写字母全部转化为小写,如下代码所示
email_contents = email_contents.lower()
  • 过滤html标签
    将文本格式中的HTML标签删除,用python实现如下所示:
email_contents = re.sub('<[^<>]+>', ' ', email_contents)
  • URL处理
    需要将所有URL标签转化为字符串httpaddr,如下代码所示:
email_contents = re.sub('(http|https)://[^\s]*', 'httpaddr', email_contents)
  • email地址处理
    所有的email地址将会被字符串emailaddr替换,如下所示:
 email_contents = re.sub('[^\s]+@[^\s]+', 'emailaddr', email_contents)
  • 数字处理
    所有的数字将会被替换为字符串number,如下所示:
email_contents = re.sub('[^\s]+@[^\s]+', 'emailaddr', email_contents)
  • $的处理
    所有的$符将会被替换为字符串dollar,如下所示
email_contents = re.sub('[$]+', 'dollar', email_contents)

经过以上步骤处理之后的邮件格式如下图所示


词汇表

经过以上处理,得到词汇列表,接下来要做的就是将筛选出来哪些词汇可以用来构建邮件分类器。
为了构建一个合适的邮件分类器,需要选择一些使用频率最高的词汇,(如果选择一些使用频率很小的词汇,可能会导致过拟合问题)。根据在垃圾邮件语料库中至少出现了100次以上的单词可以添加到词汇表中的要求,最终,词汇表中有1899个单词。在实践中,一个词汇表中通常有10000到50000个单词。
有了词汇表,可以将预处理的电子邮件中的每个单词映射到包含词汇表中单词的索引的单词索引列表。所谓单词索引列表就是每个单词所对应的数字索引所组成的列表,具体如下图所示:



邮件的文本经过处理,可以得到以下的数字索引,如下所示:



以上过程用python实现如下所示
def process_email(email_contents):
    vocab_list = get_vocab_list()

    word_indices = np.array([], dtype=np.int64)
    email_contents = email_contents.lower()
    email_contents = re.sub('<[^<>]+>', ' ', email_contents)
    email_contents = re.sub('[0-9]+', 'number', email_contents)
    email_contents = re.sub('(http|https)://[^\s]*', 'httpaddr', email_contents)
    email_contents = re.sub('[^\s]+@[^\s]+', 'emailaddr', email_contents)
    email_contents = re.sub('[$]+', 'dollar', email_contents)
    print('==== Processed Email ====')
    stemmer = nltk.stem.porter.PorterStemmer()
    tokens = re.split('[@$/#.-:&*+=\[\]?!(){\},\'\">_<;% ]', email_contents)
    for token in tokens:
        token = re.sub('[^a-zA-Z0-9]', '', token)
        token = stemmer.stem(token)
        if len(token) < 1:
            continue

        for i in range(1, len(vocab_list) + 1):
            if vocab_list[i] == token:
                word_indices = np.append(word_indices, i)

        print(token)

    print('==================')

    return word_indices


def get_vocab_list():
    vocab_dict = {}
    with open('vocab.txt') as f:
        for line in f:
            (val, key) = line.split()

            vocab_dict[int(val)] = key

    return vocab_dict

plt.ion()
np.set_printoptions(formatter={'float': '{: 0.6f}'.format})
print('Preprocessing sample email (emailSample1.txt) ...')
file_contents = open('emailSample1.txt', 'r').read()
word_indices = process_email(file_contents)

提取邮件中的特征

有了以上过程,需要从文本邮件中得到特征向量x,具体实现思路是:如果词汇表中第i个单词出现在邮件中,则用x_i=1表示,否则用x_i =0表示。最后,可以得到一个xn维向量,如下所示:


具体实现代码如下所示:
def email_features(word_indices):
    n = 1899
    features = np.zeros(n + 1)
    features[word_indices - 1] = 1
    return features

为垃圾邮件分类训练SVM算法

完成了邮件特征变量的提取之后,可以利用4000个训练样本和1000个测试样本训练SVM算法,每个原始的邮件将会被转化为一个x \in R^{1900}的向量(词汇表中有1899个词汇,x_0=1会被添加到向量中,最后,得到的向量包含1900个数字)。载入数据集之后,用变量y=1表示垃圾邮件,而y=0表示非垃圾邮件可就可以训练SVM算法了。具体实现代码如下所示:

data = scio.loadmat('spamTrain.mat')
X = data['X']
y = data['y'].flatten()

print('Training Linear SVM (Spam Classification)')
print('(this may take 1 to 2 minutes)')

c = 0.1
clf = svm.SVC(c, kernel='linear')
clf.fit(X, y)

p = clf.predict(X)
print('Training Accuracy: {}'.format(np.mean(p == y) * 100))

通过以上代码,运行后,得到的精确度如下所示:


最后,载入测试集数据,利用SVM算法构造的分类器,得到其训练精度如下所示:


相关文章

  • 用SVM算法构造垃圾邮件分类器

    前言 在之前的学习中,已经学习过了支持向量机的算法,在这部分内容中,需要使用2维数据实现带有高斯核函数的支持向量机...

  • 文本分类

    文本分类的一般流程: 预处理 文本表示及特征选择 构造分类器 分类 文本分类的应用 垃圾邮件的判定:是否为垃圾邮件...

  • 降维算法二:LDA(Linear Discriminant An

    前言 学习分类算法,线性分类器最简单的就是LDA,它可以看做是简化版的SVM,如果想理解SVM这种分类器,那理解L...

  • 机器学习系统设计(一)

    确定工作的优先级 以垃圾邮件分类器算法为例,要对垃圾邮件分类,我们首先要确定特征变量x,且其个数通常不超过100。...

  • 机器学习中的数学:线性判别分析、主成分分析

    如果学习分类算法,最好从线性的入手,线性分类器最简单的就是LDA,它可以看做是简化版的SVM,如果想理解SVM这种...

  • SMO优化算法(Sequential minimal optim

    机器学习 SVM分类器中SMO算法 https://blog.csdn.net/qq_28503457/artic...

  • 我们日常使用的机器学习

    机器学习的几类 线性分类器如垃圾邮件 众所周知,我们使用qq邮箱时候,有一些邮箱会被标记为垃圾邮件。算法会根据里面...

  • 基于HOG+SVM的猫咪识别器

    目的 使用HOG+SVM算法和OpenCV实现一个图片分类器,通过自己训练分类器,达到可以判断任意图片是否是猫咪的...

  • 基于HOG+SVM的猫咪识别器

    目的 使用HOG+SVM算法和OpenCV实现一个图片分类器,通过自己训练分类器,达到可以判断任意图片是否是猫咪的...

  • 机器学习第十课_svm算法

    支撑向量机,SVM(Support VectorMachine),其实就是一个线性分类器。在最初接到这个算法时,我...

网友评论

      本文标题:用SVM算法构造垃圾邮件分类器

      本文链接:https://www.haomeiwen.com/subject/edmdpqtx.html