knowledge-sharing-heart-attack-prediction-banner
knowledge-sharing-heart-attack-prediction-banner
knowledge-sharing-heart-attack-prediction-banner

Chhorpeanraingsey Thab, Pauruetai Kobsahai, Phongsakorn Thong-aem, Krittapol damrongkamoltip

27 ก.พ. 2567

Knowledge Sharing : Heart Attack Analysis&Prediction Dataset

Knowledge Sharing : Heart Attack Analysis&Prediction Dataset

ทำไมจึงต้องทำนายโรคหัวใจ?

หัวใจวาย” เป็นปัญหาสุขภาพที่ร้ายแรงในทั่วโลก อีกทั้งยังมีอัตราการเสียชีวิตเพิ่มสูงและมีแนวโน้มที่จะเพิ่มขึ้นอย่างต่อเนื่อง การคาดการณ์โรคหัวใจวายตั้งแต่เนิ่นๆ จึงเป็นส่วนสำคัญของการวิจัยทางการแพทย์ และปัจจุปันที่ความก้าวหน้าของการวิเคราะห์ข้อมูล จึงทำให้การคาดการณ์นั้นมีความแม่นยำมากยิ่งขึ้น ทำให้เห็นถึงแนวโน้มเพื่อคัดกรองของผู้ป่วย

ดังนั้นโปรเจคนี้มุ่งเน้นไปที่การพัฒนาโมเดลเพื่อทำนายความเป็นไปได้ของการเกิดอาการหัวใจวายในแต่ละบุคคลเพื่อช่วยลดอัตราการเสียชีวิตจากโรคหัวใจและลดความเสี่ยงในการเกิดโรคหัวใจ

why-should-we-do-a-heart-attack-analysis 

ภาพรวมของข้อมูล (Overview)

แหล่งข้อมูลที่ใช้ในการวิเคราะห์

ในการทำนายนี้นั้น ได้เลือก Heart Attack Analysis & Prediction Dataset จาก Rashik Rahman มาเป็นชุดข้อมูลในการทำนาย ชุดข้อมูลนี้เป็นชุดข้อมูลที่เกี่ยวกับผลการตรวจร่างกายของผู้ป่วยที่สัมพันธ์กับการเกิดโรคหัวใจ โดยเรามาเริ่มทำความเข้าใจรายละเอียดของข้อมูลกันก่อน ซึ่งชุดข้อมูลนี้ประกอบไปด้วย 14 คอลัมน์ ได้แก่

  1. Age : อายุของผู้ป่วย (ปี)

  2. Sex : เพศของผู้ป่วย

  3. cp : ชนิดของอาการปวดหน้าอก

    1. ค่า 0 : อาการหน้าอกแน่นแบบเฉพาะ (typical angina)

    2. ค่า 1 : อาการหน้าอกแน่นแบบไม่เฉพาะ (atypical angina)

    3. ค่า 2 : อาการปวดที่ไม่เกี่ยวกับหน้าอก (non-anginal pain)

    4. ค่า 3 : ไม่แสดงอาการ (asymptomatic)

  4. trtbps: ความดันโลหิตขณะพัก (เป็นมม. ปรอท)

  5. chol: คอเลสเตอรอลในเลือด (mg/dl) วัดผ่านเซ็นเซอร์ BMI

  6. fbs : (น้ำตาลในเลือดขณะท้องว่าง > 120 mg/dl) (1 = ใช่; 0 = ไม่ใช่)

  7. restecg : ผลการตรวจคลื่นไฟฟ้าหัวใจขณะพัก

    1. ค่า 0 : ปกติ

    2. ค่า 1 : มีความผิดปกติของคลื่น ST-T (ความผิดปกติของคลื่น T และ/หรือ ระดับคลื่น ST สูงหรือต่ำกว่า 0.05 mV)

    3. ค่า 2 : แสดงความเป็นไปได้หรือแน่ชัดของภาวะซ้ายบางส่วนของหัวใจโดยเกณฑ์ของ Estes

  8. thalach : อัตราการเต้นของหัวใจสูงสุดที่ได้

  9. exng : อาการหน้าอกแน่นเนื่องจากการออกกำลังกาย (1 = ใช่; 0 = ไม่ใช่)

  10. oldpeak : ค่า ST depressed เป็นการตรวจการทำงานของหัวใจโดยการออกกำลังกาย

  11. slp : ค่าความชันเมื่อออกกำลังกายระดับเข้มข้น

    1. ค่า 0 : การเต้นของหัวใจอยู่ในระดับดี (Unsloping)

    2. ค่า 1 : การเต้นของหัวใจอยู่ในระดับปกติ (Flatsloping)

    3. ค่า 2 : สัญญาณบอกถึงหัวใจที่ไม่แข็งแรง (Downsloping)

  12. caa : จำนวนหลอดเลือดหลักที่ผ่านการตรวจด้วยเครื่องเอ็กซเรย์มีค่า 0–3

  13. thall : โรคเลือดที่เรียกว่าธาลัสซีเมีย

    1. ค่า 0 : ปกติ (Normal)

    2. ค่า 1 : ประเภทเลือดไหลไปที่กล้ามเนื้อหัวใจบางส่วน (Fixed Defect)

    3. ค่า 2 : ประเภทไม่มีเลือดไหลไปที่กล้ามเนื้อหัวใจ (Reversible Defect)

    4. ค่า 3 : Thalassemia

  14. output : 0 = โอกาสน้อยที่จะเกิดอาการหัวใจวาย 1 = โอกาสมากที่จะเกิดอาการหัวใจวาย


