ได้ฤกษ์เปิด mini project ใหม่ขึ้นมาอีกซักหนึ่ง ฮ่าๆๆ วันนี้เป็น Logistic Regression Model โดยใช้ชุดข้อมูล diabetes จาก Kaggle

ภาพรวมเป็น Dataset ของผู้หญิงชนเผ่า Pima Indians มีอัตราการเกิดโรคเบาหวานประเภท 2 สูงที่สุดแห่งหนึ่งในโลก ไม่ว่าจะเป็นวิถีชีวิต การบริโภคอาหารที่มีไขมันและน้ำตาลสูงขึ้น และการออกกำลังกายน้อยลง มีส่วนทำให้ความชุกของโรคเบาหวานเพิ่มขึ้น

ใน dataset: diabetes.csv มีทั้งหมด 768 แถว และ 9 คอลัมน์ มีรายละเอียด Data Dictionary ดังนี้

Features ใน datasetความหมาย
Pregnanciesจำนวนครั้งที่ตั้งครรภ์
Glucoseระดับน้ำตาล (กลูโคส) ในเลือด (mg/dL)
BloodPressureค่าความดันโลหิต (mmHg)
SkinThicknessความหนาของรอยพับผิวหนัง triceps (mm)
Insulinระดับอินซูลินในเลือด (µU/mL)
BMIดัชนีมวลกาย (น้ำหนักเป็นกิโลกรัม / (ส่วนสูงเป็นเมตร)^2)
DiabetesPedigreeFunctionฟังก์ชันประวัติโรคเบาหวาน (คะแนนที่แสดงถึงโอกาสเกิดโรคเบาหวานตามประวัติครอบครัว)
Ageอายุ (ปี)
Outcomeผลลัพธ์ (0 = ไม่เป็นเบาหวาน, 1 = เป็นเบาหวาน)

ก่อนจะไปทดสอบตัวแปรต้นว่า features ใดที่ Significant บ้าง เรามารีวิวดูงาน Clinical practice guideline for Diabetes 2023 ที่จัดทำโดยสมาคมโรคเบาหวานแห่งประเทศไทย ในการคัดกรอง/ประเมินตัวบุคคลว่าปัจจัยเสี่ยงหรือภาวะ/โรคที่สัมพันธ์กับโรคเบาหวาน จากเอกสารมีข้อประเมินที่หนุ่มคิดว่าสอดคล้องกับ Dataset ที่เราจะสามารถใช้ในโมเดล ดังนี้ครับ

หัวข้อประเมินFeatures ใน dataset
มีอายุ 35 ปีขึ้นไปAge
อ้วน (ฺBMI ≥ 25 กก./ตร.ม.) และมีพ่อ แม่ พี่ หรือน้องเป็นโรคเบาหวานBMI, DiabetesPedigreeFunction
มีระดับไขมันในเลือดผิดปกติ (Triglyceride, HDL, Cholesterol)
เป็นโรคความดันโลหิตสูง, รับประทานยาควบคุมความดันฯBloodPressure
มีประวัติเป็นโรคเบาหวานขณะตั้งครรภ์ หรือเคยคลอดบุตรที่น้ำหนักตัวเกิน 4 กก.Pregnancies
เคยตรวจพบว่าความทนต่อน้ำตาลบกพร่อง (IGT หรือ IFG)Glucose
เป็นโรคหัวใจและหลอดเลือด
ผู้หญิงกลุ่มอาการถุงน้ำรังไข่หลายใบ
ผู้มีความผิดปกติเกี่ยวกับภาวะดื้ออินซูลินInsulin
เป็นผู้ติดเชื้อ HIV

ในแนวปฏิบัติของประเทศไทย หากท่านใดเข้าข่ายข้อใดข้อหนึ่งก็ควรได้รับการตรวจระดับน้ำตาลในเลือดเพื่อคัดกรองโรคเบาหวานแล้ว เพราะคุณคือ ผู้มีความเสี่ยงที่จะเป็นโรคเบาหวาน แล้ว น่ากลัวจริงๆ ครับ 😱

มาเริ่มกันเลย หนุ่มได้วางขั้นตอนโค้ดทำงาน ดังนี้

  1. Import library & Load dataset
  2. Explore data
  3. ทดสอบ features & Split features and target
  4. แบ่งข้อมูลเป็นชุดฝึก (train) และชุดทดสอบ (test)
  5. สร้างและฝึกโมเดล Logistic Regression
  6. ทำนายผลลัพธ์บนชุดทดสอบ (Test)
  7. ประเมินประสิทธิภาพของโมเดล
  8. Let’s predict

