利用上一节讲述的理论,本节将使用朴素贝叶斯实现糖尿病患病预测。本节使用的数据来源于美国国家糖尿病和消化肾脏疾病研究所,原始数据可从UCI数据库获取。这是机器学习领域一个被广泛研究的标准数据集,一般认为,关于这个数据集的预测算法如果能达到70%~76%的预测准确率就是一个较好的预测算法。本教材所用数据已经根据需要进行过适当地处理,可从教材配套的资源平台下载。
首先从本教材的资源平台下载该数据文件,并以文件名pima-indians.data.csv保存为csv文件。这是一个关于皮马族糖尿病患者的医疗检测数据(表4-1)。皮马族是美国印第安原住民的一个种族,由于基因缺陷,这个种族的糖尿病患病率很高,数据集描述了768个皮马印第安糖尿病患者的医疗观测细节,所有患者都是21岁以上(含21岁)的女性,所有的特征属性取值都是数值型,且各属性取值的度量单位是不同的。
表4-1
双击打开数据文件可以看到这是一个包含9个数据项的表格。其中Pregnancies代表怀孕次数;Glucose代表口服葡萄糖耐量试验中的葡萄糖浓度;Blood Pressure代表血压;Skin Thickness代表皮脂厚度;Insulin代表血清胰岛素含量;BMI代表体重指数;Diabetes Pedigree Function代表糖尿病系统功能;Age代表年龄;Outcome代表5年内是否患有糖尿病,1表示患病,0表示未患病。因此这可以对应到一个分类问题,输入数据是前8项检测数据,输出的分类结果是0或者1,表示该人未患病或者患病。
首先导入三个需要用到的Python库。csv是一种以逗号分隔存储数据的文件格式,csv模块可以很好地对这种格式的数据进行读取、存储和处理。random模块用于随机分割数据集,产生训练数据和测试数据。math模块用于计算数据的均值、标准差等数学结果时可以直接调用相应的计算函数。
In[1]:import csv,random,math
这里提到了训练数据和测试数据的概念,在上一章对决策树模型进行评价时也提到过这些概念,下面对它们做一个简单的说明。对于分类算法来说,训练完成后需要对训练结果的性能进行评价,如估计模型分类的准确率。为了估计准确率,需要在已知分类结果的数据集上对分类器进行测试,通过对比分类器给出的分类结果与真实的分类结果,可以方便地对准确率进行评估。所以在取得人工标注的数据集后,一种常用的处理方式是对其按一定的比例进行划分,其中一部分用来训练模型,叫作训练数据;另一部分用来进行模型的测试,叫作测试数据。
定义读取数据文件的函数load_csv_file。把数据文件中的每一行封装到一个list中,然后对数据进行处理,把数据转换成浮点型数据并返回data_set。
In[2]:def load_csv_file(filename):
with open(filename)as f:
lines=csv.reader(f)
data_set=list(lines)
for i in range(len(data_set)):
data_set[i]=[float(x)for x in data_set[i]]
return data_set
把数据集分割成训练数据和测试数据,分割比例通过参数split_ratio确定,一般按“训练数据∶测试数据=2∶1”来分割。这里使用了random库进行随机划分,以保证用来训练和测试的数据尽量服从同样的分布。
In[3]:def split_data_set(data_set,split_ratio):
train_size=int(len(data_set)*split_ratio)
train_set=[]
data_set_copy=list(data_set)
while len(train_set)best_prob:
best_label=class_val
best_prob=probability
return best_label
定义准确性评估函数,在测试数据上评估分类器的准确率。
In[9]:def get_predictions(summaries,test_set):
predictions=[]
for i in range(len(test_set)):
result=predict(summaries,test_set[i])
predictions.append(result)
return predictions
def get_accuracy(predictions,test_set):
correct=0
for x in range(len(test_set)):
if test_set[x][-1]==predictions[x]:
correct +=1
return(correct/float(len(test_set)))*100.0
定义main函数,通过运行main函数,进行分类器的训练和在测试数据集上的准确率评估。
In[10]:def main():
filename='pima-indians.data.csv'
split_ratio=0.67
data_set=load_csv_file(filename)
train_set,test_set=split_data_set(data_set,spli
t_ratio)
print('Split%s rows into train set=%s and test
set=%s rows'%(len(data_set),len(train_
set),len(test_set)))
summaries=summarize_by_class(train_set)
predictions=get_predictions(summaries,test_set)
accuracy=get_accuracy(predictions,test_set)
print('Accuracy:%s'%accuracy
In[11]:main()
最终可以看到,在测试集上,分类器的准确率大概是73%(图4-4)。
图4-4 准确率