利用贝叶斯分类器进行分类求概率-朴素贝叶斯算法

贝叶斯分类器是一类基于​​贝叶斯定理​​的概率分类模型,其核心思想是通过先验概率和样本数据计算后验概率,从而对未知数据进行分类。

​1. 基本概念​

其中:

Y:类别标签(如垃圾邮件/非垃圾邮件)。X:特征向量(如文本中的单词)。P(Y∣X):给定特征 X 时类别 Y 的后验概率。P(X∣Y):似然(类别 Y 下特征 X 的条件概率)。P(Y):类别的先验概率朴素”假设​​:所有特征在给定类别下条件独立,即:


​2. 算法步骤​

​(1) 数据准备

输入:带标签的训练数据,特征 X=(x1​,x2​,...,xn​),类别 Y。特征处理:​​离散特征​​:直接统计概率(如单词出现次数)。连续特征​​:假设服从高斯分布,计算均值和方差(高斯朴素贝叶斯)。

​(2) 计算先验概率 P(Y)​

统计每个类别在训练集中的比例:P(Y=yk​)=总样本数类别 yk​ 的样本数​

​(3) 计算似然 P(xi​∣Y)​

​(4) 预测新样本​

​训练过程​

  1. ​计算先验概率​​:统计训练集中每个类别的频率。P(Y=yi​)=总样本数类别 yi​ 的样本数​
  2. ​估计似然​​:
    • 对离散特征:计算类别下特征值的条件概率。
    • 对连续特征:拟合概率分布(如高斯分布的均值和方差)

数学示例​

假设预测天气(Y∈{晴,雨})基于两个特征:温度(高/低)和湿度(高/低)。
训练数据统计如下:

先验概率:P(晴)=0.6,P(雨)=0.4。条件概率P(温度=高∣晴)=0.8,P(湿度=高∣晴)=0.1。P(温度=高∣雨)=0.3,P(湿度=高∣雨)=0.9。

对新样本 X=(温度=高,湿度=高):

P(晴∣X)∝0.6×0.8×0.1=0.048P(雨∣X)∝0.4×0.3×0.9=0.108

预测结果为 ​​雨​​(后验概率更高)

案例分析:

编号色泽根蒂敲声纹理脐部触感密度含糖率好瓜
1青绿蜷缩浊响清晰凹陷硬滑0.6970.460
2乌黑蜷缩沉闷清晰凹陷硬滑0.7740.376
3乌黑蜷缩浊响清晰凹陷硬滑0.6340.264
4青绿蜷缩沉闷清晰凹陷硬滑0.6080.318
5浅白蜷缩浊响清晰凹陷硬滑0.5560.215
6青绿稍蜷浊响清晰稍凹软粘0.4030.237
7乌黑稍蜷浊响稍糊稍凹软粘0.4810.149
8乌黑稍蜷浊响清晰稍凹硬滑0.4370.211
9乌黑稍老沉闷稍糊稍凹硬滑0.6660.091
10青绿硬挺清脆清晰平坦软粘0.2430.267
11浅白硬挺清脆模糊平坦硬滑0.2450.057
12浅白蜷缩浊响模糊平坦软粘0.3430.099
13青绿稍蜷浊响稍糊凹陷硬滑0.6390.161
14浅白稍蜷沉闷稍糊凹陷硬滑0.6570.198
15乌黑稍蜷浊响清晰稍凹软粘0.3600.370
16浅白蜷缩浊响模糊平坦硬滑0.5930.042
17青绿硬挺沉闷稍糊稍凹硬滑0.7190.103

首先,计算类别的先验概率。好瓜是8/17 =0.471 坏瓜是 9/18=0.529

对于离散特征(如色泽、根蒂、敲声等),计算在类别 YY 下特征 XX 取某个值 xx 的条件概率:

P(X=x∣Y=yi)=类别 yi 中特征 X 取值为 x 的样本数类别 yi 的总样本数P(X=x∣Y=yi​)=类别 yi​ 的总样本数类别 yi​ 中特征 X 取值为 x 的样本数​

以 色泽 为例:

色泽取值:青绿、乌黑、浅白