Import library & Load dataset 📩

import pandas as pd
import matplotlib.pyplot as plt
import math
import seaborn as sns

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import  confusion_matrix, accuracy_score, classification_report
import statsmodels.api as sm

import pickle
# ใช้ไลบรารี pickle ใน Python เพื่อบันทึกโมเดลของคุณเป็นไฟล์ .pkl

Library ที่หนุ่มใช้จะมี 3 ส่วนสำคัญ ก็คือ ส่วนแรกมี pandas, matplotlib, math และ seaborn แทบจะเป็น Library พื้นฐานในการทำงานด้วย python เลยล่ะ

ส่วนที่ 2 เกี่ยวกับการฝึก การทำนายโมเดล รวมถึงเครื่องมือที่ใช้ช่วยประเมินประสิทธิภาพของโมเดล ไม่ว่าจะเป็น train_test_split, LogisticRegression, confusion_matrix, accuracy_score, classification_report จาก scikit-learn และ statsmodels

ส่วนที่ 3 หนุ่มจะใช้ไลบรารี pickle เพื่อบันทึกโมเดลที่ได้ทำการ Train แล้วเป็นไฟล์ .pkl และนำไปใช้บน Streamlit ทำเป็นเว็บแอพ predicted ผลได้แบบเรียลไทม์กันเลย 😎

url = 'ref/diabetes.csv'
dm = pd.read_csv(url)

# ปรับหัวคอลัมน์เป็น lower case
dm.columns = dm.columns.str.lower()
dm.head()

จากที่ได้กล่าวไปในตอนแรกนะครับว่าหนุ่มจะใช้ dataset: diabetes.csv ทำการโหลด csv เข้า Data frame ชื่อ dm จากนั้นปรับหัวคอลัมน์ให้เป็นตัวพิมพ์เล็ก จะได้พิมพ์โค้ดได้ง่ายๆ แล้วลองเรียก sample data ขึ้นมาดู

Explore data 🔮

print(dm.shape)
dm.describe().T

เริ่มจากจำนวน Observation ของเรากันก่อนมีทั้งหมด 768 รายการ จะมีคอลัมน์หรือ features ที่ไม่ควรมีค่า min เป็นศูนย์ คือ Glucose, bloodPressure, SkinThickness, Insulin, BMI อาจจะเป็นเพราะบางรายการผู้สำรวจไม่ได้เก็บข้อมูลนี้มา ส่วน Pregnancies ที่เป็นค่าศูนย์ก็เป็นไปได้ว่า หญิงคนนั้นไม่เคยตั้งครรภ์จริงๆ ได้

# Outcome
outcome_grouped = dm.groupby(['outcome']).agg({'outcome':'count'}).rename(columns={'outcome': 'count'})
outcome_grouped = outcome_grouped.reset_index()
outcome_grouped 

สำรวจ feature แรกเป็น Outcome ผลลัพธ์ที่ว่า 0 = ไม่เป็นเบาหวาน, 1 = เป็นเบาหวาน เพื่อดูว่าสัดส่วนข้อมูลที่เราได้มานั้นเป็นอย่างไร จะเห็นว่า จำนวน 500 Observations ที่ไม่เป็นเบาหวานมีจำนวนมากกว่า 268 Observations ที่เป็นเบาหวาน

# pregnancies
print("pregnancies มีค่าเป็นศูนย์ จำนวน:", len(dm[dm['pregnancies']==0]), "รายการ")
fig, axes = plt.subplots(1, 2, figsize=(10, 2))
sns.boxplot(data=dm, x="pregnancies", ax=axes[0]) # กราฟ Boxplot
dm["pregnancies"].plot.hist(ax=axes[1]) # กราฟ Histogram
plt.tight_layout() 
plt.show()

จากกราฟ pregnancies: จำนวนครั้งที่ตั้งครรภ์ จะพบว่า Observation ส่วนใหญ่มีการตั้งครรภ์ 2-5 ครั้ง และมากสุดอยู่ที่ 17 ครั้ง และไม่เคยตั้งครรภ์ (มีค่าเป็น 0) จำนวน 111 รายการ

