朴素贝叶斯分类器 注释

试编程实现拉普拉斯修正的朴素贝叶斯分类器,并以西瓜数据集3.0为训练集,对P.151“测1”进行判别。

代码全是《机器学习》上的,只是将其整合到了一起,能够运行手写体识别。
内容大部分进行了注释,可能有些注释不够精准或者不容理解,见谅!

代码

from numpy import *

def loadDataSet(): #创建实验样本
    postingList=[['青绿','蜷缩','浊响','清晰','凹陷','硬滑',0.697,0.460],
                 ['乌黑','蜷缩','沉闷','清晰','凹陷','硬滑',0.774,0.376],
                 ['乌黑','蜷缩','浊响','清晰','凹陷','硬滑',0.634,0.264],
                 ['青绿','蜷缩','沉闷','清晰','凹陷','硬滑',0.608,0.318],
                 ['浅白','蜷缩','浊响','清晰','凹陷','硬滑',0.556,0.215],
                 ['青绿','稍蜷','浊响','清晰','稍凹','软粘',0.403,0.237],
                 ['乌黑','稍蜷','浊响','稍糊','稍凹','软粘',0.481,0.149],
                 ['乌黑','稍蜷','浊响','清晰','稍凹','硬滑',0.437,0.211],
                 ['乌黑','稍蜷','沉闷','稍糊','稍凹','硬滑',0.666,0.091],
                 ['青绿','硬挺','清脆','清晰','平坦','软粘',0.243,0.267],
                 ['浅白','硬挺','清脆','模糊','平坦','硬滑',0.245,0.057],
                 ['浅白','蜷缩','浊响','模糊','平坦','软粘',0.343,0.099],
                 ['青绿','稍蜷','浊响','稍糊','凹陷','硬滑',0.639,0.161],
                 ['浅白','稍蜷','沉闷','稍糊','凹陷','硬滑',0.657,0.198],
                 ['乌黑','稍蜷','浊响','清晰','稍凹','软粘',0.360,0.370],
                 ['浅白','蜷缩','浊响','模糊','平坦','硬滑',0.593,0.042],
                 ['青绿','蜷缩','沉闷','稍糊','稍凹','硬滑',0.719,0.103]]
    classVec = [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0]    #1是好瓜,0不是好瓜
    return postingList,classVec

                 
def createVocabList(dataSet): #传入词条切分后的列表
    vocabSet = set([])  #用set()创建空的集合
    for document in dataSet:
        vocabSet = vocabSet | set(document) #合并两个集合
    return list(vocabSet)

def setOfWords2Vec(vocabList, inputSet): #传入一个集合和被检测列表
    returnVec = [0]*len(vocabList) #初始化列表全为0
    for word in inputSet: #遍历被检测列表
        if word in vocabList: #检测被检测列表中是否有给定样本中的词汇
            returnVec[vocabList.index(word)] = 1 #将该词出现的第一个位置的特征值标记为1
        else: print( "the word: %s is not in my Vocabulary!" % word)
    return returnVec

def trainNB0(trainMatrix,trainCategory): #拉普斯修改后的朴素贝叶斯算法
    numTrainDocs = len(trainMatrix) 
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs) #计算坏瓜所占比例
    p0Num = ones(numWords); p1Num = ones(numWords) 
p0Denom = 2.0; p1Denom = 2.0                        
    for i in range(numTrainDocs):  #遍历每个文本
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = log(p1Num/p1Denom)  #计算每个属性被判为坏瓜属性的概率
    p0Vect = log(p0Num/p0Denom)   #基本同上,避免结果下溢
    return p0Vect,p1Vect,pAbusive

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify * p1Vec) + log(pClass1)    #属性在出现0/1情况*概率   再求和 + 类别对数概率
    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else: 
        return 0
    
def bagOfWords2VecMN(vocabList, inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1 #每个单词再集合中的出现次数
    return returnVec

def testingNB(canshu):
    listOPosts,listClasses = loadDataSet()  #取样
    myVocabList = createVocabList(listOPosts) #变为无重复集合
    trainMat=[]
    for postinDoc in listOPosts: #标记每个属性是否再大集合中出现
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses))
    testEntry = canshu
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry)) #标记testEntry属性再集合中的出现
    print (testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))

if __name__=='__main__':
  canshu=list(input("请输入:").split()) #将结果输入
  testingNB(canshu)

运行结果

在这里插入图片描述

