介绍

在上一篇博客:数据挖掘入门系列教程(八点五)之SVM介绍以及从零开始公式推导中,详细的讲述了SVM的原理,并进行了详细的数学推导。在这篇博客中,主要是应用SVM,使用SVM进行数据分类,不会涉及到SVM的解释,so,如果对svm并不是特别了解的话,非常建议先去看我的上一篇博客(or其他博主的博客),然后再来看这一篇博客。因为在这篇并不是自己实现SVM而是基于sklearn中的svm包来进行应用。因此,我们可能使用几行代码可能就可以对数据集进行训练了。

「我们不仅要知其然,更要知其所以然。」

在这一章博客中,我们会使用SVM做两个任务:

  • 基于SVM对MINIST数据集进行分类。
  • 基于SVM对垃圾邮件进行判断

基于SVM对MINIST数据集进行分类

在前面神经网络的博客中,我们基于pybrain使用神经网络对MINIST手写数据集进行分类,但是最后结果并不是很好(可以说得上是比较差了),只有:

这次我们使用SVM来进行继续操作。数据集在前面的博客中已经进行说明,就不再赘述。

直接看代码吧:

使用SVM

下面的代码没有什么好说的,就是加载下载处理好的数据集,然后在将数据集分割成训练集和测试集(在Github中有这两个数据集,先解压再使用【其中dataset是压缩包,需要解压】):

import numpy as np
X = np.load("./Data/dataset.npy")
y = np.load("./Data/class.npy")
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(X,y,random_state=14 )

然后我们就可以使用SVM进行训练了:

from sklearn import svm
predictor = svm.SVC(gamma='scale', C=1.0, decision_function_shape='ovr', kernel='rbf')
# 进行训练
predictor.fit(x_train, y_train)

同样关于SVM的官网介绍在这里。关于svm包具体的使用可以看官方文档,官方文档写的还是蛮详细的。

这里来解释一下代码:

svm有很多类型的Estimators如下:

在这里我们选择SVC,也就是说使用SVM进行分类。具体的使用在这里。关于代码中参数的介绍:

  1. C = 1.0
    在上一章博客中,我们提到的软间隔支持向量机中提到了以下公式:

    其中C就是用来平衡结构风险和经验风险的。
  2. kernel='rbf'
    kernel代表的是核函数,“rbf”代表的就是(「高斯」「径向基函数核」(英语:Radial basis function kernel)表达式如下:

  3. gamma='scale'
    在rbf核函数中,我们有一个变量

    gamma='scale'代表

  4. decision_function_shape='ovr'
    在SVM的介绍中,我们详细的推导过SVM「二分类」的问题,但是如果类别是多个(大于3),那么怎么办呢?(比如说MINIST数据集中一共有0~9一共十个类别),此时我们可以使用一对一(one vs one),一对多(one vs rest)的方法来解决。
  • ovo
    其做法就是在任意两个类样本之间设计一个SVM,因此

    个类别的样本就需要设计
    个SVM。最后进行预测分类的时候,哪一个类别划分的次数最多,则就判定为该类别。
  • ovr
    训练时依次把某个类别的样本归为一类,其他剩余的样本归为另一类,这样k个类别的样本就构造出了k个SVM。分类时将未知样本分类为离超平面最远的那类。

fit()就是表示对数据集进行训练。

再然后,我们进行预测并使用F1进行评估:

# 预测结果
result = predictor.predict(x_test)
# 进行评估
from sklearn.metrics import f1_score
print("F-score: {0:.2f}".format(f1_score(result,y_test,average='micro')))

最后结果如下

,这个结果还是不错的。

本来呢,这篇博客到这里就ok了,怎么使用也介绍完了,但是我觉得这篇博客也太少了点,因此又决定再水一点内容。

SVM分析垃圾邮件

简单点来说,我们就是想通过一封邮件是不是垃圾邮件。一共有「1w+1」条数据(50001垃圾邮件数据,5k正常邮件的数据)。数据集下载地址:GitHub

部分数据展示如下:

其中每一行数据就是一封邮件。

加载数据集

加载数据集还是挺简单的,代码如下(数据集在我的GitHub中):

# 垃圾邮件文件地址
spam_data_path = "./Data/resource/spam_5000.utf8"
# 正常邮件文件地址
ham_data_path = "./Data/resource/ham_5000.utf8"with open(spam_data_path,encoding='utf-8') as f:spam_txt_list = f.readlines()
with open(ham_data_path,encoding="utf-8") as f:ham_txt_list= f.readlines()

这里还需要介绍一个概念——停止词(百度百科介绍):

❝ 人类语言包含很多功能词。与其他词相比,功能词没有什么实际含义。最普遍的功能词是限定词(“the”、“a”、“an”、“that”、和“those”),这些词帮助在文本中描述名词和表达概念,如地点或数量。介词如:“over”,“under”,“above” 等表示两个词的相对位置。
这些功能词的两个特征促使在搜索引擎的文本处理过程中对其特殊对待。第一,这些功能词极其普遍。记录这些词在每一个文档中的数量需要很大的磁盘空间。第二,由于它们的普遍性和功能,这些词很少单独表达文档相关程度的信息。如果在检索过程中考虑每一个词而不是短语,这些功能词基本没有什么帮助。
在信息检索中,这些功能词的另一个名称是:停用词(stopword)。称它们为停用词是因为在文本处理过程中如果遇到它们,则立即停止处理,将其扔掉。将这些词扔掉减少了索引量,增加了检索效率,并且通常都会提高检索的效果。停用词主要包括英文字符、数字、数学字符、标点符号及使用频率特高的单汉字等。

这里我们使用的是百度的停用词表,数据是来自GitHub,当然在我的GitHub上面,已经将这个词表上传上去了。

stop_word_path = "./Data/resource/stopword.txt"
with open(stop_word_path,encoding='utf-8') as f:# 去除空格以及换行符stop_words = f.read().strip()

分词

什么是分词呢?对于中文来说,分词就是将连续的一串子序列(句子)分成一个一个的词。比如说”我喜欢你“可以分成”我“,”喜欢“,”你“。实际上在计算机中对中文进行分词还是满困难的。因为有很多歧义,新词等等。这里我们使用jieba库进行分词,举例使用如下:

import jiebaa = "请不要把陌生人的些许善意,视为珍稀的瑰宝,却把身边亲近人的全部付出,当做天经地义的事情,对其视而不见"
cut_a = jieba.cut(a)
print(list(cut_a))

结果如下:

使用jieba对垃圾邮件和正常邮件进行分词代码如下(去除分词中的停词以及部分词):

import jiebaspam_words = []
# 垃圾邮件
for spam_txt in spam_txt_list:words = []cut_txts  = jieba.cut(spam_txt)for cut_txt in cut_txts:# 判断分词是否是字母表组成的,是否是换行符,并且是否在停词表中if(cut_txt.isalpha() and cut_txt!="n" and cut_txt not in stop_words):words.append(cut_txt)# 将词组成句子sentence = " ".join(words)spam_words.append(sentence)

spam_words部分数据结果如下(数据类型为list):

也就是说,我们将每一封垃圾邮件数据分成了一个一个的词(在词的中间使用空格分开),然后组成这一封邮件的词的特征。

同理我们处理正常邮件数据:

import jiebaham_words = []
for ham_txt in ham_txt_list:words = []cut_txts  = jieba.cut(ham_txt)for cut_txt in cut_txts:if(cut_txt.isalpha() and cut_txt!="n" and cut_txt not in stop_words):words.append(cut_txt)sentence = " ”.join(words)ham_words.append(sentence)

构建词云

这个没什么好说的,就是使用WordCloud构建词云。text是一个字符串,WordCloud会自动使用空格或者逗号对text进行分割。

%pylab inline
from wordcloud import WordCloud
import matplotlib.pyplot as plt
# 词云展示
def showWordCloud(text):wc = WordCloud(background_color = "white",max_words = 200,# 为了显示中文,使用字体font_path = "./Data/resource/simhei.ttf",min_font_size = 15,max_font_size = 50,width = 600)wordcloud = wc.generate(text)plt.imshow(wordcloud, interpolation="bilinear")plt.axis("off")

展示垃圾邮件词云我们将数据list变成使用空格连接的字符串。

showWordCloud(" ".join(spam_words))

展示正常邮件数据

showWordCloud(" ".join(ham_words))

构建数据集

通过前面的步骤我们已经得到了邮件进行分词之后的结果。在SVM中我们知道,每一条数据的特征的个数是一样多的(也就是他们拥有相同的特征,但是可能特征值不同),但是很明显对于文本数据,每一封邮件的特征词明显是不一样的。这里我们可以想一想在数据挖掘入门系列教程(七)之朴素贝叶斯进行文本分类中,我们使用了DictVectorizer转换器将特征字典转换成了一个矩阵,这里的数据是list数据,因此我们选择CountVectorizer将list数据转换成举证。

from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
import numpy as np
from collections import defaultdict
data = []
data.extend(ham_words)
data.extend(spam_words)
# binary默认为False,一个关键词在一篇文档中可能出现n次,如果binary=True,非零的n将全部置为1
# max_features 对所有关键词的出现的频率进行降序排序,只取前max_features个作为关键词集
vectorizer = CountVectorizer(binary=False,max_features=1500)
result = vectorizer.fit_transform(data)

然后我们在加上列对应的名字(非必须,不影响训练):

# 词汇表,为字典类型,key为词汇,value为索引
vocabulary = vectorizer.vocabulary_
result = pd.DataFrame(result.toarray())
# 对索引进行从小到大的排序
colnames = sorted(vocabulary.items(),key = lambda item:item[1])
colname = []
for i in colnames:colname.append(i[0])
result.columns = colname

最后部分的result的数据如下所示(0代表此词在邮件中没有出现,非0则代表出现):

其中index中

是正常的邮件数据,
是垃圾邮寄数据。

进行训练

from sklearn.model_selection import train_test_split
from sklearn.svm import SVC# 使用0,1划分垃圾邮件和正常邮件
labels = []
labels.extend(np.ones(5000))
labels.extend(np.zeros(5001))# 划分训练集和测试集
train,test,trainlabel,testlabel = train_test_split(result,labels,random_state=14)
predictor = SVC(gamma='scale', C=1.0, decision_function_shape='ovr', kernel='rbf')
predictor.fit(train,trainlabel)
predict_lable = predictor.predict(test)

最后进行评估结果为:

print("the accurancy is :",np.mean(predict_lable == testlabel))

交叉验证

当然我们还可以进行交叉验证来进行评估:

from sklearn.model_selection import cross_val_score
predictor = SVC(gamma='scale', C=1.0, decision_function_shape='ovr', kernel='rbf')
scores = cross_val_score(predictor,result,labels,scoring='f1')
print("Score: {}".format(np.mean(scores)))

这个准确度可以说是杠杠的:

炼丹术

继续水一波,来试一下选择不同数量的features,然后再观察不同数量的features对精度的影响。

from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
import numpy as np
import matplotlib.pyplot as pltlabels = []
labels.extend(np.ones(5000))
labels.extend(np.zeros(5001))# 画图的两个轴
scores = []
indexs = []data = []
data.extend(ham_words)
data.extend(spam_words)for i in range(1,3000,50):# 转换器vectorizer = CountVectorizer(binary=False,max_features=i)result = vectorizer.fit_transform(data)train,test,trainlabel,testlabel = train_test_split(result,labels,random_state=14)# 划分训练集和测试集    predictor = SVC(gamma='scale', C=1.0, decision_function_shape='ovr', kernel='rbf')predictor.fit(train,trainlabel)score = predictor.score(test,testlabel)scores.append(score)indexs.append(i)

然后,画图即可:

plt.plot(indexs,scores)
plt.show()

总的来说,结果还不错咯,500个以上的features就可以达到越

以上的精度。

总结

啊,终于水完了!!

这一篇博客主要是介绍基于sklearn的SVM的使用。可以很明显的看到,基本上只需要几行代码就ok了。因此我们更应该去关注svm的原理而不是简单的学会调用包然后就表示:“啊!我会了!SVM真简单”。实际上,如果我们不了解原理的话,我们甚至连调包都不知道里面的参数代表的含义是什么。

项目地址:Github

参考

  • wiki:径向基函数核
  • SVM实现多分类的三种方案
  • sklearn 实现中文数据集的垃圾邮件分类
  • 停止词

svm分类代码_数据挖掘入门系列教程(九)之基于sklearn的SVM使用相关推荐

  1. graphviz 画决策树_数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris

    数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris 加载数据集 数据特征 训练 随机森林 调参工程师 结尾 数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iri ...

  2. python亲和性分析_数据挖掘入门系列教程(一)之亲和性分析

    数据挖掘入门系列教程(一)之亲和性分析 教程系列简介 该教程为入门教程,为博主学习数据挖掘的学习路径步骤.教程为入门教程,从最简单的开始.使用的编程语言为Python3.8.1,使用JupyterNo ...

  3. 第十九课.基于sklearn的SVM人脸识别

    目录 数据集 确定人脸的类别标记 划分训练集和测试集与训练 实验为基于sklearn的SVM人脸识别,使用 SVM 算法对戴眼镜的人脸和不戴眼镜的人脸进行分类,从而完成 识别戴眼镜的人脸 的任务:实验 ...

  4. 决策树 prepruning_数据挖掘入门系列教程(三点五)之决策树

    本来还是想像以前一样,继续学习< Python数据挖掘入门与实践 >的第三章"决策树",但是这本书上来就直接给我怼了一大串代码,对于决策树基本上没有什么介绍,可直接把我 ...

  5. svm分类代码_当支持向量机遇上神经网络:SVM、GAN距离之间的关系

    选自arXiv 作者:Alexia Jolicoeur-Martineau 编辑:小舟.蛋酱 SVM 是机器学习领域的经典算法之一.如果将 SVM 推广到神经网络,会发生什么呢? 支持向量机(Supp ...

  6. 零基础数据挖掘入门系列(二) - 数据的探索性(EDA)分析

    思维导图:零基础入门数据挖掘的学习路径 1. 写在前面 零基础入门数据挖掘是记录自己在Datawhale举办的数据挖掘专题学习中的所学和所想, 该系列笔记使用理论结合实践的方式,整理数据挖掘相关知识, ...

  7. 零基础数据挖掘入门系列(三) - 数据清洗和转换技巧

    思维导图:零基础入门数据挖掘的学习路径 1. 写在前面 零基础入门数据挖掘是记录自己在Datawhale举办的数据挖掘专题学习中的所学和所想, 该系列笔记使用理论结合实践的方式,整理数据挖掘相关知识, ...

  8. 零基础数据挖掘入门系列(一) - 赛题理解

    思维导图:零基础入门数据挖掘的学习路径 1. 写在前面 零基础入门数据挖掘系列是记录自己在Datawhale举办的数据挖掘专题学习中的所学和所想, 该系列笔记使用理论结合实践的方式,整理数据挖掘相关知 ...

  9. Linux pwn入门教程,pwn堆入门系列教程1

    pwn堆入门系列教程1 因为自己学堆的时候,找不到一个系统的教程,我将会按照ctf-wiki的目录一步步学下去,尽量做到每周有更新,方便跟我一样刚入门堆的人学习,第一篇教程研究了4天吧,途中没人指导. ...

  10. html5游戏制作入门系列教程(八)

    今天,我已经准备了一个新的游戏 – SkyWalker.基本上 – 这是用飞飞行模拟射击类游戏.我们的目标到达终点线.这个游戏还有其它一些特点,例如使用飞机运动动画和爆炸动画,多按键处理(例如同时移动 ...

最新文章

  1. 【转】iOS开发学习计划
  2. python学习之if条件句的使用
  3. 算法学习:AC自动机
  4. Android——怎么在一个 Activity 中销毁另外一个 Activity
  5. 单选框radio绑定click事件
  6. 【C语言】数字在排序数组中出现的次数(改动)
  7. 利用MS17-010渗透win7(32位)
  8. 【C语言进阶深度学习记录】三十二 函数指针与使用函数指针实现回调函数
  9. dede无法在这个位置找到head.html2,织梦搜索:DedeCMS 提示信息
  10. 深度学习人体姿态估计:2014-2020全面调研
  11. 前端埋点的缺点_【埋点学习埋点质量】埋点的框架设计及其准确性
  12. Mellanox刘通:开放的理念让Mellanox的优势愈加凸显
  13. 伪静态URL、静态URL和动态URL的区别
  14. CSDN直播BlOB视频流下载,JAVA实现下载直播视频
  15. wind10 使用Hyper-V安装centos7遇到的问题及解决方案
  16. 自动驾驶汽车:传感器融合与5G互联的益处
  17. 一个3D车道线检测方法PersFormer及其开源OpenLane数据集
  18. 产品Backlog 管理
  19. jsp中给div加背景_html中给元素添加背景图片或者gif动图
  20. LeetCode——974.和可被K整除的子数组

热门文章

  1. OpenGL学习笔记_图形渲染管线及典型渲染流程(绘制一个三角形)
  2. 视觉惯性SLAM问题汇总
  3. 静默文件安装安装WebLogic
  4. ReactJs移动端兼容问题汇总
  5. PAT乙级.1013.数素数
  6. Hi3519v101调试 RTC功能
  7. MYSQL PGA SGA设置
  8. python 日志收集系统
  9. C#窗体控件简介ListBox
  10. 关于onclick中的event对象和element对象