# glucose
print("glucose มีค่าเป็นศูนย์ จำนวน:", len(dm[dm['glucose']==0]), "รายการ")
fig, axes = plt.subplots(1, 2, figsize=(10, 2))
sns.boxplot(data=dm, x="glucose", ax=axes[0]) # กราฟ Boxplot
dm["glucose"].plot.hist(ax=axes[1]) # กราฟ Histogram
plt.tight_layout() 
plt.show()

จากกราฟ glucose: ระดับน้ำตาลกลูโคสในเลือด โดยระดับน้ำตาลที่ปกติ จะอยู่ที่ประมาณ 70-100 มิลลิกรัมต่อเดซิลิตร หากค่าที่ได้สูงกว่า 100 มิลลิกรัมต่อเดซิลิตร ขึ้นไปอาจเสี่ยงต่อการเป็นโรคเบาหวาน

จะพบว่าประมาณ 75% ของ Observation มีค่าน้ำตาลในสูงกว่าเกณฑ์ปกติ เพราะว่าที่ Q1 หรือ Percentile ที่ 25 ก็มีค่าน้ำตาลในเลือด 99 มิลลิกรัมต่อเดซิลิตรไปแล้ว

# bloodpressure
print("bloodpressure มีค่าเป็นศูนย์ จำนวน:", len(dm[dm['bloodpressure']==0]), "รายการ")
print("bloodpressure มีค่า >= 100 mmHg จำนวน:", len(dm[dm['bloodpressure']>= 100]), "รายการ")
fig, axes = plt.subplots(1, 2, figsize=(10, 2))
sns.boxplot(data=dm, x="bloodpressure", ax=axes[0]) # กราฟ Boxplot
dm["bloodpressure"].plot.hist(ax=axes[1]) # กราฟ Histogram
plt.tight_layout() 
plt.show()

จากกราฟ bloodpressure: ความดันเลือด จากค่า Max ที่ได้อยู่ที่ 122 mmHg คาดการณ์ตัวเลขในชุดนี้จะต้องเป็น Diastolic blood pressure (DBP) ตัวล่าง คือ ความดันเลือดที่ต่ำสุดขณะหัวใจห้องล่างคลายตัว ซึ่งปกติเมื่อตรวจวัดความดันฯ เราจะผลออกมา 2 ค่า คือ 1) Systolic blood pressure (SBP) และ 2) Diastolic blood pressure (DBP)

ซึ่งความดันฯ มีค่าปกติอยู่ที่ 120/80 mmHg และเกณฑ์ตัวล่าง (ตรงกับที่เรามีข้อมูล)

  • ความดันฯ ค่อนข้างสูง 80-89 mmHg
  • ความดันฯ สูงมาก ≥ 90 mmHg
  • ความดันฯ ระดับอันตราย ≥ 100 mmHg

จะพบบว่าชุดข้อมูลนี้มี 16 Observations ที่ค่าความดันฯ อยู่ระดับอันตราย ≥ 100 mmHg

# skinthickness
print("skinthickness มีค่าเป็นศูนย์ จำนวน:", len(dm[dm['skinthickness']==0]), "รายการ")
fig, axes = plt.subplots(1, 2, figsize=(10, 2))
sns.boxplot(data=dm, x="skinthickness", ax=axes[0]) # กราฟ Boxplot
dm["skinthickness"].plot.hist(ax=axes[1]) # กราฟ Histogram
plt.tight_layout() 
plt.show()

จากกราฟ skinthickness: ความหนาของรอยพับผิวหนัง triceps (mm) จะเห็นว่า missing value ค่อนข้างเยอะเลย 227 รายการ ทั้งนี้ตัวแปรนี้ ไม่ได้อยู่ใน Literature review ก่อนหน้านี้ หนุ่มก็เลยขอข้ามรายละเอียดไปนะครับ

# insulin
print("insulin มีค่าเป็นศูนย์ จำนวน:", len(dm[dm['insulin']==0]), "รายการ")
fig, axes = plt.subplots(1, 2, figsize=(10, 2))
sns.boxplot(data=dm, x="insulin", ax=axes[0]) # กราฟ Boxplot
dm["insulin"].plot.hist(ax=axes[1]) # กราฟ Histogram
plt.tight_layout() 
plt.show()

