概率分类之朴素贝叶斯分类(垃圾邮件分类python实现)

    科技2022-07-17  99

    目录

    什么是概率分类?朴素贝叶斯分类垃圾邮件分类


    什么是概率分类?

            举个最简单的二分类例子:有两类(w1, w2),有样本 x ,现问:xv属于w1,还是w2?         即求:p(w1 / x)与p(w2 / x),

    若p(w1 / x)> p(w2 / x)则 x 属于 w1;若p(w1 / x)< p(w2 / x)则 x 属于 w2。

    这就是利用概率进行分类!

            其中: 分子相同,故只用比较分母即可,其中:         p(w1)与p(w2)为w的先验概率;         p(w1 / x)、 p(w2 / x)为x在w上的后验概率         p(x / w1)、 p(x / w2)为x在w上的条件概率

    因此概率分类的关键是如何通过求条件概率!

    朴素贝叶斯分类

            朴素贝叶斯分类器 (naÏve Bayes classifier)采用:“属性条件独立性假设”:对已知类别,假设所有属性相互独立。换言之,假设每个属性独立地对分类结果发生影响。         故上式可写成:         其中 d 为属性数目, x i x_i xi x x x 在第 i i i 个属性上的取值。p(c)为样本中标签为c的样本数占总样本数的比值。         对离散属性而言:         D c , x i D_{c,x_i} Dc,xi, 表示 D c D_c Dc 中在第 i i i 个属性上取值为 x i x_i xi 的样本组成的集合。

            对连续属性而言:

    垃圾邮件分类

    垃圾邮件分类问题:         标签 c i , i = 1 , 2 c_i,i={1,2} ci,i=1,2 c 1 c_1 c1 (正常邮件), c 2 c_2 c2(垃圾邮件),输入邮件为 w w w,邮件有d个属性值{x1, x2, x3, …xd}         由上述可知求 P ( c 1 ∣ w ) P(c_1 | w) Pc1w P ( c 2 ∣ w ) P(c_2|w) Pc2w         即求: P ( w ∣ c 1 ) P(w |c_1) Pwc1 P ( w ∣ c 2 ) P(w|c_2) Pwc2

            Python的sklearn包中有现成的朴素贝叶斯分类类可以调用(多项式的朴素贝叶斯分类):

    from sklearn.naive_bayes import MultinomialNB

    这是搜狗2020校招的一道算法题:

            编写Naïve Bayes分类模型对邮件文本进行分类,判断该邮件是不是垃圾邮件(二分类)。我们已经通过数据预处理,将原始的邮件文本数据转化为分类器可用的数据向量形式,具体:数据表示为整型数向量x=(x1,x2,…,xd)。d是数据特征向量的维数,每个输入数据样本的格式为:         Label x1 x2 … xd         其中Label为0或者1的整型数字(0表示正常邮件,1表示垃圾邮件);         x1 x2 … xd是离散化后的特征,表示为从0开始的自然数;         维度d小于20;         如果Label=?,则表示希望输出的预测类别值(需要预测的类别一定已在对应的训练数据中已经出现过)。

    这里采用了 l o g log log,将连乘变为了连加,效果一样:

    import math def trainNB(traindata, trainlabel): # 训练集大小 lenstrain = len(traindata) # 特征属性维度 lensvec = len(traindata[0]) # 训练集中标签为0的样本概率 p0 = sum(trainlabel)/lenstrain # 采用拉普拉斯修正 p0d, p1d = [1]*lensvec, [1]*lensvec p0sum, p1sum = 2.0, 2.0 for i in range(lenstrain): if trainlabel[i]==1: for j in range(lensvec): p1d[j] += traindata[i][j] p1sum += sum(traindata[i]) else: for j in range(lensvec): p0d[j] += traindata[i][j] p0sum += sum(traindata[i]) p0vecpro = [math.log(p0d[i]/p0sum) for i in range(lensvec)] p1vecpro = [math.log(p1d[i]/p1sum) for i in range(lensvec)] return p0vecpro, p1vecpro, p0 def test(testdata, p0vecpro, p1vecpro, p0): lenstest = len(testdata) p0test = 0 p1test = 0 for i in range(lenstest): p0test += p0vecpro[i]*testdata[i] p1test += p1vecpro[i]*testdata[i] p0test += math.log(p0) p1test += math.log(1-p0) if p0test>p1test: return 0 else: return 1 traindata, trainlabel, testdata = [], [], [] M, N, d = map(int, input().split("\t")) for i in range(M): line = [int(j) for j in input().split("\t")] traindata.append(line[1:]) trainlabel.append(line[0]) for i in range(N): line = [int(j) if j!="?" else j for j in input().split("\t")] testdata.append(line[1:]) p0vecpro, p1vecpro, p0 = trainNB(traindata, trainlabel) for i in range(N): print(test(testdata[i], p0vecpro, p1vecpro, p0))
    Processed: 0.011, SQL: 8