前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >朴素贝叶斯法(Naive Bayes,NB)

朴素贝叶斯法(Naive Bayes,NB)

作者头像
Michael阿明
发布2020-07-13 17:17:21
7370
发布2020-07-13 17:17:21
举报

1. 朴素贝叶斯法的学习与分类

1.1 基本方法

  • 输入空间
\chi \subseteq R^n

, n维向量的集合

  • 输出空间:类标记集合
Y'=\{c_1,c_2,...c_k\}
  • 输入:特征向量
x \in \chi
  • 输出:类标记
y \in Y'
X

是空间

\chi

上的随机向量

Y

是输出空间

Y'

上的随机变量

  • 训练数据集
T=\{(x_1,y_1),(x_2,y_2),...(x_N,y_N)\}

P(X,Y)

联合概率分布 独立同分布产生

目标 :通过训练数据集学习 联合概率分布

P(X,Y)
  1. 先验概率分布:
P(Y=c_k), k=1,2,...,K
  1. 条件概率分布:
P(X=x|Y=c_k)=P(X^{(1)}=x^{(1)},...,X^{(n)}=x^{(n)}|Y=c_k), k=1,2,...,K

上面两项相乘即可得到联合概率

P(X,Y)

但是

P(X=x|Y=c_k)

指数级 数量的参数,如果

x^{(j)}

的取值有

S_j

个,

j=1,2,...,n

Y

可取值有

K

个,总的参数个数为

K \prod_{j=1}^n S_j

, 不可行

做出 条件独立性假设

X^{(j)}

之间独立

P(X=x|Y=c_k)=P(X^{(1)}=x^{(1)},...,X^{(n)}=x^{(n)}|Y=c_k)=\prod_{j=1}^nP(X^{(j)}=x^{(j)}|Y=c_k) \quad\quad (1)

朴素贝叶斯法实际上学习到生成数据的机制,所以属于生成模型。条件独立假设等于是说用于分类的特征在类确定的条件下都是条件独立的。这一假设使朴素贝叶斯法变得简单,但有时会牺牲一定的分类准确率。

朴素贝叶斯法分类时,对给定的输入

x

,通过学习到的模型计算后验概率分布

P(Y=c_k | X=x)

,将后验概率最大的类作为

x

的类输出。

推导

P(Y=c_k | X=x) = \frac {P(X=x|Y=c_k)P(Y=c_k)}{\sum\limits_k P(X=x|Y=c_k)P(Y=c_k)} \quad\quad (2)

贝叶斯定理

将(1)代入(2)有:

P(Y=c_k | X=x) = \frac {P(Y=c_k)\prod\limits_{j}P(X^{(j)}=x^{(j)}|Y=c_k)}{\sum\limits_k P(Y=c_k)\prod\limits_{j}P(X^{(j)}=x^{(j)}|Y=c_k)}, k=1,2,...,K \quad\quad

所以 朴素贝叶斯分类器表示为:

\color{red} y=f(x)=\argmax\limits_{c_k} \frac {P(Y=c_k)\prod\limits_{j}P(X^{(j)}=x^{(j)}|Y=c_k)}{\sum\limits_k P(Y=c_k)\prod\limits_{j}P(X^{(j)}=x^{(j)}|Y=c_k)}

上式中,分母对所有的

c_k

都是相同的,所以

\color{red} y=\argmax\limits_{c_k} P(Y=c_k) \prod\limits_{j} P(X^{(j)}=x^{(j)}|Y=c_k)

2. 参数估计

2.1 极大似然估计

  1. 先验概率:
P(Y=c_k)=(y_i=c_k的样本数)/N
  1. 条件概率分布:
P(X^{(j)}=x^{(j)}|Y=c_k)

设第

j

个特征

x^{(j)}

可能的取值为

\{a_{j1},a_{j2},...,a_{jSj}\}

, 条件概率的极大似然估计为:

在这里插入图片描述
在这里插入图片描述
x_i^{(j)}

是第

i

个样本的第

j

个特征;

a_{jl}

是第

j

个特征可能的第

l

个值,

I

指示函数

2.2 学习与分类算法

朴素贝叶斯算法:

输入

  • 训练数据
T=\{(x_1,y_1),(x_2,y_2),...(x_N,y_N)\}
  • 其中
x_i=(x_i^{(1)},x_i^{(2)},...,x_i^{(n)})^T