จากกราฟ insulin: ระดับอินซูลินในเลือด เนื่องจาก dataset ไม่ได้บอกว่า Lab test insulin มีวิธีการอย่างไร จึงบอกไม่ได้ว่าค่าปกติอยู่ใน Range ไหน ทั้งนี้ผลการทดสอบตัวแปร (ในขั้นตอนต่อไป) ค่า p-value ก็ไม่ Significant (~0.155) รวมถึงมี missing value สูงถึง 374 รายการอีกด้วย

# bmi
print("bmi มีค่าเป็นศูนย์ จำนวน:", len(dm[dm['bmi']==0]), "รายการ")
fig, axes = plt.subplots(1, 2, figsize=(10, 2))
sns.boxplot(data=dm, x="bmi", ax=axes[0]) # กราฟ Boxplot
dm["bmi"].plot.hist(ax=axes[1]) # กราฟ Histogram
plt.tight_layout() 
plt.show()

จากกราฟ bmi: ดัชนีมวลกาย จะพบว่าประมาณ 50% ของ Observation มีภาวะน้ำหนักอยู่ในเกณฑ์อ้วน (BMI ≥ 30) เพราะว่าที่ Q2 หรือ Percentile ที่ 50 มีค่า BMI เกิน 30 ไปแล้ว 😭 จากเกณฑ์ปกติ BMI จะอยู่ที่ 18.5-22.9

# diabetespedigreefunction
print("diabetespedigreefunction มีค่าเป็นศูนย์ จำนวน:", len(dm[dm['diabetespedigreefunction']==0]), "รายการ")
fig, axes = plt.subplots(1, 2, figsize=(10, 2))
sns.boxplot(data=dm, x="diabetespedigreefunction", ax=axes[0]) # กราฟ Boxplot
dm["diabetespedigreefunction"].plot.hist(ax=axes[1]) # กราฟ Histogram
plt.tight_layout() 
plt.show()

จากกราฟ diabetespedigreefunction: ฟังก์ชันประวัติโรคเบาหวาน (หนุ่มไม่ทราบวิธีการคำนวณที่แท้จริง) เท่าที่ไปรื้อข้อมูลมา มันคือการใช้ข้อมูลทางพันธุกรรมในครอบครัว (Pedigree หรือ Family History) เพื่อนำมาประเมินความเสี่ยงการเป็นเบาหวานของแต่ละบุคคล ซึ่งข้อมูลส่วนใหญ่มีค่าต่ำกว่า 1 point

# age
print("age มีค่าเป็นศูนย์ จำนวน:", len(dm[dm['age']==0]), "รายการ")
fig, axes = plt.subplots(1, 2, figsize=(10, 2))
sns.boxplot(data=dm, x="age", ax=axes[0]) # กราฟ Boxplot
dm["age"].plot.hist(ax=axes[1]) # กราฟ Histogram
plt.tight_layout() 
plt.show()

จากกราฟ age: อายุ จะพบว่าประมาณ 75% ของ Observations มีอายุต่ำกว่า 40 ปี ในชุดข้อมูลมีอายุมากที่สุดอยู่ที่ 81 ปี

ทดสอบ features & Split features and target ⚗️

X = dm[['pregnancies', 'glucose', 'bloodpressure', 'insulin',  'bmi', 'diabetespedigreefunction', 'age']]
y = dm['outcome']

# เพิ่มค่าคงที่ (constant) ให้กับ X (จำเป็นสำหรับ statsmodels)
X = sm.add_constant(X)
model = sm.Logit(y, X).fit()
print(model.summary())

ต่อมาเป็นการทดสอบว่าตัวแปรใดบ้างที่ significant และเหมาะสมกับโมเดล ให้โมเดลแม่นยำและมีประสิทธิภาพ สำหรับโมเดล Logistic Regression ของเรา

หนุ่มจะไลบรารี statsmodels เพื่อเลือก features ที่มีค่า p-value ที่น้อยกว่าหรือเท่ากับ 0.05 โดยถือว่าตัวแปรนั้นมีความสำคัญสามารถนำเอามาใช้ทำนายได้ ประกอบด้วยตัวแปร pregnancies, glucose, bloodpressure, bmi และ diabetespedigreefunction

# กำหนดตัวแปรต้น (X) และตัวแปรตาม (y)
X = dm[['pregnancies', 'glucose', 'bloodpressure', 'bmi', 'diabetespedigreefunction']]
y = dm['outcome']

แบ่งข้อมูลเป็นชุดฝึก (train) และชุดทดสอบ (test) 🎲

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=137)

