ได้ฤกษ์เปิด 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 |
ในแนวปฏิบัติของประเทศไทย หากท่านใดเข้าข่ายข้อใดข้อหนึ่งก็ควรได้รับการตรวจระดับน้ำตาลในเลือดเพื่อคัดกรองโรคเบาหวานแล้ว เพราะคุณคือ ผู้มีความเสี่ยงที่จะเป็นโรคเบาหวาน แล้ว น่ากลัวจริงๆ ครับ 😱
มาเริ่มกันเลย หนุ่มได้วางขั้นตอนโค้ดทำงาน ดังนี้
- Import library & Load dataset
- Explore data
- ทดสอบ features & Split features and target
- แบ่งข้อมูลเป็นชุดฝึก (train) และชุดทดสอบ (test)
- สร้างและฝึกโมเดล Logistic Regression
- ทำนายผลลัพธ์บนชุดทดสอบ (Test)
- ประเมินประสิทธิภาพของโมเดล
- 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 เบื้องต้นก็สามารถใช้งานได้แล้ว หรืออยากให้หนุ่มสอนไกด์ก็คอมเม้นต์ทิ้งไว้นะครับ จะลองเขียนเป็นบทความมาฝากครับ
ขอบคุณค้าบบ 👏