【李航-统计学习方法】【原理与代码】第四章 朴素贝叶斯 Naive Bayes python C++

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/github_36923418/article/details/89116606

一、原理

     朴素贝叶斯必须要有的先决假设:特征条件独立,意思就是 X这个特征向量中的x1,x2,x3.。。。等,相互之间都是条件独立的。

     先验概率:

                            

     条件概率:

                       

      根据条件独立这个假设,可以得到如下条件概率的计算方式:

                        

       那么在利用 朴素贝叶斯 进行分类时,计算后验概率的方式如下:

                

               

     那么“朴素贝叶斯”模型可以表示为:

               

     因为,对于任何分子,他们的分母都是相同的,所以又可以简化为如下内容:

                      

二、代码

     依然会利用第三章中用到的“鸢尾属植物 iris数据集”,对于这个数据集假设服从的是“高斯分布”。那么我们可以得到如下的概率密度函数:

                    

      概率密度函数  对应于  上面的  “条件概率” 这个概念。

#倒入全部用得到,用不到的库
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
#创建数据
# 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]

#建立模型
class NaiveBayes:
    def __init__(self,):
        self.model=None
        
    #数学期望 ,用来求出训练集不同特征的的均值
    def mean(self,X):
        return sum(X)/float(len(X))
    
    #标准差/方差 ,求出训练集,不同特征的std
    def stdev(self,X):
        average = self.mean(X)
        std=sum([math.pow(x-average,2) for x in X]) / float(len(X))
        std = math.sqrt(std)
        return std
    
    #条件概率
    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*math.pow(stdev,2)))*exponent
    
    def get_mean_std(self,x_feature):
        mean_std=[(self.mean(i), self.stdev(i)) for i in zip(*x_feature)]
        return mean_std
    
    
    def train_model(self,X,y):
        labels=list(set(y)) #利用set可以获取 y的所有不同取值
        data = {label:[] for label in labels} # 给每一个类别建立 list
        for feature, label in zip(X,y):
            data[label].append(feature) #把每个类别的特征进行搜集
        #计算出,在某个类别下,某个特征的概率 =》条件概率 =》概率密度 ,因此要现求出某个类别下,某个特征的mean和std
        self.model = {label: self.get_mean_std(x_i_list_value) for label,x_i_list_value in data.items()}
        print("model ready!")
    
    def calculate_probabilities(self,input_data):
        # 需要计算,所有类别的可能概率,最后选择概率最大的类别
        probabilities={}
        for label, value in self.model.items():
            probabilities[label]=1 #先验概率直接假设为1
            assert len(value)==4
            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):
        #print(sorted(self.calculate_probabilities(X_test).items(), key=lambda x: x[-1])[-1][0])
        #利用 【(lable, probability),(lable, probability)】中的倒数第一个内容进行排序
        label = sorted(self.calculate_probabilities(X_test).items(), key=lambda x: x[-1])[-1][0]
        return label
        
X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
model = NaiveBayes()
model.train_model(X_train, y_train)
model.predict([4.4,  3.2,  1.3,  0.2])
#0.0

猜你喜欢

转载自blog.csdn.net/github_36923418/article/details/89116606