x_i^{(j)}

是第

i

个样本的第

j

个特征

x_i^{(j)} \in \{a_{j1},a_{j2},...,a_{jSj}\}

,

a_{jl}

是第

j

个特征可能的第

l

个值,

j=1,2,...,n; l=1,2,...,S_j
y_i \in \{c_1,c_2,...c_k\}
  • 实例
x

输出

  • 实例
x

的分类

步骤

  1. 计算先验概率及条件概率
P(Y=c_k)=(y_i=c_k的样本数)/N, k=1,2,...,K
在这里插入图片描述
在这里插入图片描述
  1. 对于给定的实例
x=(x^{(1)},x^{(2)},...,x^{(n)})^T

, 计算

P(Y=c_k) \prod\limits_{j=1}^n P(X^{(j)}=x^{(j)}|Y=c_k), k=1,2,...,K
  1. 确定实例
x

的类

y=\argmax\limits_{c_k} P(Y=c_k) \prod\limits_{j=1}^n P(X^{(j)}=x^{(j)}|Y=c_k)
2.2.1 例题

例题: 用下表训练数据学习一个贝叶斯分类器并确定

x=(2,S)^T

的类标记

y

X^{(1)},X^{(2)}

为特征,取值的集合分别为

A_1=\{1,2,3\}, A_2=\{S,M,L\}

,

Y

为类标记,

Y \in C=\{1,-1\}

训练数据

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

X(1)X^{(1)}X(1)

1

1

1

1

1

2

2

2

2

2

3

3

3

3

3

X(2)X^{(2)}X(2)

S

M

M

S

S

S

M

M

L

L

L

M

M

L

L

YYY

-1

-1

1

1

-1

-1

-1

1

1

1

1

1

1

1

-1

X^{(1)}

1 1 1 1 1 2 2 2 2 2 3 3 3 3 3

X^{(2)}

S M M S S S M M L L L M M L L

Y

-1 -1 1 1 -1 -1 -1 1 1 1 1 1 1 1 -1

: 先验概率

P(Y=1)=\frac {9}{15},P(Y=-1)=\frac {6}{15}

条件概率

P(X^{(1)}=1|Y=1)= \frac{2}{9},P(X^{(1)}=2|Y=1)= \frac{3}{9},P(X^{(1)}=3|Y=1)= \frac{4}{9}
P(X^{(2)}=S|Y=1)= \frac{1}{9},P(X^{(2)}=M|Y=1)= \frac{4}{9},P(X^{(2)}=L|Y=1)= \frac{4}{9}
P(X^{(1)}=1|Y=-1)= \frac{3}{6},P(X^{(1)}=2|Y=-1)= \frac{2}{6},P(X^{(1)}=3|Y=-1)= \frac{1}{6}
P(X^{(2)}=S|Y=-1)= \frac{3}{6},P(X^{(2)}=M|Y=-1)= \frac{2}{6},P(X^{(2)}=L|Y=-1)= \frac{1}{6}

对给定的

x=(2,S)^T

计算:

Y=1

时:

\quad \quad\ \quad P(Y=1)P(X^{(1)}=2|Y=1)P(X^{(2)}=S|Y=1)=\frac{9}{15} * \frac{3}{9} * \frac{1}{9} = \frac{1}{45}
Y=-1

时:

\quad \quad\ \quad P(Y=-1)P(X^{(1)}=2|Y=-1)P(X^{(2)}=S|Y=-1)=\frac{6}{15} * \frac{2}{6} * \frac{3}{6} = \frac{1}{15}
Y=-1

时的概率最大,所以

y=-1

2.2.2 例题代码
代码语言:javascript
复制
# -*- coding:utf-8 -*-
# Python 3.7
# @Time: 2020/1/19 22:08
# @Author: Michael Ming
# @Website: https://michael.blog.csdn.net/
# @File: naiveBayes.py

import numpy as np
data = [[1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3],
        ['S', 'M', 'M', 'S', 'S', 'S', 'M', 'M', 'L', 'L', 'L', 'M', 'M', 'L', 'L'],
        [-1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1]]
X1 = []
X2 = []
Y = []
for i in range(len(data[0])):  # 统计数据种类
    if data[0][i] not in X1:
        X1.append(data[0][i])
    if data[1][i] not in X2:
        X2.append(data[1][i])
    if data[2][i] not in Y:
        Y.append(data[2][i])
