图片 2

机器学习之用Python从零实现贝叶斯分类器

图片 1

呀,这是打算要卖什么狗皮膏药的广告吗?不是,其实我们程序员,或多或少,都会去研究某某抽奖平台的概率问题,笔者也不例外,说不定哪天就会天上掉下个大馅饼了呢!有些平台在我们伟大的天朝是被严厉禁止的,尽一切可能保证社会主义核心价值观…这些话咱不多说哈,以免招来杀生之祸^_^。详细内容可以下载本人的源码进行调试就可以知道结果,纯脚本式代码,写的搓,有强迫症的朋友请多包涵。

朴素贝叶斯算法简单高效,在处理分类问题上,是应该首先考虑的方法之一。

重要提示:本着分享为目的,才能使技术进步,但是笔者还是希望,我们只是在讨论算法问题,就像在监督机器人如何去学习、去预测这过程中的实现问题,懂了就行,表要声张,也千万不要陷入进去,不然谁都救不了你的哦,笔者身边就有这样的朋友,最后家破人亡…

通过本教程,你将学到朴素贝叶斯算法的原理和Python版本的逐步实现。

笔者已提供一套已经搭建70%的基础,剩下30%的算法可以自行实现。比如爬取数据,从2000年开始(只要你愿意,从1976年开始爬取都行)的数据样本;比如规则数据样本;比如分布式协同运算(名词真拗口,就是多台机器一起算)等等。

更新:查看后续的关于朴素贝叶斯使用技巧的文章“Better Naive Bayes: 12 Tips
To Get The Most From The Naive Bayes Algorithm”

由于笔者水平有限,目前由两种方式去预判:

图片 2

1:通过统计学以及长久的一些猜想规则,记录并运算能准确取消的数字(也就是它不会出现在集合中),正确率高达90%以上。

朴素贝叶斯分类器,Matt Buck保留部分版权

2:采用“组合算法”,组合了几十亿组公式来进行运算,结果嘛,算法写得搓,手头服务器资源不够,没有结果,要算半年多……

关于朴素贝叶斯

该系列由于种种因素更新会较慢,请多包涵!

朴素贝叶斯算法是一个直观的方法,使用每个属性归属于某个类的概率来做预测。你可以使用这种监督性学习方法,对一个预测性建模问题进行概率建模。

再次提示:世上没有100%的绝对,笔者分享的源码只是为了学习和研究概率方法论,千万不要陷入到这个圈子里面去了,否者一切跟笔者和平台无关。

给定一个类,朴素贝叶斯假设每个属性归属于此类的概率独立于其余所有属性,从而简化了概率的计算。这种强假定产生了一个快速、有效的方法。

 

给定一个属性值,其属于某个类的概率叫做条件概率。对于一个给定的类值,将每个属性的条件概率相乘,便得到一个数据样本属于某个类的概率。

目录(忐忑的更新中)

用Python预测某某国际平台概率分析(一):这个到底是什么,是什么样的规则?

用Python预测某某国际平台概率分析(二):如何运行你的代码,这结果又是什么意思?

用Python预测某某国际平台概率分析(三):如何实现python爬虫?

用Python预测某某国际平台概率分析(四):如何预测某个数字不会在这个集合中?

用Python预测某某国际平台概率分析(五):组合算法很渣,有没有更好的算法实现?

……

我们可以通过计算样本归属于每个类的概率,然后选择具有最高概率的类来做预测。

通常,我们使用分类数据来描述朴素贝叶斯,因为这样容易通过比率来描述、计算。一个符合我们目的、比较有用的算法需要支持数值属性,同时假设每一个数值属性服从正态分布(分布在一个钟形曲线上),这又是一个强假设,但是依然能够给出一个健壮的结果。

预测糖尿病的发生

本文使用的测试问题是“皮马印第安人糖尿病问题”。

这个问题包括768个对于皮马印第安患者的医疗观测细节,记录所描述的瞬时测量取自诸如患者的年纪,怀孕和血液检查的次数。所有患者都是21岁以上(含21岁)的女性,所有属性都是数值型,而且属性的单位各不相同。

每一个记录归属于一个类,这个类指明以测量时间为止,患者是否是在5年之内感染的糖尿病。如果是,则为1,否则为0。

机器学习文献中已经多次研究了这个标准数据集,好的预测精度为70%-76%。

下面是pima-indians.data.csv文件中的一个样本,了解一下我们将要使用的数据。

注意:下载文件,然后以.csv扩展名保存(如:pima-indians-diabetes.data.csv)。查看文件中所有属性的描述。

6,148,72,35,0,33.6,0.627,50,1  1,85,66,29,0,26.6,0.351,31,0  8,183,64,0,0,23.3,0.672,32,1  1,89,66,23,94,28.1,0.167,21,0  0,137,40,35,168,43.1,2.288,33,1  

朴素贝叶斯算法教程

教程分为如下几步:

1.处理数据:从CSV文件中载入数据,然后划分为训练集和测试集。

2.提取数据特征:提取训练数据集的属性特征,以便我们计算概率并做出预测。

3.单一预测:使用数据集的特征生成单个预测。

4.多重预测:基于给定测试数据集和一个已提取特征的训练数据集生成预测。

5.评估精度:评估对于测试数据集的预测精度作为预测正确率。

6.合并代码:使用所有代码呈现一个完整的、独立的朴素贝叶斯算法的实现。

1.处理数据

