端对端数据科学示例:使用Logistic回归预测糖尿病机器学习模型
本教程是使用数据科学解决实际问题的端到端示例。根据患者的信息,如血压,体重指数(BMI),年龄等,我们将使用机器学习来预测一个人是否患有糖尿病。本教程将介绍数据科学的各个阶段流程。特别是,本教程包含以下部分
概观
数据描述
数据探索
数据准备
培训和评估机器学习模型
解释ML模型
保存模型
用模型预测
概观
这些数据是由“国家糖尿病和消化和肾脏疾病研究所”收集并提供的,作为皮马印第安人糖尿病数据库的一部分(https://www.kaggle.com/uciml/pima-indians-diabetes-database/data)。从较大的数据库中选择这些实例有几个约束条件。特别是,这里的所有患者都属于皮马印第安人遗产(美国原住民子群),并且都是21岁及以上的女性。
我们将使用Python和一些流行的数据科学相关软件包。首先,我们将导入pandas从CSV文件中读取我们的数据,并对其进行处理以供进一步使用。我们还将使用numpy将数据转换为适合我们分类模型的格式。我们将使用seaborn和matplotlib进行可视化。然后我们将从中导入Logistic回归算法sklearn。这个算法将帮助我们建立我们的分类模型。最后,我们将使用joblib可sklearn用于保存我们的模型以供将来使用。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
% matplotlib inline
from sklearn.linear_model import LogisticRegression
from sklearn.externals import joblib
数据描述
我们将我们的数据保存在名为的CSV文件中diabetes.csv。我们首先将我们的数据集读入名为的pandas 数据框 diabetesDF,然后使用该head()函数显示数据集中的前五条记录。
diabetesDF = pd.read_csv('diabetes.csv')
print(diabetesDF.head())
以下功能可帮助我们预测一个人是否患有糖尿病:
Pregnancies:怀孕的次数
Glucose:在口服葡萄糖耐量试验中超过2小时的血浆葡萄糖浓度
BloodPressure:血压舒张压(mm Hg)
SkinThickness:三头肌皮褶厚度(mm)
insulin: 2小时血清胰岛素(mu U / ml)
BMI:体重指数(体重公斤/(身高米)2)
DiabetesPedigreeFunction:糖尿病谱系功能(根据家族史记录糖尿病可能性的函数)
Age:年龄(岁)
Outcome:类别变量(如果非糖尿病为0,糖尿病为1)
我们还要确保我们的数据是干净的(没有空值等)。
diabetesDF.info() # output shown below
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 768 entries, 0 to 767
Data columns (total 9 columns):
Pregnancies 768 non-null int64
Glucose 768 non-null int64
BloodPressure 768 non-null int64
SkinThickness 768 non-null int64
Insulin 768 non-null int64
BMI 768 non-null float64
DiabetesPedigreeFunction 768 non-null float64
Age 768 non-null int64
Outcome 768 non-null int64
dtypes: float64(2), int64(7)
memory usage: 54.1 KB
请注意,在前面的图中,数据确实有一些缺失值(参见胰岛素= 0)。理想情况下,我们可以将这些0值替换为该特性的平均值,但我们现在就跳过这个。
数据探索
现在让我们探索一下我们的数据集,我们首先找到每对特征(和结果变量)的相关性,并使用热图可视化相关性。
corr = diabetesDF.corr()
print(corr)
sns.heatmap(corr,
xticklabels=corr.columns,
yticklabels=corr.columns)
在上面的热图中,较亮的颜色表示更多的相关性。从表格和热图中可以看出,血糖水平,年龄,BMI和怀孕次数均与结局变量有显着相关性。还要注意特征对之间的相关性,如年龄和怀孕,或胰岛素和皮肤厚度。
我们还要看看数据集中有多少人患有糖尿病,多少人不是。下面是同样的图形:
可视化单个变量与结果之间的关系也很有帮助。下面,我们将看到年龄和结果之间的关系。您可以同样可视化其他功能。该图是每个输出类别的平均年龄的图表。我们可以看到糖尿病患者的平均年龄较高。
数据集准备
当使用机器学习算法时,我们应该总是将我们的数据分成训练集和测试集。(如果我们运行的实验数量很大,那么我们可以将我们的数据分成3部分,即 - 训练集,开发集和测试集)。在我们的案例中,我们还将分离出一些手动交叉检查的数据。
数据集包括总共767名患者的记录。为了训练我们的模型,我们将使用650条记录。我们将使用100个记录进行测试,并使用最后的17条记录来检查我们的模型。
dfTrain = diabetesDF[:650]
dfTest = diabetesDF[650:750]
dfCheck = diabetesDF[750:]
接下来,我们将标签和特征(针对训练和测试数据集)分开。除此之外,我们还将它们转换为NumPy数组,作为我们的机器学习算法以NumPy数组格式处理数据。
trainLabel = np.asarray(dfTrain['Outcome'])
trainData = np.asarray(dfTrain.drop('Outcome',1))
testLabel = np.asarray(dfTest['Outcome'])
testData = np.asarray(dfTest.drop('Outcome',1))
作为使用机器学习之前的最后一步,我们将标准化我们的输入。机器学习模型常常从输入标准化中获益。这也让我们更容易理解稍后每个功能的重要性,当时我们将看看模型权重。我们将数据标准化,使得每个变量的均值为0,标准差为1。
means = np.mean(trainData, axis=0)
stds = np.std(trainData, axis=0)
trainData = (trainData - means)/stds
testData = (testData - means)/stds
# np.mean(trainData, axis=0) => check that new means equal 0
# np.std(trainData, axis=0) => check that new stds equal 1
训练和评估机器学习模型
我们现在可以训练我们的分类模型。我们将使用一种称为逻辑回归的机器简单学习模型。由于该模型易于在sklearn中使用,因此培训过程非常简单,我们可以通过几行代码完成。首先,我们创建一个名为diabetesCheck的实例,然后使用拟合函数来训练模型。
diabetesCheck = LogisticRegression()
diabetesCheck.fit(trainData, trainLabel)
接下来,我们将使用我们的测试数据来找出模型的准确性。
accuracy = diabetesCheck.score(testData, testLabel)
print("accuracy = ", accuracy * 100, "%")
打印语句将打印accuracy = 78.0 %
解释ML模型
为了更好地理解逻辑回归模型内部发生的事情,我们可以将我们的模型如何使用不同的特征以及哪些特征具有更大的影响。
coeff = list(diabetesCheck.coef_[0])
labels = list(trainData.columns)
features = pd.DataFrame()
features['Features'] = labels
features['importance'] = coeff
features.sort_values(by=['importance'], ascending=True, inplace=True)
features['positive'] = features['importance'] > 0
features.set_index('Features', inplace=True)
features.importance.plot(kind='barh', figsize=(11, 6),color = features.positive.map({True: 'blue', False: 'red'}))
plt.xlabel('Importance')
从上图可以得出以下结论。
血糖水平,BMI,妊娠和糖尿病谱系功能对模型有显着影响,特别是血糖水平和BMI。我们很高兴看到我们的机器学习模型与我们一生从医生那里听到的信息相匹配!
血压对预测有负面影响,即高血压与没有患糖尿病的人相关。(另外请注意,血压作为一个特征比年龄更重要,因为血压的幅度更高)。
虽然年龄与BMI相关的输出变量(如我们在数据探索期间看到的)更相关,但该模型更多地依赖于BMI。这可能由于多种原因而发生,包括年龄所捕获的相关性也被某些其他变量捕获的事实,而由BMI捕获的信息未被其他变量捕获。
请注意,上述解释要求我们的输入数据被标准化。没有这一点,我们不能声称重要性与权重成正比。
保存模型
现在我们将保存我们训练有素的模型以备将来使用joblib。
joblib.dump([diabetesCheck, means, stds], 'diabeteseModel.pkl')
为了检查我们是否正确保存了模型,我们将使用我们的测试数据来检查我们保存的模型的准确性(如果我们已经妥善保存,我们应该观察到准确性没有变化)。
diabetesLoadedModel, means, stds = joblib.load('diabeteseModel.pkl')
accuracyModel = diabetesLoadedModel.score(testData, testLabel)
print("accuracy = ",accuracyModel * 100,"%")
用模型进行预测
我们现在将使用我们未使用的数据来了解如何进行预测。我们在dfCheck中有我们未使用的数据。
print(dfCheck.head())
我们现在将使用第一个记录来做出我们的预测。
sampleData = dfCheck[:1]
# prepare sample
sampleDataFeatures = np.asarray(sampleData.drop('Outcome',1))
sampleDataFeatures = (sampleDataFeatures - means)/stds
# predict
predictionProbability = diabetesLoadedModel.predict_proba(sampleDataFeatures)
prediction = diabetesLoadedModel.predict(sampleDataFeatures)
print('Probability:', predictionProbability)
print('prediction:', prediction)
从上面的代码我们得到:
Probability: [[ 0.4385153, 0.5614847]]
prediction: [1]
数组预测概率0.438 的第一个元素是类别为0的概率,第二元素0.561是类别为1的概率。概率总和为1.正如我们可以看到1是更可能的类,我们得到[1]作为我们的预测,这意味着该模型预测该人患有糖尿病。
下一步
有很多方法可以改进上述模型。这里有一些想法。
输入功能bucketing应该有所帮助,即为特定范围内的血压,特定范围内的血糖水平等创建新的变量。
您还可以通过用平均值替换0值来改善数据清理。
阅读一下医生最依赖哪些指标来诊断糖尿病患者,并相应地创建新函数。
看看你是否可以达到85-90%的准确性。