nY = [0] * len(Y)
for i in range(len(data[0])):  # 统计Yi的数量
    nY[Y.index(data[2][i])] += 1
PY = [0.0] * len(Y)
for i in range(len(Y)):
    PY[i] = nY[i] / len(data[0])  # Yi的概率
PX1_Y = np.zeros((len(X1), len(Y)))  # 条件概率
PX2_Y = np.zeros((len(X2), len(Y)))

for i in range(len(data[0])):
    PX1_Y[X1.index(data[0][i])][Y.index(data[2][i])] += 1  # 统计频数
    PX2_Y[X2.index(data[1][i])][Y.index(data[2][i])] += 1
for i in range(len(Y)):
    PX1_Y[:, i] /= nY[i]  # 转成条件概率
    PX2_Y[:, i] /= nY[i]
x = [2, 'S']
PX_Y = [PX1_Y, PX2_Y]
X = [X1, X2]
ProbY = [0.0] * len(Y)
for i in range(len(Y)):
    ProbY[i] = PY[i]
    for j in range(len(x)):
        ProbY[i] *= PX_Y[j][X[j].index(x[j])][i]
maxProb = -1
idx = -1
for i in range(len(Y)):  # 取最大的概率
    if ProbY[i] > maxProb:
        maxProb = ProbY[i]
        idx = i
print(Y)
print(ProbY)
print(x, ", 最有可能对应的贝叶斯估计 y = %d" % (Y[idx]))
代码语言:javascript
复制
# 运行结果
[-1, 1]
[0.06666666666666667, 0.02222222222222222]
[2, 'S'] , 最有可能对应的贝叶斯估计 y = -1

2.3 贝叶斯估计(平滑)

用极大似然估计可能会出现所要估计的概率值为0的情况。会影响到后验概率的计算结果,使分类产生偏差。解决方法是采用贝叶斯估计。

条件概率的贝叶斯估计:

在这里插入图片描述
在这里插入图片描述

式中

\lambda \geq 0

, 取 0 时,就是极大似然估计; 取正数,对随机变量各个取值的频数上赋予一个正数; 常取

\lambda = 1

,这时称为 拉普拉斯平滑(Laplacian smoothing)

先验概率的贝叶斯估计:

在这里插入图片描述
在这里插入图片描述
2.3.1 例题

例题:(与上面一致,采用拉普拉斯平滑估计概率,取

\lambda=1

) 用下表训练数据学习一个贝叶斯分类器并确定

x=(2,S)^T

的类标记

y

X^{(1)},X^{(2)}

为特征,取值的集合分别为

A_1=\{1,2,3\}, A_2=\{S,M,L\}

,

Y

为类标记,

Y \in C=\{1,-1\}

训练数据

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

X(1)X^{(1)}X(1)

1

1

1

1

1

2

2

2

2

2

3

3

3

3

3

X(2)X^{(2)}X(2)

S

M

M

S

S

S

M

M

L

L

L

M

M

L

L

YYY

-1

-1

1

1

-1

-1

-1

1

1

1

1

1

1

1

-1

X^{(1)}

1 1 1 1 1 2 2 2 2 2 3 3 3 3 3

X^{(2)}

S M M S S S M M L L L M M L L

Y

-1 -1 1 1 -1 -1 -1 1 1 1 1 1 1 1 -1

: 先验概率

P(Y=1)=\frac {9+1}{15+2}=\frac{10}{17},P(Y=-1)=\frac {6+1}{15+2}=\frac{7}{17}

条件概率

P(X^{(1)}=1|Y=1)= \frac{2+1}{9+3}=\frac{3}{12},P(X^{(1)}=2|Y=1)= \frac{3+1}{9+3}=\frac{4}{12},P(X^{(1)}=3|Y=1)= \frac{4+1}{9+3}=\frac{5}{12}
P(X^{(2)}=S|Y=1)= \frac{1+1}{9+3}=\frac{2}{12},P(X^{(2)}=M|Y=1)= \frac{4+1}{9+3}=\frac{5}{12},P(X^{(2)}=L|Y=1)= \frac{4+1}{9+3}=\frac{5}{12}
P(X^{(1)}=1|Y=-1)= \frac{3+1}{6+3}=\frac{4}{9},P(X^{(1)}=2|Y=-1)= \frac{2+1}{6+3}=\frac{3}{9},P(X^{(1)}=3|Y=-1)= \frac{1+1}{6+3}=\frac{2}{9}
P(X^{(2)}=S|Y=-1)= \frac{3+1}{6+3}=\frac{4}{9},P(X^{(2)}=M|Y=-1)= \frac{2+1}{6+3}=\frac{3}{9},P(X^{(2)}=L|Y=-1)= \frac{1+1}{6+3}=\frac{2}{9}

