【朴素贝叶斯】Part2——Python实现朴素贝叶斯算法

朴素贝叶斯

朴素贝叶斯是基于贝叶斯定理与特征条件独立假设的分类方法

三种朴素贝叶斯模型:

(1)高斯模型: P ( X j = x j ∣ Y = C k ) = 1 2 π σ k 2 e x p ( − ( x j − μ k ) 2 2 σ k 2 ) P(X_j=x_j | Y=C_k)=\frac{1}{\sqrt{2\pi}\sigma^2_{k}}exp(-\frac{(x_j-\mu_{k})^2}{2\sigma^2_{k}}) P(Xj=xjY=Ck)=2π σk21exp(2σk2(xjμk)2)

(2)多项式模型: P ( X j = x j l ∣ Y = C k ) = x j l + λ m k + n λ P(X_j=x_{jl}|Y=C_k) = \frac{x_{jl} + \lambda}{m_k + n\lambda} P(Xj=xjlY=Ck)=mk+nλxjl+λ

(3)伯努利模型: P ( X j = x j l ∣ Y = C k ) = P ( j ∣ Y = C k ) x j l + ( 1 − P ( j ∣ Y = C k ) ( 1 − x j l ) P(X_j=x_{jl}|Y=C_k) = P(j|Y=C_k)x_{jl} + (1 - P(j|Y=C_k)(1-x_{jl}) P(Xj=xjlY=Ck)=P(jY=Ck)xjl+(1P(jY=Ck)(1xjl)

1. 数据准备

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

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

from collections import Counter
import math
# 加载数据集
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, :])
    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)

# 查看数据
X.ndim, X.shape, y.ndim, y.shape
X[1:5]
y[1:5]
X_train[1:5]
y_train[1:5]
list(set(y_train))
(2, (100, 4), 1, (100,))

array([[4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
       [5. , 3.6, 1.4, 0.2]])
       
array([0., 0., 0., 0.])

array([[5.1, 3.8, 1.6, 0.2],
       [5.8, 4. , 1.2, 0.2],
       [4.8, 3.4, 1.6, 0.2],
       [5.6, 3. , 4.1, 1.3]])

array([0., 0., 0., 1.])

[0.0, 1.0]

2. GaussianNB in Python

特征的可能性被假设为高斯

概率密度函数: P ( x i ∣ y k ) = 1 2 π σ y k 2 e x p ( − ( x i − μ y k ) 2 2 σ y k 2 ) P(x_i | y_k)=\frac{1}{\sqrt{2\pi}\sigma^2_{yk}}exp(-\frac{(x_i-\mu_{yk})^2}{2\sigma^2_{yk}}) P(xiyk)=2π σyk21exp(2σyk2(xiμyk)2)

数学期望(mean): μ = ∑ i = 1 N x i N \mu=\frac{\sum_{i=1}^{N}x_{i}}{N} μ=Ni=1Nxi

方差: σ 2 = ∑ i = 1 N ( x i − x ‾ ) 2 N \sigma^2=\frac{\sum_{i=1}^{N}(x_{i}-\overline{x})^2}{N} σ2=Ni=1N(xix)2

标准差: σ = 1 N ∑ i = 1 N ( x i − x ‾ ) 2 \sigma =\sqrt{\frac{1}{N}\sum_{i=1}^{N}(x_{i}-\overline{x})^2} σ=N1i=1N(xix)2

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)]
        # zip(*zipped)可理解为解压,返回二维矩阵式,这里返回每个特征的集合列表
        # zipped = [(1, 4), (2, 5), (3, 6)],zip(*zipped)=[(1, 2, 3), (4, 5, 6)]
        return summaries

    # 分类别求出数学期望和标准差
    def fit(self, X, y):
        labels = list(set(y))  # set() 函数创建一个无序不重复元素集
        data = {label: [] for label in labels}  # 根据类别创建一个空列表
        for f, label in zip(X, y):
            # zip() 函数将特征和类别对应的元素打包成一个个元组,然后返回由这些元组组成的列表
            # a = [[5.1, 3.8, 1.6, 0.2],[5.8, 4. , 1.2, 0.2]],b = [0.0, 0.0]
            # zip(a,b) = [([5.1, 3.8, 1.6, 0.2], 0.0),([5.8, 4. , 1.2, 0.2], 0.0)]
            data[label].append(f)
        self.model = {
            label: self.summarize(value)
            for label, value in data.items()
            # data.items()以列表返回可遍历的(类别, value) 元组数组
        }
        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]))
model.score(X_test, y_test)
'gaussianNB train done!'

0.0

1.0

3. GaussianNB in Sklearn

sklearn.naive_bayes

from sklearn.naive_bayes import GaussianNB, BernoulliNB, MultinomialNB  
# 高斯模型/伯努利模型/多项式模型
clf = GaussianNB()
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
clf.predict([[4.4,  3.2,  1.3,  0.2]])

GaussianNB(priors=None)

1.0

array([0.])

4. 朴素贝叶斯Sklearn库类

        在scikit-learn中,一共有3个朴素贝叶斯的分类算法,分别是:

  • GaussianNB: 是先验为高斯分布的朴素贝叶斯,适用于样本特征的分布大部分是连续值的数据;
  • MultinomialNB: 是先验为多项式分布的朴素贝叶斯,适用于样本特征的分布大部分是多元离散值的数据;
  • BernoulliNB: 是先验为伯努利分布的朴素贝叶斯,适用于样本特征是二元离散值或者很稀疏的多元离散值;

(1)GaussianNB类:

  • priors:先验概率,对应Y的各个类别的先验概率P(Y=Ck), 这个值默认不给出,如果不给出此时P(Y=Ck)=mk/m;
  • fit( )
  • 预测函数:
    predict( ),直接给出测试集的预测类别输出
    predict_log_proba( ),会给出测试集样本在各个类别上预测的概率
    predict_proba( ),会给出测试集样本在各个类别上预测的概率的一个对数转化

(2)MultinomialNB类:

  • alpha:常数λ,默认为1,如果发现拟合的不好,可以选择稍大于1或者稍小于1的数;
  • fit_prior:布尔参数,表示是否要考虑先验概率,如果是false,则所有的样本类别输出都有相同的类别先验概率,否则可以自己用第三个参数;
  • class_prior:输入先验概率,或者不输入第三个参数让MultinomialNB从训练集样本来计算先验概率;
  • fit方法、预测方法与GaussianNB完全一样;

(3)BernoulliNB类:

  • alpha:常数λ,默认为1,如果发现拟合的不好,可以选择稍大于1或者稍小于1的数;
  • fit_prior:布尔参数,表示是否要考虑先验概率,如果是false,则所有的样本类别输出都有相同的类别先验概率,否则可以自己用第三个参数;
  • class_prior:输入先验概率,或者不输入第三个参数让MultinomialNB从训练集样本来计算先验概率;
  • binarize,可以是数值或者不输入。如果不输入,则BernoulliNB认为每个数据特征都已经是二元的。否则的话,小于binarize的会归为一类,大于binarize的会归为另外一类;
  • fit方法、预测方法与GaussianNB完全一样;

4. 应用实例

后续补充介绍…

参考资料:
李航《统计学习方法》
代码部分转自“机器学习初学者”作者内容

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值