สามารถดูรายละเอียดเชิงลึกได้ ที่นี่



Load Data

เมื่อเรารู้จักกับชุดข้อมูลเเล้ว ในการพัฒนาโมเดลจากข้อมูล เราจะต้องทำการติดตั้ง library ที่จำเป็นเเละ import ชุดข้อมูลเข้ามาก่อน

code-import-data

จากนั้นเปิดดูชุดข้อมูลด้วย command: pd.read_csv และ df.head() โดยชุดข้อมูลที่เราใช้คือ heart.csv

heart-csv

ถัดมาเรามาสำรวจข้อมูลเบื้องต้น ดูความถูกต้องของประเภทข้อมูล (data type) หรือมี missing value หรือไม่ ซึ่งพบว่ามีข้อมูลทั้งหมด 303 รายการ, 14 ตัวแปร (column) ประกอบด้วย 13 integers และ 1 float 

code-data-frame-infomation

ต่อไปเราทำการสรุปสถิติทั่วไปโดยใช้ คำสั่ง pandas describe function ที่แสดงภาพรวมทั่วไปของการวัดทางสถิติต่างๆ สำหรับคอลัมน์ตัวเลขของชุดข้อมูล

code-describe-function

Data cleaning

หลังจากที่เรารู้จักชุดข้อมูลเเล้ว การ cleaning ก่อนจะนำไปใช้ก็สำคัญ โดยใน ขั้นตอนนี้เราเเบ่งเป็น 2 ขั้นตอน ได้เเก่

  1. การหา Null Value

  2. การลบรายการที่ซ้ำกัน (Remove duplicates)

เริ่มจากตรวจสอบว่าภายใน dataset มี Null Value หรือไม่

code-check-null-datacode-check-duplicate-data

จากรูปจะเห็นได้ว่าไม่มี Null ภายใน dataset แต่!!!! มีรายการซ้ำอยู่ 1 รายการ เราจึงลบรายการที่ซ้ำกันนี้ออกโดยใช้คำสั่ง df.drop_duplicates(inplace=True)และใช้คำสั่ง df.shape เพื่อดูข้อมูลจำนวนแถวและคอลัมน์ของชุดข้อมูลหลังทำการลบเเล้ว

check-row-and-column

ตรวจสอบค่า Unique ของข้อมูลเเละดูภาพรวมทางสถิติอีกครั้ง

code-checking-data-nuniquedata-formatted-describe

EDA — Exploratory Data Analysis

หลังจากที่เตรียมข้อมูลสำหรับการทำ EDA เเล้ว เรามาเริ่มวิเคราะห์แบบตัวแปรเดียวก่อน โดยทำการพล็อตค่าของชุดข้อมูลในรูปแบบกราฟ