首先加载数据文件。CSV格式的数据没有标题行和任何引号。我们可以使用csv模块中的open函数打开文件,使用reader函数读取行数据。

我们也需要将以字符串类型加载进来属性转换为我们可以使用的数字。下面是用来加载匹马印第安人数据集(Pima
indians dataset)的loadCsv()函数。

import csv  def loadCsv(filename):  lines = csv.reader(open(filename, "rb"))  dataset = list(lines)  for i in range(len(dataset)):  dataset[i] = [float(x) for x in dataset[i]]  return dataset  

我们可以通过加载皮马印第安人数据集,然后打印出数据样本的个数,以此测试这个函数。

filename = 'pima-indians-diabetes.data.csv'  dataset = loadCsv(filename)  print('Loaded data file {0} with {1} rows').format(filename, len(dataset))  

运行测试,你会看到如下结果:

Loaded data file iris.data.csv with 150 rows 

下一步,我们将数据分为用于朴素贝叶斯预测的训练数据集,以及用来评估模型精度的测试数据集。我们需要将数据集随机分为包含67%的训练集合和包含33%的测试集(这是在此数据集上测试算法的通常比率)。

下面是splitDataset()函数,它以给定的划分比例将数据集进行划分。

import random  def splitDataset(dataset, splitRatio):      trainSize = int(len(dataset) * splitRatio)      trainSet = []      copy = list(dataset)      while len(trainSet) < trainSize:          index = random.randrange(len(copy))          trainSet.append(copy.pop(index))      return [trainSet, copy]  

我们可以定义一个具有5个样例的数据集来进行测试,首先它分为训练数据集和测试数据集,然后打印出来,看看每个数据样本最终落在哪个数据集。

dataset = [[1], [2], [3], [4], [5]]  splitRatio = 0.67  train, test = splitDataset(dataset, splitRatio)  print('Split {0} rows into train with {1} and test with {2}').format(len(dataset), train, test)  

运行测试,你会看到如下结果:

Split 5 rows into train with [[4], [3], [5]] and test with [[1], [2]] 

提取数据特征

朴素贝叶斯模型包含训练数据集中数据的特征,然后使用这个数据特征来做预测。

所收集的训练数据的特征,包含相对于每个类的每个属性的均值和标准差。举例来说,如果如果有2个类和7个数值属性,然后我们需要每一个属性(7)和类(2)的组合的均值和标准差,也就是14个属性特征。

在对特定的属性归属于每个类的概率做计算、预测时,将用到这些特征。

我们将数据特征的获取划分为以下的子任务:

  1. 按类别划分数据
  2. 计算均值
  3. 计算标准差
  4. 提取数据集特征
  5. 按类别提取属性特征

按类别划分数据

首先将训练数据集中的样本按照类别进行划分,然后计算出每个类的统计数据。我们可以创建一个类别到属于此类别的样本列表的的映射,并将整个数据集中的样本分类到相应的列表。

下面的SeparateByClass()函数可以完成这个任务:

def separateByClass(dataset):      separated = {}      for i in range(len(dataset)):          vector = dataset[i]          if (vector[-1] not in separated):              separated[vector[-1]] = []          separated[vector[-1]].append(vector)      return separated  

可以看出,函数假设样本中最后一个属性(-1)为类别值,返回一个类别值到数据样本列表的映射。

我们可以用一些样本数据测试如下:

dataset = [[1,20,1], [2,21,0], [3,22,1]]  separated = separateByClass(dataset)  print('Separated instances: {0}').format(separated)  

运行测试,你会看到如下结果:

Separated instances: {0: [[2, 21, 0]], 1: [[1, 20, 1], [3, 22, 1]]} 

计算均值

我们需要计算在每个类中每个属性的均值。均值是数据的中点或者集中趋势,在计算概率时,我们用它作为高斯分布的中值。

我们也需要计算每个类中每个属性的标准差。标准差描述了数据散布的偏差,在计算概率时,我们用它来刻画高斯分布中,每个属性所期望的散布。

标准差是方差的平方根。方差是每个属性值与均值的离差平方的平均数。注意我们使用N-1的方法(译者注:参见无偏估计),也就是在在计算方差时,属性值的个数减1。

import math  def mean(numbers):      return sum(numbers)/float(len(numbers))     def stdev(numbers):      avg = mean(numbers)      variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1)      return math.sqrt(variance)  

通过计算从1到5这5个数的均值来测试函数。

numbers = [1,2,3,4,5]  print('Summary of {0}: mean={1}, stdev={2}').format(numbers, mean(numbers), stdev(numbers))  

运行测试,你会看到如下结果:

Summary of [1, 2, 3, 4, 5]: mean=3.0, stdev=1.58113883008 

提取数据集的特征

现在我们可以提取数据集特征。对于一个给定的样本列表(对应于某个类),我们可以计算每个属性的均值和标准差。

zip函数将数据样本按照属性分组为一个个列表,然后可以对每个属性计算均值和标准差。

def summarize(dataset):  summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)]  del summaries[-1]  return summaries  

我们可以使用一些测试数据来测试这个summarize()函数,测试数据对于第一个和第二个数据属性的均值和标准差显示出显著的不同。

dataset = [[1,20,0], [2,21,1], [3,22,0]]  summary = summarize(dataset)  print('Attribute summaries: {0}').format(summary)  

运行测试,你会看到如下结果:

Attribute summaries: [(2.0, 1.0), (21.0, 1.0)] 

按类别提取属性特征

发表评论

电子邮件地址不会被公开。 必填项已用*标注