P(色泽=青绿∣Y=是)=83​=0.375P(色泽=乌黑∣Y=是)=48=0.5P(色泽=乌黑∣Y=是)=84​=0.5P(色泽=浅白∣Y=是)=18=0.125P(色泽=浅白∣Y=是)=81​=0.125

P(色泽=青绿∣Y=否)=93​≈0.333P(色泽=乌黑∣Y=否)=29≈0.222P(色泽=乌黑∣Y=否)=92​≈0.222P(色泽=浅白∣Y=否)=49≈0.444P(色泽=浅白∣Y=否)=94​≈0.444

密度(密度)

在“好瓜”(是)中:
密度值:0.697, 0.774, 0.634, 0.608, 0.556, 0.403, 0.481, 0.437

μ密度​=≈0.574

σ密度2​=≈0.016

在“非好瓜”(否)中:μ密度​≈0.496σ密度2≈0.033σ密度2​≈0.033

在“好瓜”(是)中:
含糖率:0.460, 0.376, 0.264, 0.318, 0.215, 0.237, 0.149, 0.211
计算:

μ含糖率≈0.279μ含糖率​≈0.279σ含糖率2≈0.008σ含糖率2​≈0.008

在“非好瓜”(否)中:
含糖率:0.091, 0.267, 0.057, 0.099, 0.161, 0.198, 0.370, 0.042, 0.103
计算:

μ含糖率≈0.154μ含糖率​≈0.154σ含糖率2≈0.009σ含糖率2​≈0.009

特征特征值好瓜=是 (计数/总数)好瓜=否 (计数/总数)
色泽青绿3/83/9
乌黑3/84/9
浅白2/82/9
根蒂蜷缩5/82/9
稍蜷3/85/9
稍老0/82/9
敲声浊响6/85/9
沉闷2/83/9
清脆0/81/9
纹理清晰6/82/9
稍糊2/86/9
模糊0/81/9
脐部凹陷5/82/9
稍凹3/85/9
平坦0/82/9
触感硬滑5/85/9
软粘3/84/9

样本1的预测结果: 是      准确率: 82.35%

import numpy as np
import pandas as pd
from collections import defaultdict


class NaiveBayesClassifier:
    def __init__(self):
        self.class_probs = {}
        self.feature_probs = {}
        self.discrete_features = []  # 存储离散特征名
        self.continuous_features = []  # 存储连续特征名

    def fit(self, X, y):
        # 自动识别特征类型
        self.discrete_features = [col for col in X.columns if X[col].dtype == 'object']
        self.continuous_features = [col for col in X.columns if X[col].dtype != 'object']

        # 计算类别的先验概率
        classes, counts = np.unique(y, return_counts=True)
        total_samples = len(y)
        self.class_probs = {c: (count + 1) / (total_samples + len(classes)) for c, count in
                            zip(classes, counts)}  # 拉普拉斯平滑

        # 对每个类别计算特征的条件概率
        for c in self.class_probs:
            class_samples = X[y == c]
            feature_prob = {}

            # 处理离散特征
            for feature in self.discrete_features:
                value_counts = class_samples[feature].value_counts()
                # 拉普拉斯平滑
                prob_dict = {val: (count + 1) / (len(class_samples) + len(value_counts))
                             for val, count in value_counts.items()}
                feature_prob[feature] = prob_dict

            # 处理连续特征
            for feature in self.continuous_features:
                mean = class_samples[feature].mean()
                std = class_samples[feature].std()
                # 防止标准差为0
                if std < 1e-6:
                    std = 1e-6
                feature_prob[feature] = {'mean': mean, 'std': std}

            self.feature_probs[c] = feature_prob

    def _calculate_likelihood(self, feature, value, class_label):
        # 离散特征
        if feature in self.discrete_features:
            prob_dict = self.feature_probs[class_label].get(feature, {})
            # 如果值未见过,使用最小概率
            return prob_dict.get(value, 1 / (len(prob_dict) + 1)) if prob_dict else 1e-6
        # 连续特征
        else:
            params = self.feature_probs[class_label].get(feature, {'mean': 0, 'std': 1})
            mean = params['mean']
            std = params['std']
            if std < 1e-6:
                std = 1e-6
            exponent = np.exp(-0.5 * ((value - mean) / std) ** 2)
            return (1.0 / (np.sqrt(2 * np.pi) * std)) * exponent

    def predict(self, X):
        predictions = []
        for _, sample in X.iterrows():
            max_prob = -np.inf
            best_class = None

            for class_label in self.class_probs:
                # 使用对数概率防止下溢
                prob = np.log(self.class_probs[class_label])

                for feature in X.columns:
                    value = sample[feature]
                    likelihood = self._calculate_likelihood(feature, value, class_label)
                    prob += np.log(likelihood + 1e-10)  # 防止log(0)

                if prob > max_prob:
                    max_prob = prob
                    best_class = class_label

            predictions.append(best_class)

        return predictions

    def evaluate(self, X, y):
        predictions = self.predict(X)
        accuracy = np.mean(np.array(predictions) == np.array(y))
        return accuracy


