# Data in Kaggle 姓名: 羅靖皓 學號: E94071089 系級: 資訊系 111 --- ## Stroke Prediction Dataset * [Kaggle](https://www.kaggle.com/fedesoriano/stroke-prediction-dataset) ### 分析資料 此資料集用來預測中風的可能性,提供以下幾個可能與中風有關的變因: * `id`:識別身分 * `gender`:性別 * `age`:年紀 * `hypertension`:是否有高血壓 * `heart_disease`:是否有心臟疾病 * `ever_married`:是否結過婚 * `work_type`:工作類型 * `Residence_type`:居住地類型 * `avg_glucose_level`:平均血糖濃度 * `bmi`:身高體重指數 * `smoking_status`:抽菸習慣 透過分析此資料集,可以知道每種因素與中風的相關程度,更進一步可以了解高血壓與心臟疾病是否有關連、血糖濃度與高血壓間的關係,抽菸跟心臟疾病相關性等等都是值得探討的。 首先需要先處理缺失的資料: ![](https://i.imgur.com/NowLJ0a.png) 此資料集中 BMI 欄位有 201 的缺失資料,有幾種方法可以處理這類的資料: 1. 以平均值來補 2. 以中位數來補 3. 訓練模型預測 在作者的程式碼中,在作者的程式碼中,使用了 DecisionTree 模型來預測,以 `age` 和 `gender` 當作特徵。 接著從下圖可以發現,此資料集內中風與沒中風的比例相差非常高: ![](https://i.imgur.com/xQJbFW9.png) 如果直接用原本的資料集來預測的話,會產生很嚴重的問題,假設模型預測每筆資料皆為不會中風 (0),則對此訓練集而言,該模型的準確率也還能有 95.1%,如此便不能有效預測測試資料。 常見的解決方法為將增加資料使其 balanced,或是更改訓練值的影響權重。 分析男女比例與分布: ![](https://i.imgur.com/W3xNC76.png) 可以看到女生比例略高於男生,但並沒有相差太大。而分布的部分雖然類似常態分佈,但在尾端的部分略高。 分析其變因與中風的相關性,第一張圖為血糖值與 bmi 間的相對關係,並將中風與否區分;第二張圖為年紀與 bmi 間的相對關係,一樣把中風與否分開。 ![](https://i.imgur.com/rWfNI5l.png) 首先可以看到,低血糖的人得到中風的比例較少,而高血糖則相對較高,另外 bmi 對中風的影響較看不出差異,因大部任的 bmi 皆維持在 20 ~ 60 之間。第二張圖顯示出年紀與中風也有很大的關係,年紀越大者,中風的比例越高,這也符合我們的常理,另外也能發現到 BMI > 40 的人多數有著低血糖。 分析中風跟性別間的關係: ![](https://i.imgur.com/9ljCNII.png) 可以發現女生中風的比例較男生高(但這有可能是因為女生比例較高造成的),而分布圖中可以看到,女生中風通常發於高年齡層,而男生則較常出現在 55 ~ 85 歲之間。 接著將中風的人屬性取出觀察: ![](https://i.imgur.com/ivdn4Oo.png) 可以發現工作型態,婚姻狀態與居住地區對中風的影響並不大(因在中風的人內,這些屬性的每種都有佔部分比例),但唯一小比例的為工作型態為 `children` 的部分,從剛剛年紀的分析可知道,年紀越小中風比例越少,故工作型態為 `children` 的中風較少也是很合理的。 ![](https://i.imgur.com/xWbZWWh.png) 抽菸也看不出對中風是否有正相關。 透過 heatmap 分析相關性: ![](https://i.imgur.com/0bL7c1E.png) 可以發現大部分皆為藍色,表示其相關性較低,而較有相關的地方為剛剛分析過的年紀與血糖值,心臟疾病與高血壓也有些微相關。 利用抽樣方法估算中風的機率分布: ![](https://i.imgur.com/IEYSgk2.png) 看起來類似常態分佈,這邊作者假設中風與沒中風的人都是常態分佈,並且需要找出兩者的平均值與變異數,以便產生更多 data。 接著作者使用 SMOTE 演算法來產生新的資料,但可能會造成特徵對中風的影響程度受到影響。最後便能得到 1:1 的資料集,就能開始訓練模型。 另一個作者對 BMI 描繪出 Box plot: ![](https://i.imgur.com/3DzVCms.png) 可以看到 BMI 有相當多的 outlier,觀察分布圖也可以發現: ![](https://i.imgur.com/oP7TXEi.png) 一般認知的 BMI 應呈現常態分佈,但此資料集顯示該分佈已經有點歪斜 (skew) 的傾向,有可能會對預測結果產生影響。 #### 結論 從資料分析過程中可以此資料集有以下特點: * BMI > 40 的人血糖較低 * 血糖高的人較易中風 * 女生中風的年紀普遍比男生高 * 中風通常發生於高齡者上 * 工作型態為 `private` 較易中風 * 工作型態為 `children` 較不易中風 * 有結婚者較易中風 * 心臟疾病與中風無關 * 抽菸的中風機率比沒抽菸的機率較高一點 但因資料量較少且極不平衡,上述特點並不一定符合真實情況。 ### 訓練模型 ![](https://i.imgur.com/Q3XPJSl.png) 訓練 4 個模型並使用 Cross Validation 驗證,其中 Decision Tree 與 RandomForest 效能較好。此時需用 F1 Score 來評估效能而非 Accuracy,否則會產生偏差。 為了要確保模型沒有 overfitting,需要再對原本的資料集(尚未 upsample 的資料) 進行驗證: ![](https://i.imgur.com/1cokW8T.png) 可以看到結果是不錯的,大致上都能正確分類。 ![](https://i.imgur.com/fcxFPB9.png) 可以利用 Random Forest 的 importance 觀察哪些特徵是重要的: ![](https://i.imgur.com/zVAoaHW.png) 與上述分析的結果類似,年紀、酒精濃度與 BMI 是控制中風的主要因素。 訓練結果看似是好的,但這是因為資料集不夠完整,且經過 upsample 處理過,也沒有測試資料可供評估,故還是有可能是因為 overfitting 導致結果看起來不錯。需要更多的資料來驗證結果是否有偏差。 ![](https://i.imgur.com/M1hHYw8.png) 此為另一位作者使用 Neural Network 訓練出來的結果,其 F Score 約為 0.93,稍微比前者模型還差點,我認為是因為他沒有擴充資料集,而資料又相當不平衡所造成的,可以發現應該為中風的人被預測為非中風與應為非中風的人被預測為中風的比例為 2:1,故此模型傾向於將所有的人皆預測為非中風,因為此時會有較高的準確率。 ![](https://i.imgur.com/lgwOXn3.png) 此圖為使用 XGboost 訓練的結果,很明顯看到與上方相同問題,且此模型更加嚴重,將所有看到的情況都預測為非中風。 ![](https://i.imgur.com/EZaZ3TY.png) 而這個數據為另一位作者使用 Random Forest 訓練出來的結果,顯然成果沒有很好,推測是因為其擴充資料的方式為從原本的資料內複製,並不是額外新增不同屬性的資料,導致模型 overfitting,且他使用的模型為 Random forest屬性的資料,導致模型 overfitting,且他使用的模型為 Random Forest,根據 Decision Tree 的特性,相同資料越多越容易產生 overfitting,所以測試出來的結果並沒有很好。 #### 結論 在資料集較少且不平衡時,需要對資料集作處理,如 SMOTE 算法、ENN 算法或 Tomek Link 算法等,能得到較為真實的數據,但有可能會使資料集產生偏差,結果不可信的問題。 Random Forest 與 Decision Tree 在此資料集上有較好的效果,個人認為是因為特徵少,剛好與 Decision Tree 的特性符合,但也有可能是因為過擬合導致結果看似不錯,此部分需要提供更多資料集測試。 適當的假設是重要的,尤其在資料量不足時更顯得重要,如上方假設資料為常態分佈,並利用抽樣方法驗證其想法,便能更適當的理解資料,故能產生更完美的結果。 ### 實驗 將 `Smoking Status` 中 Unknown 以 Decision Tree 預測,期望能看到吸菸對中風之間的關係: ```python DT_smoke_pipe = Pipeline( steps=[ ('scale',StandardScaler()), ('lr',DecisionTreeClassifier()) ]) X = s_data[['age','gender','bmi','heart_disease','smoking_status']].copy() X.gender = X.gender.replace({'Male':0,'Female':1,'Other':-1}).astype(np.uint8) Missing = X[X.smoking_status.str.contains('Unknown')] X = X[~X.smoking_status.str.contains('Unknown')] X.smoking_status = X.smoking_status.replace({'never smoked':0,'formerly smoked':1,'smokes':2, 'Unknown':3}).astype(np.uint8) Y = X.pop('smoking_status') DT_smoke_pipe.fit(X,Y) predicted_smoke = pd.Series(DT_smoke_pipe.predict(Missing[['age','gender','bmi','heart_disease']]),index=Missing.index) s_data.loc[Missing.index,'smoking_status'] = predicted_smoke ``` ![](https://i.imgur.com/wXpIrbH.png) 結果發現吸菸者與無吸菸者比例相當接近,可見在此資料集中,吸菸對中風的影響真的無關,與模型預測的 importance 一致。 ![](https://i.imgur.com/3YLUbum.png) 觀察中風與其他變因間的關係,`heart_disease` 與 `hypertension` 的確看不出與中風有關,符合前述的預測。 ![](https://i.imgur.com/H6dLA37.png) 此圖可以發現當有心臟疾病時,其血糖分佈為呈現雙峰現象,這很有可能是因資料集內的人血糖正常值約在 150 左右,而不在 150 附近則可能為低血糖或高血糖,容易併發其他心臟疾病。 ### 資料整合 可以與其他醫病資料做結合,如病史,就醫紀錄等等,搭配 `hypertension`、`heart_disease` 等參數,便能更有效的預測中風,甚至預測中風的類型,或是者預測其他種類的疾病等等。 與飲食習慣做結合,便能分析出哪些飲食習慣與疾病之間的關聯,藉以有效防範疾病的發生,或是探討飲食習慣與 `BMI`、`smoking_status` 是否有相關等等。 ### 參考 [Analyzing and Modeling Stroke Data](https://www.kaggle.com/thomaskonstantin/analyzing-and-modeling-stroke-data) [Stroke_prediction 🧠(EDA+Classification models)](https://www.kaggle.com/ahmedterry/stroke-prediction-eda-classification-models) [Heart Stroke EDA and Prediction](https://www.kaggle.com/jeongbinpark/heart-stroke-eda-and-prediction) ###### tags: `FDA`