700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 贝叶斯分类器 什么是朴素贝叶斯 后续为使用贝叶斯实现海量数据的邮件筛选。带源码数

贝叶斯分类器 什么是朴素贝叶斯 后续为使用贝叶斯实现海量数据的邮件筛选。带源码数

时间:2021-09-25 06:08:09

相关推荐

贝叶斯分类器 什么是朴素贝叶斯 后续为使用贝叶斯实现海量数据的邮件筛选。带源码数

朴素贝叶斯分类器.

任务:

理解朴素贝叶斯分类器。

实现我们的第一个贝叶斯分类器。

使用朴素贝叶斯分类器分类邮件.

概率论基础:

随机变量:

这个变量的值依赖于概率。抛硬币(其结果可能是正面,也可能是反面)是一个很好的例子。如果一个随机变量只能取有限数量的值,我们称其为离散变量(例如,抛硬币或者掷骰子);否则,我们就称其为连续随机变量(例如,某一天的温度)。通常随机变量用大写字母表示.

概率:

这是对事件发生可能性的度量。我们把一个事件E发生的概率表示为p(E),其中p(E)必须是在0到1之间(或者在0到100%之间)的一个数.

条件概率:

这是在另一个事件发生的情况下,对一个事件发生概率的度量。在已知事件X发生的情况下,我们把事件Y发生的概率表示为p(y|x)(读作在已知X的情况下,求Y的概率p).

概率分布:

这个函数告诉我们在同一个实验中不同事件发生的概率.

对于离散随机变量,这个函数也称为概率质量函数(probability mass function)。

对于连续随机变量,这个函数也称为概率密度函数(probability density function).

联合概率分布:

这基本上是把前面的概率函数应用于多个随机变量.

这里有个技巧:

如果我们把数据集看成是一个随机变量X,那么一个机器学习模型主要就是学习X到一组可能的目标标签Y的映射。

或者说,我们正在试着学习一个条件概率p(Y|X),即从X中抽取的一个随机样本,其目标标签是Y的概率.

正如前面介绍的那样,有两种不同的方法学习p(Y|X):

>判别式模型:

:这类模型从训练数据直接学习p(Y|X),无须浪费时间去理解底层概率分布(例如p(X)、p(Y),或者p(Y|X))。这种方法几乎适用于我们目前遇到过的所有学习算法:线性回归、k-近邻、决策树等.

>生成式模型:

:这类模型学习所有底层概率分布,然后根据联合概率分布p(X,Y)推断p(Y|X)。因为这些模型知道p(X,Y),它们不但可以告诉我们一个数据点属于一个特定目标标签的可能性有多大,还可以生成全新的数据点.

理解贝叶斯定理(/rational/bayes)[一个著名的例子]

朴素贝叶斯分类器:(Naive Bayes Classifier 或 NBC)

/item/%E6%9C%B4%E7%B4%A0%E8%B4%9D%E5%8F%B6%E6%96%AF/4925905

假设所有的P(Y|X1,X2…Xn) 中 X1-Xn 都是相互独立的。在真实场景中很少出现这种情况,故而这种假设有点简单。这就是朴素贝叶斯分类器名字的由来.

NBC模型所需估计的参数很少,对缺失数据不太敏感,算法也比较简单。理论上,NBC模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为NBC模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,这给NBC模型的正确分类带来了一定影响

文本分类

分类是数据分析和机器学习领域的一个基本问题.

文本分类已广泛应用于网络信息过滤、信息检索和信息推荐等多个方面。数据驱动分类器学习一直是近年来的热点,方法很多,比如神经网络、决策树、支持向量机、朴素贝叶斯等。相对于其他精心设计的更复杂的分类算法,朴素贝叶斯分类算法是学习效率和分类效果较好的分类器之一。直观的文本分类算法,也是最简单的贝叶斯分类器,具有很好的可解释性,朴素贝叶斯算法特点是假设所有特征的出现相互独立互不影响,每一特征同等重要。但事实上这个假设在现实世界中并不成立:首先,相邻的两个词之间的必然联系,不能独立;其次,对一篇文章来说,其中的某一些代表词就确定它的主题,不需要通读整篇文章、查看所有词。所以需要采用合适的方法进行特征选择,这样朴素贝叶斯分类器才能达到更高的分类效率。

