一、相关术语

监督学习方法可以分成生成方法和判别方法,所学到的模型分别为生成模型和判别模型

1、生成方法

生成方法学习的是联合概率分布P(X,Y)P(X,Y)P(X,Y),然后根据条件概率公式计算P(Y∣X)P(Y|X)P(Y∣X)作为预测的模型,即生成模型。

P(Y∣X)=P(X,Y)P(X)P(Y|X) = \frac{P(X,Y)}{P(X)}P(Y∣X)=P(X)P(X,Y)​

2、判别方法

判别方法直接学习决策函数f(X)f(X)f(X)或者条件概率分布P(Y∣X)P(Y|X)P(Y∣X)作为预测的模型,即判别模型

3、先验概率

  • 事件发生前的预判概率
  • 可以是基于历史数据的统计,可以由背景常识得出

4、条件概率(似然概率)

  • 一个事件发生后另一事件发生的概率
  • 一般的形式为P(X∣Y)P(X|Y)P(X∣Y),表示yyy发生的条件下xxx发生的概率
  • 有时为了区分一般意义上的条件概率,也称似然概率

5、后验概率

  • 基于先验概率求得的反向条件概率,形式上与条件概率相同
  • 若P(X∣Y)P(X|Y)P(X∣Y)为正向,则P(Y∣X)P(Y|X)P(Y∣X)为反向

6、极大似然估计

  • 利用已知的样本结果信息,反推最具有(最大概率)可能导致这些样本结果出现的模型参数
  • 极大似然函数中采样需满足一个重要的假设,就是所有的采样都是独立同分布的。

7、贝叶斯定理

P(Bi∣A)=P(Bi)P(A∣Bi)∑j=1nP(Bj)P(A∣Bj)P(B_i|A)=\frac{P(B_i)P(A|B_i)}{\sum^{n}_{j=1}P(B_j)P(A|B_j)}P(Bi​∣A)=∑j=1n​P(Bj​)P(A∣Bj​)P(Bi​)P(A∣Bi​)​

二、朴素贝叶斯法

基于贝叶斯定理与**特征条件独立假设(基本假设)**的分类方法,对于给定的训练数据集,首先基于特征条件独立假设学习输入输出的联合概率分布P(X,Y)P(X,Y)P(X,Y),然后基于此模型,对给定的输入xxx利用贝叶斯定理求出后验概率P(Y∣X)P(Y|X)P(Y∣X)最大的输出yyy。

具体步骤如下:

step1:学习先验概率分布、条件概率分布

P(Y=ck),k=1,2,...,K(1)P(Y=c_k),k=1,2,...,K \tag{1}P(Y=ck​),k=1,2,...,K(1)

P(X=x∣Y=ck)=P(X(1)=x(1),...,X(n)=x(n)∣Y=ck),k=1,2...K(2)P(X=x|Y=c_k)=P(X^{(1)}=x^{(1)},...,X^{(n)}=x^{(n)}|Y=c_k),k=1,2...K \tag{2}P(X=x∣Y=ck​)=P(X(1)=x(1),...,X(n)=x(n)∣Y=ck​),k=1,2...K(2)

其中,根据条件独立假设:

P(X=x∣Y=ck)=P(X(1),...,X(n)∣Y=ck)=∏j=1nP(X(j)=x(j)∣Y=ck)P(X=x|Y=c_k)=P(X^{(1)},...,X^{(n)}|Y=c_k) =\prod^n_{j=1}P(X^{(j)}=x^{(j)}|Y=c_k)P(X=x∣Y=ck​)=P(X(1),...,X(n)∣Y=ck​)=j=1∏n​P(X(j)=x(j)∣Y=ck​)

