การทำนายโรคหลอดเลือดในสมองโดยใช้ XGBoost ใน python
Tags: python, stroke
Published: 2024-04-16 16:00:10

บทความบน kaggle ได้นำเสนอวิธีการทำนายแนวโน้มของโรคหลอดเลือดในสมอง ซึ่งโรคหลอดเลือดในสมองเป็นสาเหตุของการเสียชีวิตที่สูงเป็นอันดับที่สองจากทั่วโลก โดยใช้ชุดข้อมูลขององค์กรอนามัยโลก(WHO) มาทำนาย เริ่มต้นจากการนำข้อมูลที่จำเป็นสำหรับการจัดการข้อมูลเข้า python และดำเนินการตามขั้นตอนการประมวลผล แกนหลักที่นำมาประยุกต์ใช้โมเดลในการเรียนรู้ขั้นสูงคือ XGBoost

> การทำนายโดยใช้ XGBoost

**ทำการ import ข้อมูล dataset จาก github** 
```
import pandas as pd
url = 'https://raw.githubusercontent.com/danielchristopher513/Brain_Stroke_Prediction_Using_Machine_Learning/main/healthcare-dataset-stroke-data.csv'
StrokeData = pd.read_csv(url)
StrokeData.head()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/um7rc01rlea6zi39jknm.png)


> ฟังก์ชัน.info()

ฟังก์ชัน .info() จะแสดงข้อมูลพื้นฐานของ Dataset ที่เราเลือกมา เช่น จำนวน columns ชนิดของข้อมูล จำนวนข้อมูลที่ไม่ใช่ค่าว่าง(null) และหน่วยความจำ
```
StrokeData.info()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27ss6sompkwc9bq41ism.png)


> ฟังก์ชัน.describe()

ฟังก์ชัน.describe() จะแสดงข้อมูลสถิติเชิงลึกของข้อมูลที่เป็นตัวเลขใน Dataset เช่น ค่าเฉลี่ย ส่วนเบี่ยงเบนมาตรฐาน เป็นต้น
```
StrokeData.describe()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80fqgoljfyf9020d0sdr.png)


> ฟังก์ชัน.isnull() และ .sum()

ฟังก์ชัน.isnull() ฟังก์ชันที่ใช้ตรวจสอบค่าที่หายไปของ Dataset โดยจะใช้ True แทนค่าที่หายไปและใช้ False แทนค่าที่มีอยู่
ฟังก์ชัน.sum() ฟังก์ชันที่จะรวมค่าของ True ในแต่ละ columns เพื่อให้รู้ว่าในแต่ละ columns มีจำนวนค่าที่หายไปเท่าไหร่
```
StrokeData.isnull().sum()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t63fkdfu4nzm86rddgrz.png)


> ฟังก์ชัน.duplicated() และ .sum()

ฟังก์ชัน.duplicated() ฟังก์ชันที่ใช้ตรวจสอบค่าที่ซ้ำกันใน Dataset โดยจะใช้ True แทนค่าที่ซ้ำกันและใช้ False แทนค่าที่ไม่ซ้ำกัน
ฟังก์ชัน.sum() ฟังก์ชันที่จะรวมค่าของ True ในแต่ละ columns เพื่อให้รู้ว่าในแต่ละ columns มีจำนวนค่าที่ซ้ำกันไปเท่าไหร่
```
StrokeData.duplicated().sum()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f94gumke0vlqjurhof0r.png)


> สร้างแผนที่ความร้อน

- import seaborn ใช้สร้างกราฟและ visualization เพื่อใช้วิเคราะห์ข้อมูล
```
import seaborn as sns
```
- import matplotlib.pyplot ใช้สร้างกราฟและภาพถ่าย
```
import matplotlib.pyplot as plt
```
- import LabelEncoder และ StandardScaler ทั้งสองเป็น class ของ sklearn.preprocessing โดยใช้แปลงข้อมูลแบบหมวดหมู่เป็นตัวเลขและปรับข้อมูลให้มี mean เท่ากับ 0 และ standard deviation เท่ากับ 1 เพื่อนำข้อมูลเข้าสู่ขั้นตอนการฝึกโมเดล
```
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
label_encoder = LabelEncoder()
scaler= StandardScaler()
df = StrokeData.apply(lambda x: label_encoder.fit_transform(x) if x.dtype == 'O' else x)
Stroke_dataup = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)
```
- คำนวณค่าของเมทริกซ์ใน DataFrame โดยใช้เมทริกซ์ความสัมพันธ์ของ pandas (cov()) และเปลี่ยนทุกค่าในเมทริกซ์ให้เป็นค่าบวกด้วย abs()
```
cov_matrix = abs(Stroke_dataup.cov())
```
- กำหนดรูปภาพให้มีขนาด 10x10
```
plt.figure(figsize=(10, 10))
```
- สร้างแผนที่ความร้อนจาก cov_matrix โดยกำหนดให้แสดงค่าตัวเลขด้วย annot=True และใช้สี cmap='copper' ในการแสดงผล ซึ่งกำหนดรูปแบบของตัวเลขในด้วย fmt='.2f'
```
sns.heatmap(cov_matrix, annot=True, cmap='copper', fmt='.2f', linewidths=.5)
```
- กำหนดหัวข้อของแผนที่ความร้อนและแสดงกราฟของแปนที่ความร้อน
```
plt.title('Covariance Matrix Heatmap')
plt.show()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cdk9wnm15kspxpn7mxr5.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cpfkxb9kpqrper8vp77z.png)