หนุ่มจะใช้ฟังก์ชัน train_test_split เพื่อแบ่ง Dataset ออกเป็นชุดฝึก Train model 80% และชุดทดสอบ Test model 20% โดย..

  • ตัวแปร X_train ที่เก็บตัวแปรต้นจะคู่กับ y_train ที่เก็บตัวแปรตาม เราจะใช้เป็นชุดฝึก
  • ตัวแปร X_test ที่เก็บตัวแปรต้นจะคู่กับ y_test ที่เก็บตัวแปรตาม จะใช้เป็นชุดทดสอบโมเดล

สร้างและฝึกโมเดล Logistic Regression 🚊

model = LogisticRegression(max_iter=1000)  # เพิ่ม max_iter
model.fit(X_train, y_train)

เริ่มฝึกโมเดล LogisticRegression โดยเพิ่ม max_iter เป็นกระบวนการ iterative (วนซ้ำ 1,000 รอบ) เพื่อหาค่าสัมประสิทธิ์ที่ทำให้ความผิดพลาดของโมเดลมีค่าน้อยที่สุด

# ทำนายผลลัพธ์บนชุดฝึก (train set)
y_train_pred = model.predict(X_train)

# แสดง Confusion Matrix เป็น Heatmap 
plt.figure(figsize=(3, 2))
cm = confusion_matrix(y_train, y_train_pred) # สร้าง Confusion Matrix
sns.heatmap(cm, annot=True, fmt="d", cmap="Blues")
plt.xlabel("Predicted")
plt.ylabel("Actual")
plt.title("Confusion Matrix")
plt.show()

กราฟจะแสดงแนวนอนเป็นค่าที่แท้จริง Actual เทียบกับแนวตั้งที่เป็นค่าที่โมเดลทำนาย Predicted ไว้

# แสดง Classification Report & ประเมินประสิทธิภาพของโมเดล
print("Classification Report:\n", classification_report(y_train, y_train_pred))

# แสดง Accuracy
accuracy = accuracy_score(y_train, y_train_pred)
print(f"Accuracy: {accuracy}")

หนุ่มจะใช้ฟังก์ชัน classification_report() และ accuracy_score() เพื่อแสดงผลลัพธ์ accuracy, precision, recall และ f1-score ที่โมเดลทำได้

  • Accuracy: ไม่ว่าผลลัพธ์จะเป็น DM หรือ Non-DM แล้วโมเดลทายถูก / จำนวนทั้งหมด ~ 0.78
  • Precision: เมื่อเรา Predicted ว่า DM → เราทายถูกกี่ครั้ง / จำนวนที่เราทายว่า DM ทั้งหมด ~ 0.75
  • Recall: เมื่อข้อมูล Actual เป็น DM → เราทายถูกกี่ครั้ง / จำนวนที่ข้อมูล Actual เป็น DM ทั้งหมด ~ 0.58
  • F1 Score: วัดค่าผลลัพธ์โดยรวมของโมเดล 2 *((precision * recall) / (precision + recall)) ~ 0.65

ทำนายผลลัพธ์บนชุด Test 🔮

y_pred = model.predict(X_test)
y_pred

หลังจากที่ fit model แล้วใช้ฟังก์ชัน predict() เพื่อทำนายผลลัพธ์ว่าแต่ละ Observation จะเป็นเบาหวานหรือไม่ ซึ่งค่าได้จะเป็น 0 = ไม่เป็นเบาหวาน และ 1 = เป็นเบาหวาน

# คำนวณ Sigmoid probability
y_proba = model.predict_proba(X_test)
proba_df = pd.DataFrame(y_proba, columns=["prob_0", "prob_1"])
proba_df

แต่หนุ่มต้องการแสดงเป็นตัวเลขความน่าจะเป็น probability จาก Sigmoid function ซึ่งจะคืนค่าแต่ละ Observations ออกมา 2 ค่า คือ ความน่าจะเป็นที่จะเป็น 0 (ไม่เป็นเบาหวาน) และ ความน่าจะเป็นที่จะเป็น 1 (เป็นเบาหวาน)

ก่อนจะไปประเมินประสิทธิภาพของโมเดล (13:34 น. 2025-03-28 หนุ่มขอหอบคอมฯ วิ่งลงตึกก่อนนะครับ แผ่นดินไหว 😱) — ฟิ้วววว ขอให้ทุกคนปลอดภัยนะครับ เสียใจกับการสูญเสียด้วยนะครับ