概率估计方法可以是极大似然估计或贝叶斯估计。

  • 极大似然估计

    P(Y=ck)=∑i=1NI(yi=ck)N,k=1,2,...,KP(Y=c_k)=\frac{\sum^{N}_{i=1}I(y_i=c_k)}{N},k=1,2,...,KP(Y=ck​)=N∑i=1N​I(yi​=ck​)​,k=1,2,...,K

    P(X(j)=ajl∣Y=ck)=∑i=1NI(xi(j)=ajl,yi=ck)∑i=1NI(yi=ck)j=1,2,...,n;l=1,2,...,Sj;k=1,2,...,KP(X^{(j)}=a_{jl}|Y=c_k)=\frac{\sum^{N}_{i=1}I(x^{(j)}_i=a_{jl},y_i=c_k)}{\sum^{N}_{i=1}I(y_i=c_k)} \\j=1,2,...,n;l=1,2,...,S_j;k=1,2,...,KP(X(j)=ajl​∣Y=ck​)=∑i=1N​I(yi​=ck​)∑i=1N​I(xi(j)​=ajl​,yi​=ck​)​j=1,2,...,n;l=1,2,...,Sj​;k=1,2,...,K

  • 贝叶斯估计(Bayesian estimation)

    P(Y=ck)=∑i=1NI(yi=ck)+λN+Kλ,k=1,2,...,KP(Y=c_k)=\frac{\sum^{N}_{i=1}I(y_i=c_k)+\lambda}{N+K\lambda},k=1,2,...,KP(Y=ck​)=N+Kλ∑i=1N​I(yi​=ck​)+λ​,k=1,2,...,K

    P(X(j)=ajl∣Y=ck)=∑i=1NI(xi(j)=ajl,yi=ck)+λ∑i=1NI(yi=ck)+Sjλj=1,2,...,n;l=1,2,...,Sj;k=1,2,...,KP(X^{(j)}=a_{jl}|Y=c_k)=\frac{\sum^{N}_{i=1}I(x^{(j)}_i=a_{jl},y_i=c_k)+\lambda}{\sum^{N}_{i=1}I(y_i=c_k)+S_j\lambda} \\j=1,2,...,n;l=1,2,...,S_j;k=1,2,...,KP(X(j)=ajl​∣Y=ck​)=∑i=1N​I(yi​=ck​)+Sj​λ∑i=1N​I(xi(j)​=ajl​,yi​=ck​)+λ​j=1,2,...,n;l=1,2,...,Sj​;k=1,2,...,K

    其中,取λ=0\lambda=0λ=0时,就是极大似然估计,取λ=1\lambda=1λ=1时,称为拉普拉斯平滑(Laplacian smoothing)

step2: 计算后验概率

对于给定的实例x=(x(1),x(2),...,x(j))Tx=(x^{(1)},x^{(2)},...,x^{(j)})^Tx=(x(1),x(2),...,x(j))T,计算

P(Y=ck)∏j=1nP(X(j)=x(j)∣Y=ck),k=1,2,...,KP(Y=c_k)\prod^n_{j=1}P(X^{(j)}=x^{(j)}|Y=c_k),k=1,2,...,KP(Y=ck​)j=1∏n​P(X(j)=x(j)∣Y=ck​),k=1,2,...,K

**为什么计算这个呢?**其实这个式子就是根据贝叶斯定理求得的后验概率P(Y=ck∣X=x)P(Y=c_k|X=x)P(Y=ck​∣X=x)化简后的代表式子。具体推导见书本P60.

step3:确定实例xxx的类

y=arg⁡max⁡ckP(Y=ck)∏j=1nP(Xj=x(j)∣Y=ck)y=\arg \max _{c_{k}} P\left(Y=c_{k}\right) \prod_{j=1}^{n} P\left(X_{j}=x^{(j)} | Y=c_{k}\right)y=argck​max​P(Y=ck​)j=1∏n​P(Xj​=x(j)∣Y=ck​)

即哪个后验概率最大,就把实例xxx认为是它那一类。

三、朴素贝叶斯的数学道理

看到上面的朴素贝叶斯算法过程,想必大家都会有一个疑问:为什么从先验概率算到后验概率,后验概率最大的类就是我们要的结果?

对于感知机来说,我们证明了算法的收敛性,即肯定能在有限次数达到最优解。这里有点不太一样,我们从先验概率到后验概率的计算都是固定步骤,不涉及是否收敛,只需要说明后验概率得到的结果是我们要的结果,而对于一个学习过程的最终需求来说,我们在保证算法可以执行的情况下,需要的结果是让损失达到最低,即风险函数最小化。所以只需要证明将实例分到后验概率最大的类等价于期望风险最小化。

假设选择0-1损失函数:

