برنامه پیش بینی دیابت با یادگیری ماشین

معرفی پروژه
دیابت شرایطی است که بر نحوه پردازش قند (گلوکز) تأثیر می گذارد. به طور معمول ، بدن شما از انسولین برای تنظیم سطح قند خون استفاده می کند ، اما در دیابت ، این روند مختل می شود. دو نوع اصلی وجود دارد:
- دیابت نوع 1: بدن به هیچ وجه انسولین تولید نمی کند. معمولاً در اوایل زندگی ایجاد می شود و به تزریق انسولین نیاز دارد.
- دیابت نوع 2: هنگامی اتفاق می افتد که بدن یا انسولین کافی تولید نمی کند یا نمی تواند از آن به درستی استفاده کند. این شایع تر است و اغلب با عوامل سبک زندگی مانند رژیم و ورزش مرتبط است.
در صورت عدم کنترل ، دیابت می تواند منجر به مشکلات جدی در سلامتی شود ، اما با مراقبت مناسب مانند رژیم غذایی متعادل ، ورزش و دارو ، می توان آن را کنترل کرد. این جایی است که برنامه پیش بینی دیابت شما وارد می شود و به افراد کمک می کند تا یک نشانه اولیه دریافت کنند و اقدام کنند!
هدف پروژه
مجموعه داده این پروژه از Kaggle بارگیری شد. این پروژه با هدف توسعه برنامه ای است که می تواند پیش بینی کند که آیا بیمار دیابتی است. دست زدن به داده ها و تجسم نیز برای به دست آوردن بینش صورت می گیرد. یک رگرسیون لجستیک و مدل طبقه بندی کننده جنگل تصادفی ایجاد می شود و از مدل بهترین عملکرد برای تعیین اینکه بیمار دیابتی است یا خیر ، استفاده می شود.
بررسی اجمالی مجموعه داده ها
مجموعه داده از https://www.kaggle.com/datasets/uciml/pima-indians-diabetes-database به دست می آید
واردات کتابخانه های مورد نیاز
#Import required libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline
sns.set_style('whitegrid')
مجموعه داده ها را بارگیری کنید
df = pd.read_csv('diabetes.csv')
df.head(5)
اطلاعات مجموعه داده را دریافت کنید
#information of dataset
df.info()
اطلاعات مربوط به ویژگی های مجموعه داده
- بارداری: برای بیان تعداد بارداری ها
- گلوکز: برای بیان سطح گلوکز در خون
- خونرسانی: برای بیان اندازه گیری فشار خون
- Skinthickness: برای بیان ضخامت پوست
- انسولین: برای بیان سطح انسولین در خون
- BMI: برای بیان شاخص توده بدنی
- عملکرد دیابت: برای بیان درصد دیابت
- سن: برای بیان سن
- نتیجه: برای بیان نتیجه نهایی ، 1 بله و 0 نه نه
آمار مجموعه داده ها
#check statistics of dataset
df.describe().T
مشاهده:
- آمار مجموعه داده ها نشان می دهد که حداقل مقادیر گلوکز ، فشار خون ، ضخامت پوست ، انسولین و BMI نمی تواند واقع بینانه 0 باشد ، بنابراین این موردی است که باید به آن پرداخته شود.
داده های حمل و نقل
ما مقادیر گمشده را در این جنبه بررسی می کنیم و بر این اساس آنها را اداره می کنیم.
#Check for missing values
df.isna().sum()
مشاهده:
- هیچ مقدار از دست رفته در مجموعه داده وجود ندارد.
رسیدگی به مقادیر صفر
در این جنبه ، ما صفحات موجود در مجموعه داده ها را اداره می کنیم.
اولا ، ما بررسی می کنیم که صفر در کجا ظاهر می شود.
#check for where 0 is present in each column
print(df[df['Glucose'] == 0].shape[0])
print(df[df['BloodPressure'] == 0].shape[0])
print(df[df['SkinThickness'] == 0].shape[0])
print(df[df['Insulin'] == 0].shape[0])
print(df[df['BMI'] == 0].shape[0])
Output:
5
35
227
374
11
در مرحله بعد ، ما طرح را برای بررسی توزیع هر ستون تجسم می کنیم.
#Check distribution of each column in the dataset
df.hist(figsize=(20,20))
plt.show()
مشاهده:
- برخی از ستون ها توزیع های کمتری دارند ، بنابراین میانگین کمتر از میانه تحت تأثیر قرار می گیرد. گلوکز و فشار خون توزیع طبیعی دارند. از این رو ، ما 0 مقادیر را در آن ستون ها با مقادیر متوسط جایگزین می کنیم. ضخامت پوست ، انسولین و BMI توزیع های کمتری دارند. از این رو ، میانه انتخاب بهتری است زیرا کمتر تحت تأثیر Outliers قرار می گیرد.
#Handling Zero Values
df['Glucose'] = df['Glucose'].replace(0, df['Glucose'].mean())
df['BloodPressure'] = df['BloodPressure'].replace(0, df['BloodPressure'].mean())
df['SkinThickness'] = df['SkinThickness'].replace(0, df['SkinThickness'].median())
df['Insulin'] = df['Insulin'].replace(0, df['Insulin'].median())
df['BMI'] = df['BMI'].replace(0, df['BMI'].median())
تجسم داده ها
در این جنبه ، ما یک تجسم ساده را انجام می دهیم که در آن رابطه بین ستون هدف (نتیجه) با ستون های دیگر را بررسی می کنیم.
#Get numerical columns
num_col = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin',
'BMI', 'DiabetesPedigreeFunction', 'Age']
#Visualize columns in respect to the outcome.
# Number of rows needed (assuming you want 2 histograms per row)
nrows = (len(num_col) + 1) // 2 # this will round up the division
fig, axes = plt.subplots(nrows=nrows, ncols=2, figsize=(10, nrows * 5))
# Flatten axes array to make it easier to iterate over
axes = axes.flatten()
for i, col in enumerate(num_col):
sns.histplot(df, x=col, hue=df['Outcome'], ax=axes[i])
axes[i].set_title(f'Distribution of {col} by Outcome')
# Hide any unused subplots if there are an odd number of columns
for j in range(i + 1, len(axes)):
axes[j].axis('off')
plt.tight_layout()
plt.show()
خط حرارت همبستگی
#correlation heatmap
plt.figure(figsize=(10,6))
sns.heatmap(df.corr(), annot=True, fmt=" .2f")
plt.title('CORRELATION HEATMAP')
plt.show()
تهیه داده ها
در این جنبه ، من ابتدا مجموعه داده ها را با استفاده از مقیاس استاندارد و تقسیم به X (متغیر ویژگی) و Y (متغیر هدف) مقیاس می کنم.
#Scale data
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X = pd.DataFrame(scaler.fit_transform(df.drop(columns=['Outcome'])), columns=df.columns[:-1])
y = df['Outcome']
y
سپس ، من مجموعه داده ها را با استفاده از Scikit-Learn-Learn TraintSplit تقسیم می کنم.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
مشاهده:
- مجموعه داده به ویژگی ها تقسیم شد [X] و هدف[y] متغیر
- سپس با استفاده از TestTrainsPlit به قطار و انشعابات تست ما تقسیم شد.
- مجموعه داده ها به داده های قطار 80 ٪ و 20 ٪ داده های آزمون تقسیم شد.
انتخاب و ارزیابی مدل
ما از دو مدل برای این پروژه پیش بینی استفاده کردیم ، مدل های مورد استفاده عبارتند از:
- رگرسیون لجستیک: یک روش آماری که برای پیش بینی احتمال یک نتیجه باینری (مانند بله/خیر ، 0/1) بر اساس یک یا چند متغیر مستقل استفاده می شود ، اساساً احتمال وقوع یک رویداد را پیش بینی می کند.
- طبقه بندی کننده جنگل تصادفی: یک الگوریتم یادگیری ماشین که از مجموعه ای از درختان تصمیم گیری برای طبقه بندی داده ها استفاده می کند ، و پیش بینی هایی را با میانگین پیش بینی درختان فردی انجام می دهد. این یک ابزار قدرتمند و همه کاره است که به دلیل دقت و کارآیی آن شناخته شده است.
رگرسیون لجستیک
برای پیش بینی مدل را بسازید.
#import required libraries
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
lr = LogisticRegression()
lr.fit(X_train,y_train)
#predictions
train_pred = lr.predict(X_train) #prediction on training set
test_pred = lr.predict(X_test) #Prediction on test set
#Accuracy scores
train_acc = accuracy_score(y_train,train_pred)
test_acc = accuracy_score(y_test, test_pred)
print('Train Set Accuracy: ', train_acc * 100)
print('Test Set Accuracy: ', test_acc * 100)
print()
#Confusion matrix and classification report
print('Confusion Matrix:\n', confusion_matrix(y_test,test_pred))
print('Classification Report:\n', classification_report(y_test,test_pred))
#Visualize the Logistic Regression confusion matrix
#convert to matrix
conf_matrix = np.array([[82, 18], [27,27]])
#convert to dataframe
df_cm = pd.DataFrame(conf_matrix, index=['Actual Negative', 'Actual Positive'], columns=['Predicted Negative', 'Predicted Positive'])
#heatmap
plt.figure(figsize=(8,6))
sns.heatmap(df_cm, annot=True, fmt="d", cmap='Blues')
plt.title('Logistic Regression Confusion Matrix')
plt.show()
مشاهده:
-
این مدل به دقت 79.48 ٪ در مجموعه آموزش و دقت 70.78 ٪ در مجموعه آزمون دست می یابد ، که نشانگر افت متوسط در عملکرد است ، که نشان می دهد برخی از موارد بیش از حد.
-
از ماتریس سردرگمی ، مدل به درستی 82 بیمار غیر دیابتی را طبقه بندی می کند اما 18 را به عنوان دیابتی طبقه بندی می کند. همچنین به درستی 27 بیمار دیابتی را طبقه بندی می کند اما 27 را به عنوان غیر دیابتی طبقه بندی می کند ، که ممکن است نشان دهنده مشکل در تشخیص موارد دیابتی باشد.
-
گزارش طبقه بندی نشان می دهد که این مدل برای موارد غیر دیابتی در مقایسه با موارد دیابتی دارای دقت بالاتری (0.75) و فراخوان (82/0) است (دقت = 0.60 ، فراخوان = 0.50). این نشان می دهد که این مدل در شناسایی بیماران غیر دیابتی بهتر است اما با موارد دیابتی مبارزه می کند ، احتمالاً به دلیل عدم تعادل کلاس یا نمایش ویژگی.
طبقه بندی کننده جنگل تصادفی
برای پیش بینی مدل را بسازید.
#import required libraries
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
from sklearn.model_selection import GridSearchCV
#hyperparameter grid
param_grid = {
'n_estimators': [50, 100, 200, 300],
'max_depth': [10, 20 ,30],
'min_samples_split': [2, 5, 10]
}
#Perform gridsearch with cross validation
grid = GridSearchCV(RandomForestClassifier(), param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid.fit(X_train,y_train)
#get the best estimator
print('Best param: ', grid.best_params_)
rfc = grid.best_estimator_
#predictions
rf_train_pred = rfc.predict(X_train)
rf_test_pred = rfc.predict(X_test)
#Accuracy score
rf_train_acc = accuracy_score(y_train,rf_train_pred)
rf_test_acc = accuracy_score(y_test, rf_test_pred)
print('Train Set Accuracy: ', rf_train_acc * 100)
print('Test Set Accuracy: ', rf_test_acc * 100)
print()
#Confusion matrix and classification report
print('Confusion Matrix:\n', confusion_matrix(y_test,rf_test_pred))
print('Classification Report:\n', classification_report(y_test,rf_test_pred))
#visualize the confusion matrix
#convert to matrix
rf_matrix = np.array([[82,18],[22,32]])
#convert to dataframe
rf_df = pd.DataFrame(rf_matrix, index=['Actual Negative', 'Actual Positive'], columns=['Predicted Negative', 'Predicted Positive'])
#heatmap
plt.figure(figsize=(8,6))
sns.heatmap(rf_df, annot=True, fmt="d", cmap='Blues')
plt.title('Random Forest Confusion Matrix')
plt.show()
مشاهده:
-
دقت آموزش مدل به 93.16 ٪ بهبود یافته است ، در حالی که دقت آزمایش به 62/76 درصد افزایش یافته است ، و تعمیم بهتری را نشان می دهد اما هنوز هم بیش از حد مناسب است.
-
ماتریس سردرگمی نشان می دهد که این مدل به درستی 83 بیمار غیر دیابتی و 35 دیابتی را طبقه بندی می کند ، با کمتر طبقه بندی در مقایسه با مدل قبلی. با این حال ، 17 بیمار غیر دیابتی و 19 بیمار دیابتی هنوز طبقه بندی شده اند.
-
گزارش طبقه بندی بهبود در تشخیص موارد دیابتی (دقت = 0.67 ، فراخوان = 0.65 ، F1-نمره = 0.66) را نشان می دهد ، به این معنی که مدل اکنون در شناسایی دیابت کمی بهتر است ، اگرچه هنوز هم از پیش بینی های غیر دیابتی استفاده می کند (دقت = 0.81 ، فراخوان = 0.83).
ذخیره مدل
طبقه بندی کننده جنگل تصادفی مدل عملکرد بهتر است. با استفاده از کتابخانه ترشی ذخیره می شود و در ساخت برنامه ما مفید است. هنگامی که کاربر ما جزئیات را در اختیار شما قرار می دهد ، مقیاس دهنده استاندارد نیز ذخیره می شود تا در برنامه مورد استفاده قرار گیرد ، مدل ابتدا ورودی ها را قبل از عبور آنها به مدل برای پیش بینی مقیاس می کند.
#import required library
import pickle
pickle.dump(rfc, open('model.pkl', 'wb'))
pickle.dump(scaler, open('scaler.pkl', 'wb'))
ایجاد و استقرار برنامه
اکنون ، ما برنامه را با استفاده از برنامه می سازیم و مستقر می کنیم جریان
import streamlit as st
import pickle
import numpy as np
import time
# Load the trained model and scaler
model = pickle.load(open('model.pkl', 'rb'))
scaler = pickle.load(open('scaler.pkl', 'rb'))
# Streamlit app styling
st.markdown(
"""
""",
unsafe_allow_html=True
)
# Title
st.markdown("""
This app predicts the likelihood of diabetes based on patient medical details.
""", unsafe_allow_html=True)
# Sidebar for user inputs
st.sidebar.header("Enter Patient Details 🏥")
pregnancies = st.sidebar.slider('Pregnancies 🤰', 0, 20, 0)
glucose = st.sidebar.slider('Glucose Level 🍬', 0, 300, 120)
blood_pressure = st.sidebar.slider('Blood Pressure 💉', 0, 200, 80)
skin_thickness = st.sidebar.slider('Skin Thickness 📏', 0, 100, 20)
insulin = st.sidebar.slider('Insulin Level 💊', 0, 900, 80)
bmi = st.sidebar.slider('BMI ⚖️', 0.0, 70.0, 25.0, step=0.1)
dpf = st.sidebar.slider('Diabetes Pedigree Function 🧬', 0.0, 3.0, 0.5, step=0.01)
age = st.sidebar.slider('Age 🎂', 0, 120, 30)
# Prediction button
if st.sidebar.button('🔍 Predict Diabetes'):
# Create input array
input_data = np.array([[pregnancies, glucose, blood_pressure, skin_thickness, insulin, bmi, dpf, age]])
# Scale the data
input_data_scaled = scaler.transform(input_data)
# Loading animation
with st.spinner('Analyzing medical data... ⏳'):
time.sleep(2)
# Make prediction
prediction = model.predict(input_data_scaled)
# Display the result with better styling and animations
if prediction[0] == 1:
st.markdown("""
🚨 Prediction: DIABETES DETECTED!
Please consult a medical professional.
""", unsafe_allow_html=True)
else:
st.markdown("""
✅ Prediction: NO DIABETES!
Maintain a healthy lifestyle! 🏃♂️🥗
""", unsafe_allow_html=True)
در بالا تصاویری از برنامه اجرا شده است که پیش بینی نمی کند دیابت یا دیابت شناسایی نشده باشد.
پایان
در این مقاله ، با استفاده از مجموعه داده های دیابت ، ما از ابتدا تا انتها یک پروژه یادگیری و استقرار ماشین نهایی را نشان داده ایم. تمیز کردن و تجسم داده ها اولین مراحل ما بود. سپس ، برای ارائه داده های بهتر برای آموزش با مدل یادگیری ماشین ، داده ها با استفاده از مقیاس استاندارد مقیاس بندی شدند. پس از آن ، ما دو مدل ساختیم ، رگرسیون لجستیک و طبقه بندی کننده جنگلی تصادفی ، که در آن جنگل تصادفی مدل عملکرد بهتر بود و مدل برای ساخت برنامه ما با استفاده از StreamLit ذخیره و استفاده شد. این مدل هنوز هم می تواند با استفاده از مدلهای ماشین پیشرفته تر ، که در این مقاله مورد بحث قرار نگرفته است ، بهبود یابد ، زیرا هدف اصلی این مقاله نشان دادن استفاده از طبقه بندی کننده جنگل تصادفی و ساختمان برنامه Streamlit است.
می توانید پرونده GitHub را در اینجا بررسی کنید: پرونده خام