项目:朴素贝叶斯手工模型

1.分类预测模型:朴素贝叶斯

构建分类器的简单方法,不是训练分类器的单一算法,而是一系列基于相同原理的算法。
假定样本每个特征与其他特征都不相关,即样本所包含的属性在判定其是否为某一类时的概率分布上是独立的(条件概率)。
优点:学习和预测的效率高,易于实现;在数据较少时仍然有效,可以处理多分类问题。
缺点:分类的效果不一定高,特征独立性假设使该模型简单,但是会牺牲一定的分类准确率。
p ( C ∣ F 1 , . . . , F n ) = p ( C ) p ( F 1 , . . . , F n ∣ C ) p ( F 1 , . . . F n ) = p ( C ) p ( F 1 ∣ C ) . . . p ( F n ∣ C ) p ( F 1 , . . . F n ) p(C|F_1,...,F_n)=\frac{p(C)p(F_1,...,F_n|C)}{p(F_1,...F_n)}=\frac{p(C)p(F_1|C)...p(F_n|C)}{p(F_1,...F_n)} p(CF1,...,Fn)=p(F1,...Fn)p(C)p(F1,...,FnC)=p(F1,...Fn)p(C)p(F1C)...p(FnC)

1.1概率计算及参数估计

特征是离散变量,可以用频率来估计概率。
特征的连续的,一种通常的假设使这些连续数值服从高斯分布。
首先对数据类别分类,然后计算每个类别中特征x的均值和方差。

2.代码及注释

mian.py

# -*- coding: utf-8 -*-


from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from nb_tools import NaiveBayes, cal_acc


def run_main():
    """
        主函数
    """
    n_feat = 100    # 特征个数(维度)
    X, y = make_classification(
        n_samples=400,   #400个样本
        n_features=n_feat,
        n_classes=4,  #四类
        random_state=5)

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,
                                                        random_state=17)

    nb_model = NaiveBayes(n_feat)

    # 样本特征为连续值,假设其符合高斯分布,则需要求出每个特征的均值和标准差
    # 这里称为统计参数 stats

    # 获取训练集中每个类别的统计参数nb_model里获得均值方差
    tr_cls_stats = nb_model.get_cls_stats(X_train, y_train)
    for cls, samples_stats in tr_cls_stats.items():
        print('类{}的统计参数:'.format(cls))
        for i, feat_stats in enumerate(samples_stats):
            # 查看每个特征的统计参数
            print('第{}个特征的统计参数{}'.format(i, feat_stats))

    # 根据训练样本的统计参数进行预测
    y_pred = nb_model.predict(tr_cls_stats, X_test)

    # 准确率
    print('准确率:{}'.format(cal_acc(y_test, y_pred)))


if __name__ == '__main__':
    run_main()


nb_tools.py

# -*- coding: utf-8 -*-

import numpy as np
import scipy.stats


class NaiveBayes(object):
    """
        Naive Bayes 类
    """
    def __init__(self, n_feat):
        self.n_feat = n_feat    # 样本的特征维度

    def get_cls_stats(self, X_train, y_train):
        """
            返回训练集中每个类的统计参数
        """
        # 获取类别
        unique_cls_list = list(set(y_train.tolist()))

        # 构造字典
        dataset_stats = {}
        for cls in unique_cls_list:
            # 获取属于该类的样本(过滤)
            samples_in_cls = X_train[y_train == cls]

            # 获取该类样本中每个特征的统计参数
            samples_in_cls_stats = self.get_samples_stats(samples_in_cls)
            dataset_stats[cls] = samples_in_cls_stats

        return dataset_stats

    def get_samples_stats(self, samples):
        """
            返回一组样本中每个特征(属性)的统计参数
        """
        # 每个特征维度上计算统计参数,即均值和标准差
        samples_stats = [(np.mean(samples[:, i]), np.std(samples[:, i]))
                         for i in range(self.n_feat)]
        return samples_stats

    def predict(self, tr_cls_stats, X_test):
        """
            根据训练样本统计参数预测整个测试样本集
        """
        y_pred = []
        n_sample = X_test.shape[0]  # 测试样本的个数
        for i in range(n_sample):
            # 遍历每个测试样本
            sample = X_test[i, :]
            pred = self.predict_sample(tr_cls_stats, sample)
            y_pred.append(pred)

        return y_pred

    def predict_sample(self, tr_cls_stats, sample):
        """
            根据训练样本统计参数预测单一样本
        """
        cls_probs = self.cal_cls_probs(tr_cls_stats, sample)

        # 初始化
        best_label = None
        best_prob = -1

        for cls, cls_prob in cls_probs.items():
            if best_label is None or cls_prob > best_prob:
                best_prob = cls_prob
                best_label = cls

        return best_label

    def cal_cls_probs(self, tr_cls_stats, sample):
        """
            根据高斯分布及训练集的统计参数返回样本分类的概率
        """
        probs = {}
        for cls, cls_stats in tr_cls_stats.items():
            # 初始化属于cls类的概率100%
            probs[cls] = 1
            for i in range(len(cls_stats)):
                # 遍历cls类中每个特征维度上的统计参数
                mean, std = cls_stats[i]
                single_feat_vec = sample[i]

                # 根据高斯分布的概率密度函数及每个特征维度上的统计参数求联合该概率
                probs[cls] *= scipy.stats.norm.pdf(single_feat_vec, mean, std)

        return probs


def cal_acc(true_labels, pred_labels):
    """
        计算准确率
    """
    n_total = len(true_labels)
    correct_list = [true_labels[i] == pred_labels[i] for i in range(n_total)]

    acc = sum(correct_list) / n_total
    return acc

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值