การวิเคราะห์แบบตัวแปรเดียว (Univariate Analysis)

1. Categorical Feature Analysis

เราสังเกตเห็นว่าในชุดข้อมูลนี้หลายคุณลักษณะหมวดหมู่ไม่แสดงความสมดุลในการกระจายของข้อมูล ทำให้บางหมวดหมู่มีจำนวนข้อมูลที่น้อยหรือมากกว่ากลุ่มอื่นอย่างเด่นชัด

Categorical-Feature-Analysis

2.Numerical Feature Analysis

ถัดมาเราพบว่ามี Minor Outliers โดยจำนวนของ outliers ถือว่ามีไม่มากเมื่อเทียบกับขนาดของข้อมูลทั้งหมดและค่อนข้างมีค่าตรงกับแนวโน้มโดยรวมของ dataset เราจึงคาดว่าค่า outliers นี้อาจไม่ได้เกิดจากข้อผิดพลาดในการเก็บข้อมูล (มี outliers เล็กน้อยใน features เเต่สอดคล้องกับรูปแบบของdataset)

Numerical-Feature-Analysis

การวิเคราะห์แบบสองตัวแปร (Bivariate Analysis)

สำหรับการวิเคราะห์นี้เพื่อดูความสัมพันธ์ระหว่างตัวแปรสองตัว ได้ดังนี้

  • อายุและความเสี่ยงภาวะหัวใจวาย : จากกราฟจะเห็นว่าแค่อายุอย่างเดียวไม่ได้กำหนดความเสี่ยงของภาวะหัวใจวาย และแสดงให้เห็นว่าความเสี่ยงต่อภาวะหัวใจวายแตกต่างกันไปตามกลุ่มอายุ

the-effect-of-age-on-risk-of-heart-attack-graph
  • เพศและความเสี่ยงภาวะหัวใจวาย : แผนภูมิวงกลมแสดงให้เห็นว่าผู้ชาย (44.7%) มีแนวโน้มที่จะมีอาการหัวใจวายมากกว่าผู้หญิง (25%)

the-effect-of-sex-on-risk-of-heart-attack-graph
  • cp (ชนิดของอาการปวดหน้าอก)เเละความเสี่ยงภาวะหัวใจวาย : ผู้ที่มีอาการเจ็บหน้าอกประเภท 2 อาการปวดที่ไม่เกี่ยวกับหน้าอก (non-anginal pain) มีแนวโน้มที่จะเป็นโรคหัวใจมากกว่า

the-effect-of-cp-on-risk-of-heart-attack-graph
  • Exng (อาการหน้าอกแน่นเนื่องจากการออกกำลังกาย)และความเสี่ยงภาวะหัวใจวาย : ผู้ที่มีอาการหน้าอกแน่นเนื่องจากการออกกำลังกาย (exng) มีแนวโน้มที่จะเป็นโรคหัวใจมากกว่า

the-effect-of-exng-on-risk-of-heart-attack-graph
  • ค่า oldpeak (ค่า ST depressed)และความเสี่ยงภาวะหัวใจวาย : ผู้ที่มีค่า Oldpeak เป็น 0 มีแนวโน้มที่จะเป็นโรคหัวใจมากกว่า

the-effect-of-oldpeak-on-risk-of-heart-attack-graph
  • ค่า slp (ความชันของ ST Segment)และความเสี่ยงภาวะหัวใจวาย : ผู้ที่มีภาวะ slp ประเภท 2 (Upsloping) มีแนวโน้มที่จะเป็นโรคหัวใจมากกว่า

the-effect-of-slp-on-risk-of-heart-attack-graph
  • CAA (จำนวนหลอดเลือดใหญ่)และความเสี่ยงภาวะหัวใจวาย : ผู้ที่มีค่า CAA เป็น 0 มีแนวโน้มที่จะเป็นโรคหัวใจมากกว่า

