一、问题描述
利用机器学习算法实现糖尿病数据集的二分类问题。
二、数据集分析
- 糖尿病数据集中一共有768个样本,每个样本有8个特征和1个对应的标签
Pregnancies | 怀孕次数 |
Glucose | 葡萄糖测试值 |
BloodPressure | 血压 |
SkinThickness | 皮肤厚度 |
Insulin | 胰岛素 |
BMI | 身体质量指数 |
DiabetesPedigreeFunction | 糖尿病遗传函数 |
Age | 年龄 |
Outcome | 糖尿病标签,1表示有糖尿病,0表示没有糖尿病 |
- 数据集下载地址为:https://www.kaggle.com/saurabh00007/diabetescsv
- 打开diabetes.csv,数据格式如下:
三、代码实现
import numpy as py
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
diabetes_data = pd.read_csv('diabetes.csv')
print(diabetes_data.head())
# 查看数据信息
print(diabetes_data.info(verbose=True))
# 设置参数verbose为True,允许冗长信息
# 数据描述
print(diabetes_data.describe())
# 通过describe可以观察到数据的数量,平均值,标准差,最小值,最大值等数据
#数据形状
print("dimension of diabetes data: {}".format(diabetes_data.shape))
#查看标签分布
print(diabetes_data.Outcome.value_counts())
#使用柱状图的方式画出标签个数统计
plt.figure()
diabetes_data.Outcome.value_counts().plot(kind="bar")
plt.figure()
sns.countplot(diabetes_data['Outcome'], label="Count")
plt.savefig("0_1_graph")
# 可视化数据分布
# 对角线上是各个属性的直方图(分布图)
# 而非对角线上是两个不同属性之间的相关图
plt.figure()
sns.pairplot(diabetes_data)
plt.savefig("0_2_graph")
'''
sns.pairplot(diabetes_data, hue="Outcome");
plt.savefig("0_3_grap")
'''
# 画热力图,数值为两个变量之间的相关系数
# annot: 默认为False,为True,在格子上显示数字
plt.figure()
sns.heatmap(diabetes_data.corr(), annot=True)
plt.savefig("0_4_grap")
# KNN算法
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(\
diabetes_data.loc[:,diabetes_data.columns !='Outcome'],\
diabetes_data['Outcome'],stratify=diabetes_data['Outcome'],random_state=66)
# 把数据切分为特征X和标签y
# 切分数据集,test_size=0.3表示30%为测试集。
# stratify=y表示切分后训练集和测试集中的数据类型的比例跟切分前y中的比例一致
# 如切分前y中0和1的比例为1:2,切分后y_train和y_test中0和1的比例也都是1:2
#X = diabetes_data.drop("Outcome",axis = 1)
#y = diabetes_data.Outcome
#X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3, stratify=y)
from sklearn.neighbors import KNeighborsClassifier
# 保存不同k值测试集准确率
training_accuracy = []
# 保存不同k值训练集准确率
test_accuracy = []
# try n_neighbors from 1 to 10
neighbors_settings = range(1,11)
for n_neighbors in neighbors_settings:
# build the model
knn = KNeighborsClassifier(n_neighbors = n_neighbors)
knn.fit(X_train,y_train)
#record training set accuracy 保存训练集准确率
training_accuracy.append(knn.score(X_train,y_train))
#record test set accuracy 保存测试集准确率
test_accuracy.append(knn.score(X_test,y_test))
plt.figure()
plt.plot(neighbors_settings,training_accuracy,label="training accuracy")
plt.plot(neighbors_settings,test_accuracy,label="test accuracy")
plt.ylabel("Accuracy")
plt.xlabel("n_neighbors")
plt.legend() # 给图像加上图例
plt.savefig('knn_compare_model')
knn = KNeighborsClassifier(n_neighbors=9)
knn.fit(X_train,y_train)
print('Accuracy of K-NN classifier on training set:{:.2f}'.format(\
knn.score(X_train,y_train)))
print('Accuracy of K-NN classifier on training set:{:.2f}'.format(\
knn.score(X_test,y_test)))
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
y_pred = knn.predict(X_test)
print(classification_report(y_pred, y_test))
confusion = confusion_matrix(y_pred, y_test)
df_cm = pd.DataFrame(confusion)
plt.figure()
sns.heatmap(df_cm, annot=True)
plt.savefig('confusion_matrix')
plt.show()
补充说明:
- sns.heatmap()用于绘制热力图,热力图表示的是两个数据之间的相关性,数值范围是-1到1之间,大于0表示两个数据之间是正相关的,小于0表示两个数据之间是负相关的,等于0就是不相关。
-
从上述热力图可以看出一些明显的特征,如糖尿病的标签Outcome和葡萄糖测试值Glucose正相关系数比较大,说明葡萄糖测试值高的话,有可能患有糖尿病。同理,年龄Age和怀孕次数Pregnancies之间的相关性也比较强。
- sns.pairplot()用于展示属性两两之间的关系,线性、非线性、相关等等。
- confusion_matrix()混淆矩阵,是模型评估的方法之一,在机器学习中总结分类模型预测结果的情形分析表,以矩阵形式将数据集中的记录按照真实的类别与分类模型预测的类别判断两个标准进行汇总。以下是二分类的矩阵表现形式。
- TP(True Positive):将正类预测为正类数,真实为0,预测也为0
- FN(False Negative):将正类预测为负类数,真实为0,预测为1
- FP(False Positive):将负类预测为正类数, 真实为1,预测为0
- TN(True Negative):将负类预测为负类数,真实为1,预测也为1
- 对于二分类问题来说,精确率Precision=a/(a+c)=TP/(TP+FP),召回率recall=a/(a+b)=TP/(TP+FN),准确率accuracy=(a+d)/(a+b+c+d)=(TP+FN+FP+TN),可以看到准确率中的分子值就是矩阵对角线上的值。
- Python中的sklearn库提供了confusion_matrix()方法来输出矩阵数据,具体函数定义为:
-
sklearn.metrics.confusion_matrix(y_true, y_pred, labels=None, sample_weight=None):其中,y_true:是样本真实分类结果,y_pred 是样本预测分类结果 ,labels是所给出的类别,通过这个可对类别进行选择 ,sample_weight 是样本权重。
-
混淆矩阵可以看出,测试集中非糖尿病被预测为非糖尿病有100例,糖尿病被预测为糖尿病有44例,非糖尿病被预测为糖尿病有23例,糖尿病被预测为非糖尿病有20例。
- range(1,11)的类型并非list,在进行print的时候,需要将其转换为list,才可以将列表中的数据一一打印出来,即print(list(range(1,11)))。
- 本例中通过一个循环寻找最佳的K值,不同的K值得到不同的准确率结果。下图展示了训练集和测试集在模型预测准确度和近邻点个数之间的关系,从图中可以看出,如果选择一个近邻点,训练集的预测是绝对正确的,随着近邻点的增加,训练集的准确度下降,而测试集准确度上升,最终选择K=9。
-
四、算法分析
- 此案例依然采用了KNN,K最近邻算法,具体算法说明可以参考实验一:鸢尾花数据集分类。接下来可以利用线性逻辑回归,决策树,随机森林,支持向量机,深度学习等多种算法来实现分类预测。