其他

朴素贝叶斯算法在文字识别, 图像识别方向有着较为重要的作用。 可以将未知的一种文字或图像,根据其已有的分类规则来进行分类,最终达到分类的目的。

现实生活中朴素贝叶斯算法应用广泛,如文本分类,垃圾邮件的分类,信用评估,钓鱼网站检测等等.

from sklearn import datasetsimport numpy as npimport matplotlib.pyplot as pltimport pandas as pdimport cv2import sklearnfrom sklearn.model_selection import train_test_splitX,Y = datasets.make_blobs(500,2,centers = 2,random_state = 1701,cluster_std = 2)X = X.astype(np.float32)Y = Y.astype(np.float32)plt.scatter(X[:,0],X[:,1],c=Y,s = 50)

<matplotlib.collections.PathCollection at 0x19a75a5b630>

x_train,x_test, y_train, y_test = train_test_split(X, Y,test_size=0.1)x_train,y_train

(array([[-2.79518723e+00, -8.22881699e-01],[-1.05599594e+01, -4.86849737e+00],[-1.90754294e+00, -3.84562039e+00],[-9.88454914e+00, -8.99528027e+00],[ 2.24983287e+00, 4.01547641e-01],[-7.92066622e+00, -5.53331089e+00],[-5.40525150e+00, -9.27240562e+00],[-8.61370277e+00, -6.71525431e+00],[ 3.33042598e+00, 2.08401442e+00],[-8.52738321e-01, -2.81190300e+00],[-5.82671344e-01, 2.11686641e-01],[-7.58908844e+00, -8.26457691e+00],array([1., 0., 1., 0., 1., 0., 0., 0., 1., 1., 1., 0., 1., 0., 0., 1., 0.,0., 0., 1., 0., 0., 1., 1., 1., 1., 1., 1., 1., 1., 0., 0., 0., 0.,0., 1., 0., 1., 0., 1., 0., 0.], dtype=float32))

使用普通贝叶斯分类器对数据进行分类

1)使用以下函数,我们可以创建一个新分类器:

2)接着,通过train方法进行训练:

3)一旦分类器训练成功,就返回True.

4)绘图函数检验决策边界!如果你还记得的话,我们的思路是创建一个包含所有数据点的网格,再分类网格上的每个点。通过同名的NumPy函数创建网格:

5)meshgrid函数将返回2个浮点矩阵xx和yy,包含网格上每个坐标点x和y坐标们使用ravel函数可以把这些矩阵展开成列向量,并把它们堆叠形成一个新矩阵X_hypo:

6)现在,X_hypo包含了X_hypo[:, 0]中的所有x值以及X_hypo[:, 1]中的所有y值.

7)然而,我们希望能够同时使用OpenCV和scikit-learn的模型.

这两者之间的区别是OpenCV返回多个变量(表示成功/失败的一个布尔标志以及预测的目标标签),而scikit-learn只返回预测的目标标签.

sklearn中贝叶斯模型有以下几种分布类型:

伯努利分布,高斯分布,多项式分布

all= [‘BernoulliNB’, ‘GaussianNB’, ‘MultinomialNB’, ‘ComplementNB’,

‘CategoricalNB’]

# 加载朴素贝叶斯模型# cv2_Bayes = cv2.ml.NormalBayesClassifier_create()# cv2_Bayes.train(x_train,cv2.ml.ROW_SAMPLE,y_train)from sklearn import naive_bayessklearn_Bayes_Gaussian = naive_bayes.GaussianNB()sklearn_Bayes_Bernoulli = naive_bayes.BernoulliNB()# sklearn_Bayes_Complement = plementNB()# sklearn_Bayes_Complement.fit(x_train,y_train)sklearn_Bayes_Bernoulli.fit(x_train,y_train)sklearn_Bayes_Gaussian.fit(x_train,y_train)