ประเมินประสิทธิภาพของโมเดล 🧪

มาต่อเลย “ประเมินประสิทธิภาพของโมเดล” หนุ่มจะแสดง Confusion Matrix บน Heatmap ดูว่าโมเดลทายถูกเยอะมั้ยนะครับ

# แสดง Confusion Matrix เป็น Heatmap 
plt.figure(figsize=(3, 2))
cm = confusion_matrix(y_test, y_pred) # สร้าง Confusion Matrix
sns.heatmap(cm, annot=True, fmt="d", cmap="Blues")
plt.xlabel("Predicted")
plt.ylabel("Actual")
plt.title("Confusion Matrix")
plt.show()

กราฟจะแสดงแนวนอนเป็นค่าที่แท้จริง Actual ที่เราได้แยกไว้ เทียบกับแนวตั้งที่เป็นค่าที่โมเดลทำนาย Predicted ไว้ ดูคร่าวๆ แล้วโมเดลก็สามารถทำนายได้ถูกต้องเยอะเหมือนกันนะเนี่ย

# แสดง Classification Report & ประเมินประสิทธิภาพของโมเดล
print("Classification Report:\n", classification_report(y_test, y_pred))

# แสดง Accuracy
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")

ใช้ฟังก์ชัน classification_report() และ accuracy_score() เหมือนกับที่ใช้ใน Train set เพื่อแสดงผลลัพธ์ accuracy, precision, recall และ f1-score ที่โมเดลทำได้

  • Accuracy: ไม่ว่าผลลัพธ์จะเป็น DM หรือ Non-DM แล้วโมเดลทายถูก / จำนวนทั้งหมด ~ 0.79
  • Precision: เมื่อเรา Predicted ว่า DM → เราทายถูกกี่ครั้ง / จำนวนที่เราทายว่า DM ทั้งหมด ~ 0.63
  • Recall: เมื่อข้อมูล Actual เป็น DM → เราทายถูกกี่ครั้ง / จำนวนที่ข้อมูล Actual เป็น DM ทั้งหมด ~ 0.66
  • F1 Score: วัดค่าผลลัพธ์โดยรวมของโมเดล 2 *((precision * recall) / (precision + recall)) ~ 0.64
  • ผลลัพธ์ของโมเดลค่อนข้างต่ำ อาจเป็นผลมาจากความไม่สมดุลของข้อมูล (imbalanced dataset) ซึ่งจำนวน observation ที่เป็น 1 น้อยกว่า observation ที่เป็น 0 เยอะเกิ๊นนนน (110:44)
  • ตอนทำนาย train set เราจะได้ค่า train accuracy อยู่ที่ 78% และในส่วนของ test accuracy เพิ่มขึ้นมาประมาณ 1% อย่างน้อยก็ไม่ได้มีปัญหา overfitting เพราะค่าทั้ง 2 ไม่ต่างกันมากนัก
  • แต่อาจจะต้องพิจารณาเพิ่มตัวแปรต้นที่ส่งผลต่อการทำนายให้มากขึ้น

Let’s predict 🤩

พาร์ทที่น่าตื่นเต้นที่สุดแล้วคือการ Predicted แบบเรียลไทม์ จากโมเดลที่่เราได้เทรนไว้ เราจะมาทดลองป้อนค่าใหม่เข้าไปเพื่อดูผลลัพธ์กัน

# แสดงค่าสัมประสิทธิ์ของโมเดล
print("Coefficients:")
print(pd.DataFrame(model.coef_, columns=X.columns))
print("Intercept:")
print(model.intercept_)

# เก็บเข้าตัวแแปรเพื่อใช้ในสมการ LR
inter_ = model.intercept_
coef_pregnancies = model.coef_[0][0]
coef_glucose = model.coef_[0][1]
coef_bp = model.coef_[0][2]
coef_bmi = model.coef_[0][3]
coef_dmpedfunc = model.coef_[0][4]

# กำหนดตัวแปรต้นที่จะใช้ในการทำนาย
vari_pregnancies = 6
vari_glucose = 162
vari_bp = 62
vari_bmi = 24.3
vari_dmpedfunc = 0.178

หนุ่มจะใช้ model.coef_ เพื่อดึงค่าสัมประสิทธิ์ของตัวแปร (coefficient) และ model.intercept_ ดึง Intercept มาใช้ในสมการ Linear Regression จะได้ ..