对给定的

x=(2,S)^T

计算:

Y=1

时:

\quad \quad\ \quad P(Y=1)P(X^{(1)}=2|Y=1)P(X^{(2)}=S|Y=1)=\frac{10}{17} * \frac{4}{12} * \frac{2}{12} = \frac{5}{153}=0.0327
Y=-1

时:

\quad \quad\ \quad P(Y=-1)P(X^{(1)}=2|Y=-1)P(X^{(2)}=S|Y=-1)=\frac{7}{17} * \frac{3}{9} * \frac{4}{9} = \frac{28}{459}=0.0610
Y=-1

时的概率最大,所以

y=-1

2.3.2 例题代码
代码语言:javascript
复制
# -*- coding:utf-8 -*-
# Python 3.7
# @Time: 2020/1/19 22:08
# @Author: Michael Ming
# @Website: https://michael.blog.csdn.net/
# @File: naiveBayes.py

import numpy as np

data = [[1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3],
        ['S', 'M', 'M', 'S', 'S', 'S', 'M', 'M', 'L', 'L', 'L', 'M', 'M', 'L', 'L'],
        [-1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1]]
X1 = []
X2 = []
Y = []
for i in range(len(data[0])):  # 统计数据种类
    if data[0][i] not in X1:
        X1.append(data[0][i])
    if data[1][i] not in X2:
        X2.append(data[1][i])
    if data[2][i] not in Y:
        Y.append(data[2][i])
nY = [0] * len(Y)
for i in range(len(data[0])):  # 统计Yi的数量
    nY[Y.index(data[2][i])] += 1
PY = [0.0] * len(Y)
for i in range(len(Y)):
    PY[i] = (nY[i]+1) / (len(data[0])+len(Y)) # Yi的概率,+1为平滑
PX1_Y = np.zeros((len(X1), len(Y)))  # 条件概率
PX2_Y = np.zeros((len(X2), len(Y)))

for i in range(len(data[0])):
    PX1_Y[X1.index(data[0][i])][Y.index(data[2][i])] += 1  # 统计频数
    PX2_Y[X2.index(data[1][i])][Y.index(data[2][i])] += 1
for i in range(len(Y)):
    PX1_Y[:, i] = (PX1_Y[:, i] + 1)/(nY[i]+len(X1))  # 转成条件概率,带平滑
    PX2_Y[:, i] = (PX2_Y[:, i] + 1)/(nY[i]+len(X2))
x = [2, 'S']
PX_Y = [PX1_Y, PX2_Y]
X = [X1, X2]
ProbY = [0.0] * len(Y)
for i in range(len(Y)):
    ProbY[i] = PY[i]
    for j in range(len(x)):
        ProbY[i] *= PX_Y[j][X[j].index(x[j])][i]
maxProb = -1
idx = -1
for i in range(len(Y)):  # 取最大的概率
    if ProbY[i] > maxProb:
        maxProb = ProbY[i]
        idx = i
print(Y)
print(ProbY)
print(x, ", 最有可能对应的贝叶斯估计 y = %d" % (Y[idx]))
代码语言:javascript
复制
# 运行结果
[-1, 1]
[0.06100217864923746, 0.0326797385620915]
[2, 'S'] , 最有可能对应的贝叶斯估计 y = -1

3. 自编程实现NB

特征的概率分布假设为高斯分布

概率密度函数:

P(x_i | y_k)=\frac{1}{\sqrt{2\pi\sigma^2_{y_k}}}exp(-\frac{(x_i-\mu_{y_k})^2}{2\sigma^2_{y_k}})

数学期望(mean):

\mu

,方差:

\sigma^2=\frac{\sum(X-\mu)^2}{N}

抄自:https://github.com/fengdu78/lihang-code,并修复其中一个Bug

代码语言:javascript
复制
import math