GaussianNB()

def plt_decision_boundary(model,x_test,y_test):h = 0.02x_min,x_max = x_test[:,0].min()-1,x_test[:,0].max()+1y_min,y_max = x_test[:,1].min()-1,x_test[:,1].max()+1xx,yy = np.meshgrid(np.arange(x_min,x_max,h),np.arange(y_min,y_max,h))x_hypo = np.column_stack((xx.ravel().astype(np.float32),yy.ravel().astype(np.float32)))ret = model.predict(x_hypo)if isinstance(ret,tuple): # 返回一个对象是否是一个类的实例或其子类的实例。zz = ret[1]else: zz = retzz = zz.reshape(xx.shape)plt.contourf(xx,yy,zz,cmap = plt.cm.coolwarm,alpha = 0.8)plt.scatter(x_test[:,0],x_test[: ,1],c = y_test,s= 20)

我们通过传递一个模型(model_norm)、一个特征矩阵(X),以及一个目标标签向量(y)调用函数:

plt.subplot(121)plt.title("Bayes_Gaussian")plt.text(-13,5,f"score is {sklearn_Bayes_Gaussian.score(x_test,y_test)}")plt_decision_boundary(sklearn_Bayes_Gaussian,X,Y)plt.subplot(122)plt.title("Bayes_Bernoulli")plt.text(-13,5,f"score is {sklearn_Bayes_Bernoulli.score(x_test,y_test)}")plt_decision_boundary(sklearn_Bayes_Bernoulli,X,Y)plt.show()# plt_decision_boundary(sklearn_Bayes_Complement,X,Y)

这里,y_proba是一个N×2的矩阵,表示N个数据点中的每一个数据点分类为0类或者1类的概率:

# 查看每一项分布的概率y_proba = sklearn_Bayes_Gaussian.predict_proba(x_test)y_proba,y_proba.shape

(array([[6.67123910e-09, 9.99999993e-01],[3.25034981e-11, 1.00000000e+00],[8.61484778e-07, 9.99999139e-01],[9.99999998e-01, 2.12333267e-09],[9.99999764e-01, 2.35882152e-07],[1.76920832e-08, 9.99999982e-01],[4.62116174e-09, 9.99999995e-01],[9.99999998e-01, 2.31522665e-09],[9.99995365e-01, 4.63528804e-06],[1.00000000e+00, 1.16713331e-10],[4.66004901e-05, 9.99953400e-01],[9.99999824e-01, 1.76352079e-07],[9.99999962e-01, 3.81341079e-08],[9.68532424e-08, 9.99999903e-01],[9.99937130e-01, 6.28697724e-05],[9.99984755e-01, 1.52450663e-05],[9.99999495e-01, 5.04574456e-07],[3.09641222e-05, 9.99969036e-01],[1.65794167e-11, 1.00000000e+00]]),(50, 2))

使用朴素贝叶斯算法处理解决一个二值分类(垃圾邮件/非垃圾邮件)问题。

朴素贝叶斯分类器实际上是一个非常流行的邮件过滤模型。它们很适合于文本数据的分析,其中每个特征都是一个单词(或者词袋模型),而每个单词都依赖于其他单词建模是不可行的。

邮件数据集:使用Enrom-Spam数据集

Hewlett-Packard垃圾邮件数据集:

https://archive.ics.uci.edu/ml/machine-learning-databases/spambase。

Enrom-Spam数据集:

http://www.aueb.gr/users/ion/data/enron-spam.

import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport sklearnimport skimageimport os

datadir = '../data/chapter7'sources = [('beck-s.tar.gz', 0),('farmer-d.tar.gz', 0),('kaminski-v.tar.gz', 0),('kitchen-l.tar.gz', 0),('lokay-m.tar.gz', 0),('williams-w3.tar.gz', 0),('BG.tar.gz', 1),('GP.tar.gz', 1),('SH.tar.gz', 1)]

