項目介紹
這次我們要學習的項目是糖尿病的預測,數據保存在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