the-effect-of-CAA-on-risk-of-heart-attack-graph
  • Thall (ธาลัสซีเมีย)และความเสี่ยงภาวะหัวใจวาย : ผู้ที่เป็น Thall ประเภท 2 (Reversible Defect) มีแนวโน้มที่จะเป็นโรคหัวใจมากกว่า

the-effect-of-Thalassemia-on-risk-of-heart-attack-graph

ดังนั้นสรุปการทำ Bivariate Analysis ได้ว่า

  • ความเสี่ยงของโรคหัวใจวายเปลี่ยนแปลงตามอายุแต่อายุอย่างเดียวไม่ได้กำหนดความ

  • เสี่ยงของภาวะหัวใจวาย

  • ผู้ชายมากกว่า (44.7%) มีแนวโน้มที่จะเกิดโรคหัวใจวายมากกว่าผู้หญิง (25%)

  • ชนิดของอาการปวดหน้าอกประเภท 2 (non-anginal pain) มีความเสี่ยงของโรคหัวใจวาย

  • ผลการตรวจคลื่นไฟฟ้าหัวใจประเภท 1 (ความผิดปกติของคลื่น ST-T) นั้นมีความเสี่ยงที่สูงขึ้นของโรคหัวใจวาย

  • ผู้ที่มีอาการหน้าอกแน่นเนื่องจากการออกกำลังกาย (exng) มีแนวโน้มที่จะเป็นโรคหัวใจมากกว่า

  • ค่า Oldpeak เป็น 0 หมายถึงความเสี่ยงที่สูงขึ้นของโรคหัวใจวาย

  • ผู้ที่อยู่ใน slp ประเภท 2 (Upsloping) มีความเสี่ยงของโรคหัวใจวายมากกว่า

  • ค่า CAA เป็น 0 มีแนวโน้มที่จะเป็นโรคหัวใจมากกว่า

  • ผู้ที่เป็น Thall ประเภท 2 (Reversible Defect) มีแนวโน้มที่จะเป็นโรคหัวใจมากกว่า

การวิเคราะห์แบบหลายตัวแปร (Multivariate Analysis)

  • ความดันโลหิตขณะพัก (trtbps) , อายุ เเละความเสี่ยงต่อภาวะหัวใจวาย : กราฟแสดงความสัมพันธ์แบบกระจาย (scatter plot) แสดงถึงความสัมพันธ์ในเชิงบวกระหว่างอายุและความดันโลหิตขณะพัก, โดยคนที่มีอายุมากขึ้นมีความดันโลหิตขณะพักที่สูงขึ้น, ซึ่งอาจเพิ่มความเสี่ยงของการเกิดโรคหัวใจ

graph-the-effect-of-resting-blood-pressure-and-age--on-risk-of-heart-attack
  • ระดับคอเลสเตอรอลในเลือด (chol) , อายุและความเสี่ยงต่อภาวะหัวใจวาย : แผนภูมิกระจายแสดงความสัมพันธ์เชิงบวกระหว่างอายุและระดับคอเลสเตอรอลในเลือด โดยผู้สูงอายุมักจะมีระดับคอเลสเตอรอลสูงกว่า ซึ่งอาจเพิ่มความเสี่ยงต่อโรคหัวใจวาย

graph-the-effect-of-serum-cholesterol-level-and-age-on-risk-of-heart-attack
  • อัตราการเต้นของหัวใจสูงสุดระหว่างออกกำลังกาย (thalachh), อายุและความเสี่ยงต่อภาวะหัวใจวาย : แผนภูมิกระจายแสดงถึงความสัมพันธ์ที่ตรงกันข้ามระหว่างอายุและอัตราการเต้นของหัวใจสูงสุดระหว่างการออกกำลังกายโดยบุคคลที่มีอายุมากขึ้นมักจะมีอัตราการเต้นของหัวใจสูงสุดที่ต่ำลง ซึ่งอาจเพิ่มความเสี่ยงในการเกิดอาการหัวใจวายได้

graph-the-effect-of-maximum-heart-rate-during-exercise-and-age-on-risk-of-heart-attack

Heart Attack prediction model

Data Preprocessing