#第一步是把这些文件提取到子目录., 读取一个压缩文件

def extract_tar(datafile,extractdir):try:import tarfileexcept ImportError:raise ImportError(' you do not have tarfile installed')tar = tarfile.open(datafile, 'r')tar.extractall(path=extractdir)tar.close()print("%s successfully extracted to %s"%(datafile,extractdir))

# for source ,_ in sources:#datafile = datadir + "/" + source#extract_tar(datafile,datadir)

现在,这里有个棘手的地方。每一个子目录都包含很多其他目录,文本文件就放在这些目录中。因此,我们需要编写两个函数:

read_single_file(filename):这个函数提取来自于filename文件的相关内容。

read_files(path):这个函数提取来自于path特定目录中的所有文件的相关内容.

要提取一个文件的相关内容,我们需要了解每个文件的结构。我们只知道邮件的标题部分(From:、To:和Cc:)

和正文用换行符“/n”分隔。因此,我们能做的就是遍历文本文件中的每一行,只保留那些属于正文的行,并将其存储在变量行中.

我们还想保留一个布尔标志past_header,最初把这个布尔标志设置为False,但是一旦我们通过了头文件部分,它就会变为True:

1)我们先初始化这两个变量:

2)接着,我们查看是否存在一个名为filename的文件。如果存在,我们开始逐行遍历:

os.walk()目录树生成器

作用:

对于目录树中以top为根的每个目录(包括top

本身,但不包括’.‘和’…'),产生一个3元组

dirpath, dirnames, filenames

dirpath是一个字符串,是指向该目录的路径。dirpath中的子目录的名称(不包括'.'和'..')。filenames是dirpath中的非目录文件的名称列表。注意,列表中的名字只是名字,没有路径成分。要想获得一个文件或目录的完整路径(以top开头),可以在中的文件或目录的完整路径(以top开头),请执行os.path.join(dirpath, name).

def read_single_file (filename):past_header,lines = False, []if os.path.isfile(filename): # 如果这个文件存在f = open(filename, encoding="latin-1") #因为一些邮件没有使用统一码,这条语句试图正确解码文件。#我们不想保留头文件信息,因此我们继续循环,直到遇到"\n"字符,此时我们把past_header从False转换成True。for line in f:if past_header:lines.append(line)elif line == "\n":past_header =Truef.close()#把所有行连接成一个字符串,由换行符分隔,返回文件的完整路径和文件的实际内容:content = "\n".join(lines)return filename,contentdef read_files(path):"""循环遍历一个文件夹中的所有文件,并调用read_single_file:"""for dirpath, dirnames, filenames in os.walk(path): #目录树生成器 ,产生一个3元组 [dirpath, dirnames, filenames]for filename in filenames:filepath = os.path.join(dirpath, filename) # 获得一个文件或目录的完整路径(以top开头)yield read_single_file(filepath) # yield是一个类似于return的关键字。区别是yield返回的是一个生成器而不是实际的值

使用pandas 建立数据矩阵

结合上述函数从提取的数据中建立一个pandas DataFrame:

def build_data_frame(extractdir, classification):rows = []index = []for file_name, text in read_files(extractdir):rows.append({'text': text, 'class': classification})index.append(file_name)data_frame = pd.DataFrame(rows, index=index)return data_framedata = pd.DataFrame({'text': [], 'class': []})for source, classification in sources:extractdir = '%s/%s' % (datadir, source[:-7])data = data.append(build_data_frame(extractdir, classification),sort=True)

data.shapedata

52076 rows × 2 columns

数据预处理阶段:

CountVectorize :只考虑每种词汇在该训练文本中出现的频率.将文本中的词语转换为词频矩阵

CountVectorizer类的参数很多,分为三个处理步骤:preprocessing、tokenizing、n-grams generation.

一般要设置的参数是:ngram_range,max_df,min_df,max_features等,具体情况具体分析

#参数有:

encodeing 使用默认的utf-8即可,分析器将会以utf-8解码raw document

strip_accents 默认为None,可设为ascii或unicode,

ngram_range 词组切分的长度范围

lowercase 将所有字符变成小写

max_df 可以设置为范围在[0.0 1.0]的float,也可以设置为没有范围限制的int,默认为1.0。

这个参数的作用是作为一个阈值,当构造语料库的关键词集的时候,如果某个词的document frequence大于max_df,这个词不会被当作关键词.

min_df 类似于max_df

max_features 默认为None,可设为int,对所有关键词的term frequency进行降序排序,只取前max_features个作为关键词集

dtype 使用CountVectorizer类的fit_transform()或transform()将得到一个文档词频矩阵,dtype可以设置这个矩阵的数值类型

矩阵元素a[i][j] 表示j词在第i个文本下的词频,即各个词语出现的次数.

通过get_feature_names()可看到所有文本的关键字,通过toarray()可看到词频矩阵的结果.

from sklearn import feature_extractioncounts = feature_extraction.text.CountVectorizer()X = counts.fit_transform(data['text'].values)X.shape,X

((52076, 643270),<52076x643270 sparse matrix of type '<class 'numpy.int64'>'with 8607632 stored elements in Compressed Sparse Row format>)

它告诉我们一共收集了52076封电子邮件,总共包含643270个不同的单词.保存在了一个稀疏矩阵中间

#常见稀疏矩阵的存储方式:

1.有三元组表示法、

2.带辅助行向量的二元组表示法(也即行逻辑链表的顺序表),

3.十字链表表示法

要建立目标标签(label)的向量,我们需要访问pandas DataFrame中的数据。这通过把DataFrame看成一个字典来实现,

其中values属性将允许我们访问底层的NumPy数组:也就是每个样本的标签我们最开始就保存在了class中

sklearn中贝叶斯模型有以下几种分布类型:

伯努利分布,高斯分布,多项式分布

伯努利分布’BernoulliNB’:

伯努利分布(Bernoulli distribution)又名两点分布或0-1分布,伯努利试验是只有两种可能结果的单次随机试验,即对于一个随机变量X而言

高斯分布’GaussianNB’:

正态分布

多项式分布’MultinomialNB’:

Multinomial Variables说白了就是多种选择选其一.

比如随机变量X有三种取值x1,x2,x3,那么用一个三维向量表示Multinomial 的取值就是{1,0,0},{0,1,0},{0,0,1}

分别代表选中x1,x2,x3,即必须选中一个,同时只能选一个这样的意思.

all= [‘BernoulliNB’, ‘GaussianNB’, ‘MultinomialNB’, ‘ComplementNB’,

‘CategoricalNB’]

label = data['class'].values

训练朴素贝叶斯模型

使用naive_bayes模块的MultinomialNB,这是最适合处理类别数据(如单词计数)的朴素贝叶斯分类器.

from sklearn import naive_bayesmodel_naive = naive_bayes.MultinomialNB() # 假设数据类型是多项式分布from sklearn import model_selection as msX_train, X_test, y_train, y_test = ms.train_test_split(X, label, test_size=0.2, random_state=42)print(X_train.shape,y_train.shape)model_naive.fit(X_train, y_train)print(model_naive.score(X_test,y_test))model_naive.score(X_train,y_train),model_naive.score(X_test, y_test)

(41660, 643270) (41660,)0.9442204301075269(0.9508641382621219, 0.9442204301075269)TypeError: score() missing 1 required positional argument: 'y'初始化的时候没有加(),后修改为model_naive = naive_bayes.MultinomialNB()

其他文章

Glcm 灰度共生矩阵,保姆级别教程,带源码

SVM支持向量机自动调优,带源码

HOG特征+SVM 进行行人检测,带源码,异常处理

Sober算子边缘检测与Harris角点检测1

贝叶斯分类器 什么是朴素贝叶斯 后续为使用贝叶斯实现海量数据的邮件筛选。带源码数据集和解决思路

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。