File size: 8,562 Bytes
65c2a51 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
import gradio as gr
import xgboost as xgb
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix
import plotly.express as px
import plotly.graph_objects as go
import json
class DiabetesGame:
def __init__(self):
self.data = self.load_data()
self.model = self.train_model()
self.user_score = 0
self.total_attempts = 0
self.tips_database = {
"glucose": "Normal fasting blood glucose levels are less than 100 mg/dL. Levels between 100-125 mg/dL indicate prediabetes.",
"bmi": "A BMI between 18.5 and 24.9 is considered healthy. BMI over 30 indicates obesity, a risk factor for diabetes.",
"blood_pressure": "Normal blood pressure is usually below 120/80 mmHg. High blood pressure often co-occurs with diabetes.",
"age": "Type 2 diabetes risk increases with age, particularly after 45 years.",
"pregnancies": "Gestational diabetes during pregnancy increases future diabetes risk.",
"lifestyle": "Regular exercise and a balanced diet can significantly reduce diabetes risk.",
"family_history": "Having a parent or sibling with diabetes increases your risk.",
"general": "Early detection and lifestyle changes can prevent or delay type 2 diabetes."
}
def load_data(self):
return pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/diabetes.csv')
def train_model(self):
X = self.data.drop(columns=['Outcome'])
y = self.data['Outcome']
X_train, _, y_train, _ = train_test_split(X, y, test_size=0.2, random_state=42)
model = xgb.XGBClassifier(
eval_metric='logloss',
max_depth=6,
learning_rate=0.1,
n_estimators=100,
random_state=42
)
model.fit(X_train, y_train)
return model
def create_radar_chart(self, values):
categories = ['Pregnancies', 'Glucose', 'Blood Pressure', 'Skin Thickness',
'Insulin', 'BMI', 'Diabetes Pedigree', 'Age']
# Normalize values for radar chart
max_values = [17, 200, 122, 99, 846, 67.1, 2.42, 81]
normalized_values = [v/m for v, m in zip(values, max_values)]
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=normalized_values,
theta=categories,
fill='toself',
name='Patient Values'
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 1]
)),
showlegend=True,
title="Patient Risk Factors Radar Chart"
)
return fig
def create_feature_importance_plot(self):
importance_df = pd.DataFrame({
'Feature': ['Pregnancies', 'Glucose', 'Blood Pressure', 'Skin Thickness',
'Insulin', 'BMI', 'Diabetes Pedigree', 'Age'],
'Importance': self.model.feature_importances_
})
importance_df = importance_df.sort_values('Importance', ascending=True)
fig = px.bar(importance_df, x='Importance', y='Feature',
orientation='h',
title='Feature Importance in Diagnosis')
fig.update_layout(height=400)
return fig
def get_relevant_tips(self, values):
tips = []
# Add tips based on values
if values[1] > 140: # High glucose
tips.append(("β οΈ High Glucose", self.tips_database["glucose"]))
if values[5] > 30: # High BMI
tips.append(("β οΈ High BMI", self.tips_database["bmi"]))
if values[2] > 90: # High blood pressure
tips.append(("β οΈ High Blood Pressure", self.tips_database["blood_pressure"]))
# Always add a random general tip
general_tips = [self.tips_database["lifestyle"],
self.tips_database["family_history"],
self.tips_database["general"]]
tips.append(("π‘ Health Tip", np.random.choice(general_tips)))
return "\n\n".join([f"{title}\n{content}" for title, content in tips])
def predict_and_play(self, pregnancies, glucose, blood_pressure, skin_thickness,
insulin, bmi, diabetes_pedigree, age, user_diagnosis):
values = [pregnancies, glucose, blood_pressure, skin_thickness,
insulin, bmi, diabetes_pedigree, age]
# Make prediction
user_input = np.array(values).reshape(1, -1)
prediction = self.model.predict(user_input)[0]
probability = self.model.predict_proba(user_input)[0][1] * 100
# Update score
self.total_attempts += 1
correct = (user_diagnosis == "Yes" and prediction == 1) or \
(user_diagnosis == "No" and prediction == 0)
if correct:
self.user_score += 1
# Create visualizations
radar_chart = self.create_radar_chart(values)
importance_plot = self.create_feature_importance_plot()
# Generate result message
accuracy = (self.user_score / self.total_attempts) * 100 if self.total_attempts > 0 else 0
result = f"""{'π Correct!' if correct else 'β Incorrect'}\n
Model Prediction: {'Diabetes Risk Detected' if prediction == 1 else 'No Significant Risk'}\n
Confidence: {probability:.1f}%\n
Your Score: {self.user_score}/{self.total_attempts} ({accuracy:.1f}% accuracy)
"""
# Get relevant tips
tips = self.get_relevant_tips(values)
return result, radar_chart, importance_plot, tips
# Initialize game
game = DiabetesGame()
# Create the interface
with gr.Blocks(theme=gr.themes.Soft()) as interface:
gr.Markdown("""
# π₯ Interactive Diabetes Diagnosis Game
Test your medical diagnosis skills! Analyze patient data and try to predict diabetes risk.
Your score will be tracked as you play.
## How to Play:
1. Adjust the patient parameters using the sliders
2. Make your diagnosis (Yes/No for diabetes risk)
3. Submit to see if you matched the model's prediction
4. Learn from the visualizations and tips
""")
with gr.Row():
with gr.Column():
pregnancies = gr.Slider(0, 17, step=1, label="Pregnancies")
glucose = gr.Slider(0, 200, value=120, step=1, label="Glucose Level")
blood_pressure = gr.Slider(0, 122, value=70, step=1, label="Blood Pressure")
skin_thickness = gr.Slider(0, 99, value=20, step=1, label="Skin Thickness")
with gr.Column():
insulin = gr.Slider(0, 846, value=80, step=1, label="Insulin")
bmi = gr.Slider(0.0, 67.1, value=25.0, step=0.1, label="BMI")
diabetes_pedigree = gr.Slider(0.078, 2.42, value=0.5, step=0.001, label="Diabetes Pedigree")
age = gr.Slider(21, 81, value=30, step=1, label="Age")
diagnosis = gr.Radio(["Yes", "No"], label="Your Diagnosis", info="Do you think this patient has diabetes?")
submit_btn = gr.Button("Submit Diagnosis", variant="primary")
with gr.Row():
result_box = gr.Textbox(label="Game Result", lines=5)
tips_box = gr.Textbox(label="Health Tips & Information", lines=5)
with gr.Row():
radar_plot = gr.Plot(label="Patient Risk Factors")
importance_plot = gr.Plot(label="Feature Importance")
submit_btn.click(
fn=game.predict_and_play,
inputs=[pregnancies, glucose, blood_pressure, skin_thickness,
insulin, bmi, diabetes_pedigree, age, diagnosis],
outputs=[result_box, radar_plot, importance_plot, tips_box]
)
gr.Markdown("""
## π About the Features
- **Pregnancies**: Number of times pregnant
- **Glucose**: Plasma glucose concentration (2 hours in an oral glucose tolerance test)
- **Blood Pressure**: Diastolic blood pressure (mm Hg)
- **Skin Thickness**: Triceps skin fold thickness (mm)
- **Insulin**: 2-Hour serum insulin (mu U/ml)
- **BMI**: Body mass index (weight in kg/(height in m)Β²)
- **Diabetes Pedigree**: A function scoring likelihood of diabetes based on family history
- **Age**: Age in years
""")
if __name__ == "__main__":
interface.launch() |