pred_ = inter_ + (vari_pregnancies * coef_pregnancies) + (vari_glucose * coef_glucose) + (vari_bp * coef_bp) + (vari_bmi * coef_bmi) + (vari_dmpedfunc * coef_dmpedfunc)
print(pred_[0])
## 0.11436579081462475

จะได้ค่า Linear Regression ออกมาเท่ากับ 0.11436579081462475 ซึ่งตัวเลขนี้จะต้องเข้าสู่ Sigmoid function เพื่อแปลงให้เป็นความน่าจะเป็น 0 ถึง 1

# Sigmoid probability
pred_ = pred_[0]
pred_prop = math.exp(pred_)/(1+math.exp(pred_))
print(pred_prop)
# 0.5285603248423204

และหนุ่มจะตั้งค่า threshold ที่ 0.5 ทำหน้าที่เป็นจุดตัดในการแบ่งแยกผลลัพธ์ของการทำนาย โดยใช้ Sigmoid probability ก่อนหน้านี้ แล้วก็เข้าฟังก์ชัน if อีกครั้งเพื่อตีเป็นคำทำนาย

thershold = 0.5
if pred_prop >= thershold: 
    pred_outcome = 1
    pred_outcome_name = 'ทำนายว่าเป็น DM'
else:
    pred_outcome = 0
    pred_outcome_name = 'ทำนายว่าไม่เป็น DM'
    
print(pred_outcome)
print(pred_outcome_name)
## 1
## ทำนายว่าเป็น DM

จากตัวแปรต้นที่ตั้งไว้สรุปว่า หญิงที่มีการตั้งครรภ์มาแล้ว 6 ครั้ง, มีระดับน้ำตาลในเลือก 162 mg/dL, ความดันเลือดค่าล่างอยู่ที่ 62 mmHg, มี BMI อยู่ที่ 24.3 และมีฟังก์ชันประวัติโรคเบาหวานอยู่ที่ 0.178 และโมเดลได้ทำนายว่า หญิงท่านนี้เป็นเบาหวานมีโอกาสความน่าจะเป็นที่ 0.53

แน่นอนว่า ไหนๆ เราก็สามารถระบุค่าตัวแปรและทำนายได้แล้ว หนุ่มก็คิดว่าน่าจะลอง build application ขึ้นมา (อีกแล้ว เหอะๆๆ 😝 หลังจากที่พาลง titanic shiny app ไปแล้ว)

คราวนี้ใช้ Streamlit app จะได้หน้าต่าง app เป็นแบบนี้เลย คุณผู้อ่านสามารถคลิกไปลองเล่นกันได้นะครับ ดีไม่ดียังไงคอมเม้นต์บอกกันได้น้า ที่ลิงก์นี้ค้าบบ: Python 🐍 Project Model

ในลิงก์จะมีหลายโปรเจ็คนะครับ ให้คลิกไปที่แท็บ “diabetes”

จะได้ผลลัพธ์ที่โมเดลทำนายได้ แบบนี้เลย 😎 เอาเรื่อง


Build app มาหลายรอบแล้ว หากท่านผู้อ่านสนใจอยากลอง build model เองบ้างสามารถเข้าไปลองใช้บน Steamlit ได้เลยนะครับ Pack Free เบื้องต้นก็สามารถใช้งานได้แล้ว หรืออยากให้หนุ่มสอนไกด์ก็คอมเม้นต์ทิ้งไว้นะครับ จะลองเขียนเป็นบทความมาฝากครับ

ขอบคุณค้าบบ 👏



Leave a Reply

Your email address will not be published. Required fields are marked *

Search

About

Feasible เว็บไซต์ที่นำเสนออาชีพปัจจุบันที่เรา (เจ้าของเว็บ) กำลังทำ ไม่ว่าจะเป็น นักวิเคราะห์ข้อมูล นักเรียน นักอ่าน นักฟาร์ม และอีกหลากหลายมุมมอง เรียกได้ว่าเป็น ‘แกงโฮะ’ เลยล่ะ ฮ่าๆๆ ติดตาม Content ที่จะทำออกมาได้เรื่อยๆ นะครับ ขอบคุณที่เข้ามาเยี่ยมกัน 😁✌️

Social Icons

Buy Me a Coffee

😁 ขอบคุณทุกน้ำใจ ทุกการสนับสนุนครับ 👏