實戰 | 糖尿病預測項目

項目介紹

這次我們要學習的項目是糖尿病的預測,數據保存在diabetes.csv文件中。數據一共有8個特徵和1個標籤:

Pregnancies:懷孕次數Glucose:葡萄糖測試值BloodPressure:血壓SkinThickness:皮膚厚度Insulin:胰島素BMI:身體質量指數DiabetesPedigreeFunction:糖尿病遺傳函數Age:年齡Outcome:糖尿病標籤,1表示有糖尿病,0表示沒有糖尿病


首先先載入一些常用模塊

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import seaborn as sns


然後用pandas讀入數據

diabetes_data = pd.read_csv('diabetes.csv')

diabetes_data.head()




# 查看數據信息

diabetes_data.info(verbose=True)


<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

我們從上面可以看到一共有768個數據,並且所有的特徵和標籤都是768個值,所有沒有缺失數據。並且所有數據都是數值類型(int64 or float64)的數據。


# 數據描述

diabetes_data.describe()



通過describe我們可以觀察到數據的數量,平均值,標準差,最小值,最大值等數據。


# 數據形狀

diabetes_data.shape

(768, 9)


# 查看標籤分佈

print(diabetes_data.Outcome.value_counts())

# 使用柱狀圖的方式畫出標籤個數統計

p=diabetes_data.Outcome.value_counts().plot(kind="bar")

0    500

1    268

Name: Outcome, dtype: int64




# 可視化數據分佈

p=sns.pairplot(diabetes_data, hue = 'Outcome')



圖片可能需要放大才能看清楚。這裏畫的圖主要是兩種類型,直方圖和散點圖。單一特徵對比的時候用的是直方圖,不同特徵對比的時候用的是散點圖,顯示兩個特徵的之間的關係。觀察數據分佈我們可以發現一些異常值,比如Glucose葡萄糖,BloodPressure血壓,SkinThickness皮膚厚度,Insulin胰島素,BMI身體質量指數這些特徵應該是不可能出現0值的。但是數據分佈中卻有很多0值。


# 把葡萄糖,血壓,皮膚厚度,胰島素,身體質量指數中的0替換爲nan

colume = ['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI']

diabetes_data[colume] = diabetes_data[colume].replace(0,np.nan)


# 查看數據空值情況

import missingno as msno

p=msno.bar(diabetes_data)



圖中可以看到葡萄糖,血壓,皮膚厚度,胰島素,身體質量指數都是存在空值的,並且皮膚厚度和胰島素中的空值特別多。


# 設定閥值

thresh_count = diabetes_data.shape[0]*0.8

# 若某一列數據缺失的數量超過20%就會被刪除

diabetes_data = diabetes_data.dropna(thresh=thresh_count, axis=1)

p=msno.bar(diabetes_data)



把空值超過20%的特徵都去除掉之後,只剩下6個特徵。


# 導入插補庫

from sklearn.preprocessing import Imputer

# 對數值型變量的缺失值,我們採用均值插補的方法來填充缺失值

imr = Imputer(missing_values='NaN', strategy='mean', axis=0)

colume =  ['Glucose', 'BloodPressure', 'BMI']

# 進行插補

diabetes_data[colume] = imr.fit_transform(diabetes_data[colume])

p=msno.bar(diabetes_data)



使用特徵的平均值給特徵中的缺失值進行填充,填充後所有的數據就沒有空值了。


plt.figure(figsize=(12,10))  

# 畫熱力圖,數值爲兩個變量之間的相關係數

p=sns.heatmap(diabetes_data.corr(), annot=True)



熱力圖可能也需要放大來看,它是表示兩個數據之間的相關性,數值範圍是-1到1之間,大於0表示兩個數據是正相關的,小於0表示兩個數據是負相關的,等於0就是不相關。我們可以看到有一條對角線上的數值都是1,兩個數據如果是相同的兩個數據,那麼他們的相關係數就是1。並且這個相關係數矩陣是對稱的。


我們可以觀察到一些比較明顯的特徵,比如Age年齡跟Pregnancies懷孕次數有比較強的相關性,也就是說年齡越大懷孕次數就越多,或者懷孕次數越多年齡就越大,這應該是比較合理的一個情況。


糖尿病的標籤Outcome和Glucose葡萄糖測試值正相關係數比較大,也就是說葡萄糖測試值比較高的話,那麼就很可能患有糖尿病。


# 把數據切分爲特徵x和標籤y

x = diabetes_data.drop("Outcome",axis = 1)

y = diabetes_data.Outcome from sklearn.model_selection import train_test_split

# 切分數據集,test_size=0.3表示30%爲測試集。stratify=y表示切分後訓練集和測試集中的數據類型的比例跟切分前y中的比例一致

# 比如切分前y中0和1的比例爲1:2,切分後y_train和y_test中0和1的比例也都是1:2

x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3, stratify=y)


# 導入KNN算法

from sklearn.neighbors import KNeighborsClassifier

# 保存不同k值測試集準確率

test_scores = []

# 保存不同k值訓練集準確率

train_scores = []

x_train_values = x_train.values

y_train_values = y_train.values

# 設置30個k值

k = 30

for i in range(1,k):

    knn = KNeighborsClassifier(i)

    knn.fit(x_train,y_train)

    # 保存測試集準確率

    test_scores.append(knn.score(x_test,y_test))

    # 保存訓練集準確率

    train_scores.append(knn.score(x_train,y_train))


plt.title('k-NN Varying number of neighbors')

plt.plot(range(1,k),test_scores,label="Test")

plt.plot(range(1,k),train_scores,label="Train")

plt.legend()

plt.xticks(range(1,k))

plt.xlabel('k')

plt.ylabel('accuracy')

plt.show()



不同k值得到不同的準確率結果。


# 選擇一個最好的k值作爲模型參數

k = np.argmax(test_scores)+1

knn = KNeighborsClassifier(k)

knn.fit(x_train,y_train)

knn.score(x_test,y_test)

0.8138528138528138


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))

              precision    recall  f1-score   support


           0       0.88      0.84      0.86       157

           1       0.69      0.76      0.72        74


   micro avg       0.81      0.81      0.81       231

   macro avg       0.79      0.80      0.79       231

weighted avg       0.82      0.81      0.82       231

macro avg:宏平均,所有類的算數平均數micro avg:分母就是輸入分類器的預測樣本個數,分子就是預測正確的樣本個數weighted avg:加權平均,每個類別的權值爲:類別suppot/總suppot


confusion = confusion_matrix(y_pred, y_test)

df_cm = pd.DataFrame(confusion)

sns.heatmap(df_cm, annot=True)



混淆矩陣,測試集中非糖尿病被預測爲非糖尿病有130例,糖尿病被預測爲糖尿病有56例,非糖尿病被預測爲糖尿病有25例,糖尿病被預測爲非糖尿病有18例子。



項目打包

糖尿病預測項目

百度雲:https://pan.baidu.com/s/1nscdWSkU3FqhyGbZAwH6bA 

提取碼:y91a 






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章