Advertisement

朴素贝叶斯算法实现

阅读量:

数据集 泰坦尼克号存亡数据

免费

零成本

零成本

复制代码
 # Author : Haoer

    
 import  random
    
  
    
 import pandas as pd
    
 # 多项式朴素贝叶斯分类器
    
 class MulNB:
    
     # 初始化 特征标签
    
     def __init__(self,features):
    
     self.features=features
    
     #计算先验概率
    
     def calPriP(self,labelslist:list):
    
     # 所有的分类属性
    
     labelset=set(labelslist)
    
     # 存储每个分类属性的先验概率
    
     classdicP={}
    
     for label in labelset:
    
         #每个分类的先验概率 这里采用拉普拉斯修正
    
         classdicP[label]=(labelslist.count(label)+1)/(len(labelslist)+len(labelset))
    
     return classdicP
    
  
    
     # 计算后验概率
    
     def calpostP(self,dataset):
    
     # 存放每一个分类下每一个特征的所有样本
    
     classdiclist={}
    
     for label in self.classdicPri:
    
         #初始化
    
         classdiclist[label]={}
    
         for feature in self.features:
    
             #将该分类下的此特征设定为一个列表供后续遍历的添加
    
             classdiclist[label][feature]=[]
    
     #特征数量
    
     feature_num=len(self.features)
    
     for sample in dataset:
    
         for i in range(feature_num):
    
             # 将每一条数据添加到该分类下对应特征值下面
    
             classdiclist[sample[-1]][self.features[i]].append(sample[i])
    
     #存放每个特征下面有那些属性
    
     features_set={}
    
     for i in range(feature_num):
    
         # 找到该特征下所有属性
    
         features_set[self.features[i]]=set([sample[i] for sample in dataset])
    
     # 存放每个分类下,对应特征值的属性出现的概率
    
     classdicP= {}
    
     for label in self.classdicPri:
    
         #初始化
    
         classdicP[label]={}
    
         for feature in self.features:
    
             #用于从放每个分类下每个特征下每个属性的概率
    
             classdicP[label][feature]={}
    
     for label in classdiclist:
    
         for feature in features_set:
    
             for value in features_set[feature]:
    
                 #计算后验概率,这里采用拉普拉斯修正
    
                 classdicP[label][feature][value]=(classdiclist[label][feature].count(value)+1)/(len(classdiclist[label][feature])+len(feature))
    
     #返回各个后验概率
    
     return classdicP
    
  
    
     #训练朴素贝叶斯分类器
    
     def fit(self,dataset):
    
     labellist=[sample[-1] for sample in dataset]
    
     # 获取每个分类的先验概率
    
     self.classdicPri=self.calPriP(labellist)
    
     # 获取后验概率
    
     self.classP=self.calpostP(dataset)
    
  
    
     #预测
    
     def predict(self,sample):
    
     maxP=0
    
     out='unknown'
    
     for label in self.classdicPri:
    
         #先验概率
    
         P=self.classdicPri[label]
    
         for i in range(len(sample)):
    
             # 每个后验概率累乘
    
             P=P*self.classP[label][self.features[i]][sample[i]]
    
         # 出现更大概率 即该分类为预测值
    
         if P>maxP:
    
             maxP=P
    
             out=label
    
     return out
    
  
    
  
    
 def loadData():
    
     df =pd.read_csv('titanic.csv')
    
     # 年龄用中位数填充
    
     df['Age'].fillna(df['Age'].median(),inplace=True)
    
     # 15岁一个年龄段处理 转换成整型
    
     df['Age']=df['Age'].apply(lambda p:int(p/15))
    
     # Embarked用众数填充
    
     df['Embarked'].fillna(df['Embarked'].mode()[0],inplace=True)
    
     # 丢弃id 姓名 票价格(和船舱等级相关)和编号,Cabin缺少太多了,参考价值小
    
     df=df.drop(['PassengerId','Name','Ticket','Fare','Cabin'],axis=1)
    
     df.isnull().any()
    
     all_labels=list(df.columns)
    
     # 将幸存者预测这一列交换到最后
    
     all_labels[0],all_labels[6]=all_labels[6],all_labels[0]
    
     df=df[all_labels]
    
     print('数据处理后的留下的特征',all_labels)
    
     dataset=[]
    
     # 遍历Dataset转换成列表
    
     for i in range(len(df)):
    
     dataset.append(list(df.loc[i,:]))
    
     return  dataset,all_labels[:-1]
    
  
    
 def main():
    
     dataset, features = loadData()
    
     # 打乱数据
    
     random.shuffle(dataset)
    
     # 训练集和测试机 8 : 2
    
     trainset = dataset[:int(len(dataset) * 0.8)]
    
     testset = dataset[int(len(dataset) * 0.8):]
    
     # 初始化朴素贝叶斯分类器
    
     nb=MulNB(features)
    
     # 训练模型
    
     nb.fit(trainset)
    
     # 预测正确数量
    
     truecount = 0
    
     # 预测样本总数
    
     sumcount = len(testset)
    
     for sample in testset:
    
     pre=nb.predict(sample[:-1])
    
     print('预测为:', pre, '实际为:', sample[-1])
    
     if sample[-1] == pre:
    
         truecount += 1
    
     print('预测正确数量: ', truecount)
    
     print('总预测数:', sumcount)
    
     print('预测正确率:', truecount / sumcount)
    
  
    
  
    
 if __name__=='__main__':
    
     main()
    
    
    
    
    代码解读

全部评论 (0)

还没有任何评论哟~