class GausNB():
    def __init__(self):
        self.model = None

    @staticmethod
    def mean(X):  # 均值
        return sum(X) / float(len(X))

    def std(self, X):  # 标准差
        avg = self.mean(X)
        return np.sqrt(sum([pow(x - avg, 2) for x in X]) / float(len(X)))

    def gaus_prob(self, x, mean, std):  # 高斯概率密度
        exponent = math.exp(-(math.pow(x - mean, 2) / (2 * math.pow(std, 2))))
        return (1 / (math.sqrt(2 * math.pi) * std)) * exponent

    def summarize(self, train_data):
        summaries = [(self.mean(i), self.std(i)) for i in zip(*train_data)]
        return summaries  # 返回 [(各特征的均值,标准差),(),()...]]

    def fit(self, X, y):
        labels = list(set(y))
        data = {label: [] for label in labels}
        for x, label in zip(X, y):
            data[label].append(x)
        self.model = {
            label: [len(data[label]) / float(len(X)), self.summarize(value)]
            for label, value in data.items()
        }  # model写入字典 label : [[label概率],[(各特征的均值,标准差),(),()...]]
        return 'GuassNB train Done !'

    def cal_prob(self, input_data):
        prob = {}
        for label, value in self.model.items():
            prob[label] = value[0]  # P(Y=Ck), 此处修正了原作者的初始概率均等问题
            for i in range(len(value[1])):
                mean, std = value[1][i]
                prob[label] *= self.gaus_prob(input_data[i], mean, std)
                # 分类器概率公式
        return prob

    def predict(self, X_test):
        label = sorted(self.cal_prob(X_test).items(), key=lambda x: x[-1])[-1][0]
        # {label : prob},按照概率排序,取最后(最大)的【0】标签
        return label

    def predict_prob(self, X_test):
        prob = sorted(self.cal_prob(X_test).items(), key=lambda x: x[-1])[-1][1]
        s = sum(i for i in self.cal_prob(X_test).values())
        return prob / s  # 预测概率

    def score(self, X_test, y_test):
        right = 0
        for X, y in zip(X_test, y_test):
            label = self.predict(X)
            if label == y:
                right += 1
        return right / float(len(X_test))


clf = GausNB()
clf.fit(X_train, y_train)
x = [2, ord('S')]
print(x, "自编程高斯贝叶斯预测", clf.predict(x), clf.predict_prob(x))
代码语言:javascript
复制
[2, 83] 自编程高斯贝叶斯预测 -1 0.9221912681158962

4. sklearn.naive_bayes

代码语言:javascript
复制
import pandas as pd
from sklearn.naive_bayes import GaussianNB
from sklearn.naive_bayes import BernoulliNB
from sklearn.naive_bayes import MultinomialNB

for i in range(len(data[0])):
    data[1][i] = ord(data[1][i])  # 将字符转成ASCII数字
data = np.array(pd.DataFrame(data).T)
X_train, y_train = data[:, :-1], data[:, -1]

clf = GaussianNB()
clf.fit(X_train, y_train)
print(x, "的高斯贝叶斯预测是", clf.predict([[2, ord('S')]]), clf.predict_proba([[2, ord('S')]]))

clf = BernoulliNB()
clf.fit(X_train, y_train)
print(x, "的伯努利贝叶斯预测是", clf.predict([[2, ord('S')]]), clf.predict_proba([[2, ord('S')]]))

clf = MultinomialNB()
clf.fit(X_train, y_train)
print(x, "的多项式贝叶斯预测是", clf.predict([[2, ord('S')]]), clf.predict_proba([[2, ord('S')]]))
代码语言:javascript
复制
[2, 'S'] 的高斯贝叶斯预测是 [-1] [[0.92219127 0.07780873]]
[2, 'S'] 的伯努利贝叶斯预测是 [1] [[0.38180179 0.61819821]]
[2, 'S'] 的多项式贝叶斯预测是 [1] [[0.41221915 0.58778085]]
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-01-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 朴素贝叶斯法的学习与分类
    • 1.1 基本方法
    • 2. 参数估计
      • 2.1 极大似然估计
        • 2.2 学习与分类算法
          • 2.2.1 例题
          • 2.2.2 例题代码
        • 2.3 贝叶斯估计(平滑)
          • 2.3.1 例题
          • 2.3.2 例题代码
      • 3. 自编程实现NB
      • 4. sklearn.naive_bayes
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档