# 准备数据
data = {
    '编号': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
    '色泽': ['青绿', '乌黑', '乌黑', '青绿', '浅白', '青绿', '乌黑', '乌黑', '乌黑', '青绿', '浅白', '浅白', '青绿', '浅白', '乌黑', '浅白', '青绿'],
    '根蒂': ['蜷缩', '蜷缩', '蜷缩', '蜷缩', '蜷缩', '稍蜷', '稍蜷', '稍蜷', '稍老', '硬挺', '硬挺', '蜷缩', '稍蜷', '稍蜷', '稍蜷', '蜷缩', '硬挺'],
    '敲声': ['浊响', '沉闷', '浊响', '沉闷', '浊响', '浊响', '浊响', '浊响', '沉闷', '清脆', '清脆', '浊响', '浊响', '沉闷', '浊响', '浊响', '沉闷'],
    '纹理': ['清晰', '清晰', '清晰', '清晰', '清晰', '清晰', '稍糊', '清晰', '稍糊', '清晰', '模糊', '模糊', '稍糊', '稍糊', '清晰', '模糊', '稍糊'],
    '脐部': ['凹陷', '凹陷', '凹陷', '凹陷', '凹陷', '稍凹', '稍凹', '稍凹', '稍凹', '平坦', '平坦', '平坦', '凹陷', '凹陷', '稍凹', '平坦', '稍凹'],
    '触感': ['硬滑', '硬滑', '硬滑', '硬滑', '硬滑', '软粘', '软粘', '硬滑', '硬滑', '软粘', '硬滑', '软粘', '硬滑', '硬滑', '软粘', '硬滑', '硬滑'],
    '密度': [0.697, 0.774, 0.634, 0.608, 0.556, 0.403, 0.481, 0.437, 0.666, 0.243, 0.245, 0.343, 0.639, 0.657, 0.360,
           0.593, 0.719],
    '含糖率': [0.460, 0.376, 0.264, 0.318, 0.215, 0.237, 0.149, 0.211, 0.091, 0.267, 0.057, 0.099, 0.161, 0.198, 0.370,
            0.042, 0.103],
    '好瓜': ['是', '是', '是', '是', '是', '是', '是', '是', '否', '否', '否', '否', '否', '否', '否', '否', '否']
}

df = pd.DataFrame(data)

# 准备特征和目标变量
features = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感', '密度', '含糖率']
X = df[features]
y = df['好瓜']

# 创建并训练分类器
nb_classifier = NaiveBayesClassifier()
nb_classifier.fit(X, y)

# 评估分类器
accuracy = nb_classifier.evaluate(X, y)
print(f"模型在训练集上的准确率: {accuracy:.2%}")

# 预测新样本
new_samples = pd.DataFrame([
    {'色泽': '青绿', '根蒂': '蜷缩', '敲声': '浊响', '纹理': '清晰', '脐部': '凹陷', '触感': '硬滑', '密度': 0.697, '含糖率': 0.460},
])

predictions = nb_classifier.predict(new_samples)
for i, pred in enumerate(predictions):
    print(f"样本{i + 1}的预测结果: {'是' if pred == '是' else '否'}")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值