好的,以下是对课本朴素贝叶斯代码的注释: ``` import numpy as np # 定义朴素贝叶斯分类器类 class NaiveBayes: # 初始化函数,传入数据集和标签 def __init__(self, X, y): self.X, self.y = X, y self.classes = np.unique(y) # 获取不重复的标签类别 self.n_classes = len(self.classes) # 获取标签类别数 self.n_features = X.shape[1] # 获取特征数 # 初始化每个类别的均值、标准差和先验概率 self.mean = np.zeros((self.n_classes, self.n_features)) self.std = np.zeros((self.n_classes, self.n_features)) self.prior = np.zeros(self.n_classes) # 计算每个类别的均值和标准差 def fit(self): for i, c in enumerate(self.classes): X_c = self.X[self.y == c] # 获取当前类别下的数据 self.mean[i, :] = X_c.mean(axis=0) # 计算当前类别下每个特征的均值 self.std[i, :] = X_c.std(axis=0) # 计算当前类别下每个特征的标准差 self.prior[i] = X_c.shape[0] / self.X.shape[0] # 计算当前类别的先验概率 # 计算概率密度函数 def gaussian_density_function(self, class_idx, x): mean = self.mean[class_idx] std = self.std[class_idx] numerator = np.exp(-((x - mean) ** 2) / (2 * (std ** 2))) # 计算正态分布的分子部分 denominator = np.sqrt(2 * np.pi) * std # 计算正态分布的分母部分 return numerator / denominator # 预函数 def predict(self, X): y_pred = np.zeros(X.shape[0]) for i, x in enumerate(X): posteriors = [] for j in range(self.n_classes): prior = np.log(self.prior[j]) # 先验概率取对数,避免数值下溢 class_conditional = np.sum(np.log(self.gaussian_density_function(j, x))) # 计算类条件概率取对数 posterior = prior + class_conditional # 计算后验概率 posteriors.append(posterior) y_pred[i] = self.classes[np.argmax(posteriors)] # 取后验概率最大的类别作为预结果 return y_pred ``` - `import numpy as np`:导入NumPy库,并简写为np。 - `class NaiveBayes:`:定义朴素贝叶斯分类器类。 - `def __init__(self, X, y):`:初始化函数,传入数据集X和标签y。 - `self.X, self.y = X, y`:将传入的数据集和标签分别赋值给实变量self.X和self.y。 - `self.classes = np.unique(y)`:获取不重复的标签类别,赋值给实变量self.classes。 - `self.n_classes = len(self.classes)`:获取标签类别数,赋值给实变量self.n_classes。 - `self.n_features = X.shape[1]`:获取特征数,赋值给实变量self.n_features。 - `self.mean = np.zeros((self.n_classes, self.n_features))`:初始化每个类别的均值,用一个n_classes行、n_features列的全0数组表示,赋值给实变量self.mean。 - `self.std = np.zeros((self.n_classes, self.n_features))`:初始化每个类别的标准差,用一个n_classes行、n_features列的全0数组表示,赋值给实变量self.std。 - `self.prior = np.zeros(self.n_classes)`:初始化每个类别的先验概率,用一个n_classes长度的全0数组表示,赋值给实变量self.prior。 - `def fit(self):`:计算每个类别的均值、标准差和先验概率。 - `for i, c in enumerate(self.classes):`:遍历每个类别的索引i和类别c。 - `X_c = self.X[self.y == c]`:获取当前类别下的数据,即所有标签为c的样本。 - `self.mean[i, :] = X_c.mean(axis=0)`:计算当前类别下每个特征的均值,用mean函数计算,赋值给self.mean的第i行。 - `self.std[i, :] = X_c.std(axis=0)`:计算当前类别下每个特征的标准差,用std函数计算,赋值给self.std的第i行。 - `self.prior[i] = X_c.shape[0] / self.X.shape[0]`:计算当前类别的先验概率,即当前类别下的样本数占总样本数的比,赋值给self.prior的第i个元素。 - `def gaussian_density_function(self, class_idx, x):`:计算概率密度函数。 - `mean = self.mean[class_idx]`:获取类别为class_idx的所有特征的均值,赋值给变量mean。 - `std = self.std[class_idx]`:获取类别为class_idx的所有特征的标准差,赋值给变量std。 - `numerator = np.exp(-((x - mean) ** 2) / (2 * (std ** 2)))`:计算正态分布的分子部分,即exp(-(x-μ)^2/(2σ^2))。 - `denominator = np.sqrt(2 * np.pi) * std`:计算正态分布的分母部分,即√(2π)σ。 - `return numerator / denominator`:返回概率密度函数的值,即正态分布的概率密度函数。 - `def predict(self, X):`:预函数,传入测试数据集X。 - `y_pred = np.zeros(X.shape[0])`:初始化预结果,用一个长度为测试数据集样本数的全0数组表示,赋值给变量y_pred。 - `for i, x in enumerate(X):`:遍历测试数据集中的每个样本的索引i和特征向量x。 - `posteriors = []`:初始化后验概率列表posteriors。 - `for j in range(self.n_classes):`:遍历每个类别的索引j。 - `prior = np.log(self.prior[j])`:计算当前类别的先验概率取对数,避免数值下溢。 - `class_conditional = np.sum(np.log(self.gaussian_density_function(j, x)))`:计算当前类别下的类条件概率取对数。 - `posterior = prior + class_conditional`:计算后验概率。 - `posteriors.append(posterior)`:将当前后验概率添加到posteriors列表中。 - `y_pred[i] = self.classes[np.argmax(posteriors)]`:取后验概率最大的类别作为预结果,赋值给y_pred的第i个元素。 - `return y_pred`:返回预结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值