ผลลัพธ์ที่ได้คือแผนที่ความร้อนแสดงความสัมพันธ์ระหว่างคู่ของคุณลักษณะ (features) ใน Dataset ซึ่งสามารถช่วยในการวิเคราะห์และเข้าใจความสัมพันธ์ระหว่างข้อมูลได้ง่ายขึ้น เช่น สีสว่างแสดงถึงความสัมพันธ์บวกและสีเข้มแสดงถึงความสัมพันธ์ลบ ตามค่าที่แสดงในแต่ละช่องของแผนที่ความร้อน


> Drop

ปรับข้อมูลใน DataFrame โดยกำหนดให้ลบคอลัมน์ที่มีชื่อว่า 'id' และ 'gender' ออกจาก DataFrame โดยใช้ .drop() กับพารามิเตอร์ axis=1 เพื่อกำหนดว่าจะลบคอลัมน์ไหน เพื่อไม่ให้การเปลี่ยนแปลงนี้ส่งผลต่อ DataFrame และทำการเก็บผลลัพธ์ใน DataFrame
```
df=df.drop([ 'id', 'gender' ], axis=1)
X_StrokeData=df.drop(['stroke'], axis=1)
Y_StrokeData=df['stroke']
X_StrokeData = pd.DataFrame(scaler.fit_transform(X_StrokeData), columns=X_StrokeData.columns)
```


> XGBoost

ใช้ XGBoost และ cross-validation เพื่อประเมินประสิทธิภาพของโมเดลโดย
- โหลดไลบรารี XGBoost 
- โหลดฟังก์ชัน KFold และ cross_val_score จากไลบรารี sklearn.model_selection เพื่อทำ Cross-validation
- กำหนดโมเดล XGBoost โดยใช้ XGBClassifier และกำหนดพารามิเตอร์ต่าง ๆ
- กำหนด KFold เพื่อทำ Cross-validation โดยกำหนดจำนวน Split และค่า random_state
- ใช้ cross_val_score เพื่อประเมินประสิทธิภาพของโมเดล
```
import xgboost as xgb
from sklearn.model_selection import KFold, cross_val_score

model = xgb.XGBClassifier(
    n_estimators=100,
    max_depth=5,
    learning_rate=0.2,
    objective='binary:logistic',
    random_state=42
)

kf = KFold(n_splits=4, shuffle=True, random_state=42)
cv_results = cross_val_score(model, X_StrokeData, Y_StrokeData, cv=kf, scoring='accuracy')
accuracy = cv_results
average_accuracy = cv_results.mean()
```
- คำนวณความแม่นยำของแต่ละรอบ และความแม่นยำเฉลี่ยของทั้งหมด
- แสดงผลลัพธ์ความแม่นยำในแต่ละรอบ และความแม่นยำเฉลี่ยทั้งหมด
```
print("Accuracy for each fold:", accuracy)
print("Average Accuracy across all folds:", average_accuracy)
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i838zdduvgenf44dw1lu.png)


> ถ้าเราลองลบคอลัมน์ให้เหลือแค่ 5 คอลัมน์จะเกิดอะไรขึ้น

```
StrokeData = StrokeData[['age', 'hypertension',
       'heart_disease','avg_glucose_level','stroke']]

StrokeData.head()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k0oabyrevhswohozsafn.png)

```
StrokeData.info()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ioyx491k7k350860qbx5.png)

```
StrokeData.describe()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1poh15jx4xpig472dpc.png)

```
StrokeData.isnull().sum()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gwjofd5nxijaijtbk7zr.png)

```
StrokeData.duplicated().sum()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gulx8fh6txcyfcn9eh36.png)
```
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
label_encoder = LabelEncoder()
scaler= StandardScaler()
df = StrokeData.apply(lambda x: label_encoder.fit_transform(x) if x.dtype == 'O' else x)
Stroke_dataup = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)
cov_matrix = abs(Stroke_dataup.cov())
plt.figure(figsize=(5, 5))
sns.heatmap(cov_matrix, annot=True, cmap='copper', fmt='.2f', linewidths=.5)
plt.title('Covariance Matrix Heatmap')
plt.show()
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7vcyqexqktluvhr8s80.png)

```
import xgboost as xgb
from sklearn.model_selection import KFold, cross_val_score

model = xgb.XGBClassifier(
    n_estimators=100,
    max_depth=5,
    learning_rate=0.2,
    objective='binary:logistic',
    random_state=42
)

kf = KFold(n_splits=4, shuffle=True, random_state=42)
accuracy = cv_results
average_accuracy = cv_results.mean()

print("Accuracy for each fold:", accuracy)
print("Average Accuracy across all folds:", average_accuracy)
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zlnqbrvwzmks9mu8t3k.png)

> สรุปผล

เมื่อเราได้ใช้ XGBoost และกระบวนการ Cross-validation ในการทำนายโรคหลอดเลือดในสมองโดยตัวอย่างแรกใช้ชุด Dataset ทั้งหมด ผลลัพธ์ที่ได้คือค่าความแม่นยำของโมเดล = 0.947 และตัวอย่างที่สองได้ลบคอลัมน์ให้เหลือเพียง 5 คอลัมน์ ผลลัพธ์ที่ได้คือค่าความแม่นยำของโมเดล = 0.948 ซึ่งค่าความแม่นยำยิ่งมีค่ามากยิ่งดี

> References 

https://www.kaggle.com/code/chiragchiku25/stroke-prediction-using-xgboost
https://www.kaggle.com/code/onurrr90/heart-science-stroke-prediction-with-ai