ขั้นตอนนี้เป็นการเตรียมข้อมูลโดยเริ่มจากการตรวจสอบข้อมูลที่หายไป ซึ่งในชุดข้อมูลนี้ไม่มี missing values เราได้จำแนกข้อมูลออกเป็นสองประเภท ได้แก่ หมวดหมู่ที่ไม่มีลำดับ (Nominal Categories) เช่น sex และ หมวดหมู่ที่มีลำดับ (Ordinal Categories) เช่น output ด้วยการใช้ฟังก์ชัน get_dummies และเราได้แปลงข้อมูลเหล่านี้เป็นรูปแบบ one-hot encoding เพื่อนำไปใช้กับโมเดลการเรียนรู้ของเครื่อง นอกจากนี้ ยังได้มีการตรวจสอบและจัดการกับข้อมูลที่เป็น outliers สำหรับการฝึกฝนโมเดล

checking-missing-value-imageone-hot-encoding-imagechecking-on-status-and-manage-outliers-image1checking-on-status-and-manage-outliers-image2checking-on-status-and-manage-outliers-image3

Model Building

1. นำเข้าข้อมูลที่ผ่านการ Preparation แล้ว

ข้อมูลที่ได้มีทั้งหมด 283 rows, 30 columns

prepared-data-table

2. ใช้เครื่องมือของ library PyCaret เพื่อทดลองสร้างโมเดล

2.1 ก่อนที่จะสร้างโมเดลก็ต้อง download และ import เครื่องมือที่จะใช้ก่อนแบบนี้

download-and-import-library

2.2 ใช้ setup() เพื่อตั้งค่าการทดลอง

setup-function

ใช้ฟังก์ชัน setup() เพื่อกำหนดตัวแปรต่าง ๆ ของการทดลอง ดังนี้

  1. data และ profile สำหรับกำหนดข้อมูลที่จะใช้สร้างโมเดล

  2. session_id เป็น seed สำหรับการสุ่มต่าง ๆ

  3. use_gpu ใช้กำหนดการใช้งาน GPU ในการสร้างโมเดล (ในที่นี้ไม่ใช้ GPU)

  4. train_size ใช้กำหนดขนาดของการแบ่งข้อมูลสำหรับ train และ test โมเดล

  5. fold บอกจำนวน fold ที่ใช้สำหรับ cross validation

  6. normalize เพื่อบอกให้ฟังก์ชัน normalize ข้อมูลก่อนเอาไปใช้ในโมเดล โดยที่กำหนดวิธีการที่ใช้ด้วย normalize_method = ‘zscore’ หรืออีกชื่อคือ standard normalization

เมื่อรันฟังก์ชันด้านบนก็จะได้ตารางแสดงผลลัพธ์ประมาณนี้

setup-result-table

3. ทดลองโมเดล

เมื่อ setup เรียบร้อยแล้วก็สามารถเข้าสู่การทดลองได้เลย โดยสิ่งแรกที่จะทำคือ

3.1 เปรียบเทียบโมเดลของ algorithm ต่าง ๆ

ขั้นตอนนี้เป็นการเปรียบเทียบโมเดลของ algorithm ต่าง ๆ ที่ใช้กันทั่วไป เพื่อหาโมเดลที่เหมาะกับโจทย์ของเรามากที่สุด โดยสามารถดูได้จาก metric ต่าง ๆ ที่ใช้ในการวัดผลโมเดลแต่ละตัว สามารถทำได้ง่าย ๆ โดยใช้ฟังก์ชันตามนี้

compare-model-function

คำสั่งนี้จะทำการทดลองสร้างโมเดลของหลาย ๆ algorithm แล้ววัดผลด้วยการทำ cross-validation ตามที่ได้ระบุไว้ในขั้น setup() แล้วเก็บโมเดลที่ดีที่สุดไว้ในตัวแปร “best” (ในค่าเริ่มต้นจะจัดอันดับโมเดลด้วยค่า Accuracy สำหรับโมเดล classification)

หลังจากนั้นจะแสดงผลของโมเดลใน metric ต่าง ๆ ในตารางแบบนี้

metric-data-table

3.2 เลือกโมเดลที่ดีที่สุด