L(Y,f(X))={1,Y≠f(X) 0,Y=f(X)L(Y,f(X))=\left\{\begin{matrix}1,Y\neq f(X)\\ 0,Y=f(X)\end{matrix}\right.L(Y,f(X))={1,Y​=f(X) 0,Y=f(X)​

式中f(X)f(X)f(X)是分类决策函数。这时,期望风险函数为

Rexp(f)=E[L(Y,f(X))]R_{exp}(f)=E[L(Y,f(X))]Rexp​(f)=E[L(Y,f(X))]

期望是对联合分布P(X,Y)P(X,Y)P(X,Y)取的。由此条件期望

Rexp(f)=Ex∑k=1K[L(ck,f(X))]P(ck∣X)R_{exp}(f)=Ex\sum_{k=1}^{K}[L(c_k,f(X))]P(c_k|X)Rexp​(f)=Exk=1∑K​[L(ck​,f(X))]P(ck​∣X)

为了使期望风险最小化,只需对X=xX=xX=x逐个极小化,由此得到:

f(x)=argmin⁡y∈Y∑k=1KL(ck,y)P(ck∣X=x)=argmin⁡y∈Y∑k=1KP(y≠ck∣X=x)=argmin⁡y∈Y(1−P(y=ck∣X=x))=argmin⁡y∈YP(y=ck∣X=x)\begin{aligned} f(x) &=arg \min \limits_{y \in {Y}}\sum_{k=1}^{K}L(c_k,y)P(c_k|X=x)\\ &=arg \min \limits_{y \in {Y}}\sum_{k=1}^{K}P(y \neq c_k|X=x) \\&=arg \min \limits_{y \in {Y}}(1-P(y=c_k|X=x)) \\&=arg \min \limits_{y \in {Y}}P(y=c_k|X=x) \end{aligned} f(x)​=argy∈Ymin​k=1∑K​L(ck​,y)P(ck​∣X=x)=argy∈Ymin​k=1∑K​P(y​=ck​∣X=x)=argy∈Ymin​(1−P(y=ck​∣X=x))=argy∈Ymin​P(y=ck​∣X=x)​

这样一来,根据期望风险最小化准则就得到了后验概率最大化准则:

f(x)=arg⁡max⁡ckP(ck∣X=x)f(x)=\arg \max _{c_{k}} P(c_k|X=x)f(x)=argck​max​P(ck​∣X=x)

即朴素贝叶斯法所采用的原理。

四、NaiveBayes代码实例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

from collections import Counter
import math

# data
def create_data():
    iris = load_iris()
    df = pd.DataFrame(iris.data, columns=iris.feature_names)
    df['label'] = iris.target
    df.columns = [
        'sepal length', 'sepal width', 'petal length', 'petal width', 'label'
    ]
    data = np.array(df.iloc[:100, :])
    # print(data)
    return data[:, :-1], data[:, -1]

X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
print(X_train,X_test,y_train, y_test)

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

    # 数学期望
    @staticmethod
    def mean(X):
        return sum(X) / float(len(X))

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

    # 概率密度函数
    def gaussian_probability(self, x, mean, stdev):
        exponent = math.exp(-(math.pow(x - mean, 2) /
                              (2 * math.pow(stdev, 2))))
        return (1 / (math.sqrt(2 * math.pi) * stdev)) * exponent

    # 处理X_train
    def summarize(self, train_data):
        summaries = [(self.mean(i), self.stdev(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 f, label in zip(X, y):
            data[label].append(f)
        self.model = {
            label: self.summarize(value)
            for label, value in data.items()
        }
        return 'gaussianNB train done!'

    # 计算概率
    def calculate_probabilities(self, input_data):
        # summaries:{0.0: [(5.0, 0.37),(3.42, 0.40)], 1.0: [(5.8, 0.449),(2.7, 0.27)]}
        # input_data:[1.1, 2.2]
        probabilities = {}
        for label, value in self.model.items():
            probabilities[label] = 1
            for i in range(len(value)):
                mean, stdev = value[i]
                probabilities[label] *= self.gaussian_probability(
                    input_data[i], mean, stdev)
        return probabilities

    # 类别
    def predict(self, X_test):
        # {0.0: 2.9680340789325763e-27, 1.0: 3.5749783019849535e-26}
        label = sorted(
            self.calculate_probabilities(X_test).items(),
            key=lambda x: x[-1])[-1][0]
        return label

    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))

model = NaiveBayes()

model.fit(X_train, y_train)

print("预测结果:",model.predict([4.4,  3.2,  1.3,  0.2]))

score = model.score(X_test, y_test)

print("得分:",score)
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