พวกเราเลือกโมเดลที่ดีที่สุดโดยดูจาก metric Accuracy และ F1-score เพราะ metric ทั้งสองเป็นค่าที่ใช้บอกความแม่นยำโดยรวมของโมเดล ไม่เหมือน Precision และ Recall ที่อาจจะเกิดจาก bias ได้ ดังนั้นโมเดลที่ดีที่สุดคือ lightgbm หรือ Light Gradient Boosting Machine

4. Model Optimization

ขั้นตอนนี้คือการปรับค่าต่าง ๆ ของโมเดล เพื่อให้ได้คามแม่นยำที่ดีขึ้น

4.1 Feature Selection

ขั้นตอนนี้คือการเลือก feature ที่มีความสำคัญกับโมเดลมากที่สุดการเลือก feature ที่ดีจะสามารถเพิ่มความแม่นยำของโมเดล และลดปัญหาการ overfitting ได้ โดยสามารถพลอตค่าความสำคัญของแต่ละ feature ได้ด้วยการใช้คำสั่ง ดังนี้

plot-functionplot-feature-importance

โดยวิธีการที่ใช้คือการปรับฟังก์ชัน setup() ของ PyCaret ให้ทำ Feature Selection ก่อนสร้างโมเดล ดังนี้

code-feature-selection

ส่วนที่เพิ่มไปเป็นส่วนที่กำหนดวิธีการทำ Feature Selection ในที่นี้กำหนดเป็น ‘classic’ หรือก็คือการ SelectKBest ของ sklearn วิธีนี้จะสร้างโมเดลพื้นฐานขึ้นมาในที่นี้คือโมเดล ‘lightgbm’ แล้วเลือก feature โดยดูจาก scoring function ที่อธิบายความสำคัญของ feature นั้น ๆ โดยสำหรับโมเดลนี้คือค่า ‘split’ แล้วก็มีการกำหนดจำนวน feature ที่ต้องการไว้ที่ 0.4 หรือ 40% ของ feature ทั้งหมด

4.2 Parameters Tuning

การทำ Parameters Tuning คือการปรับค่าต่าง ๆ ใน algorithm ของโมเดลเพื่อให้ได้ค่าความแม่นยำที่ดีขึ้น สำหรับเครื่องมือ PyCaret สิ่งที่ต้องทำมีดังนี้

4.2.1 สร้างโมเดลพื้นฐานที่ไม่มีปรับค่าอะไร โดยสามารถสร้างได้โดยใช้คำสั่งดังนี้

code-create-a-model

4.2.2 ใช้ฟังก์ชัน tune_model() โดยกำหนดโมเดลที่จะใช้ metric ที่ใช้เปรียบเทียบ(optimize) จำนวนครั้งที่อยากทดลอง(n_iter) วิธีการทดลอง(search_algorithm) และกำหนด choose_better = True เพื่อที่ในกรณีที่การ tune ไม่ให้ผลที่ดีขึ้น จะให้ผลลัพธ์เป็นโมเดลที่ไม่ผ่านการ tune

code-function-tune-model

ผลที่ได้ก็จะเป็นโมเดลที่มีการปรับ parameter ดังนี้

result-model

5. Prediction

นำโมเดลที่ผ่านการ Optimize ไปใช้กับข้อมูล Test เพื่อวัดผลโมเดล โดยใช้คำสั่งดังนี้

ลัพธ์ที่ทำนายมีค่าความแม่นยำดังนี้

code-predict-on-test
  • Accuracy = 0.8772

  • Precision = 0.9310

  • Recall = 0.8438

  • F1-score = 0.8852

plot model

plot-confusion-matrix
Project Code:
References:

อ่านบทความ Data Science เรื่องอื่นๆ : จาก Data สู่ Insight : แนวทางขับเคลื่อนองค์กรด้วยข้อมูลลูกค้า

Back

ร่วมกันพัฒนาและสร้างสรรค์

อนาคตใหม่ ไปพร้อมกับเรา

ร่วมกันพัฒนาและสร้างสรรค์

อนาคตใหม่ ไปพร้อมกับเรา