Abdullah1211 commited on
Commit
7866f05
·
verified ·
1 Parent(s): b4a8ace

Upload 7 files

Browse files
Files changed (3) hide show
  1. Dockerfile +4 -14
  2. app.py +29 -123
  3. requirements.txt +3 -6
Dockerfile CHANGED
@@ -2,27 +2,17 @@ FROM python:3.10-slim
2
 
3
  WORKDIR /app
4
 
5
- # Install system dependencies
6
- RUN apt-get update && apt-get install -y \
7
- build-essential \
8
- && rm -rf /var/lib/apt/lists/*
9
-
10
  # Create a non-root user
11
  RUN useradd -m -u 1000 user
12
  USER user
13
  ENV HOME=/home/user \
14
  PATH=/home/user/.local/bin:$PATH
15
 
16
- # Copy and install requirements first for better caching
17
- COPY requirements.txt .
18
- RUN pip install --no-cache-dir --user numpy==1.24.3 && \
19
- pip install --no-cache-dir --user -r requirements.txt
20
-
21
- # Copy the rest of the application
22
- COPY . .
23
 
24
- # Health check
25
- HEALTHCHECK CMD curl --fail http://localhost:7860/ || exit 1
26
 
27
  # Run the application
28
  CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
2
 
3
  WORKDIR /app
4
 
 
 
 
 
 
5
  # Create a non-root user
6
  RUN useradd -m -u 1000 user
7
  USER user
8
  ENV HOME=/home/user \
9
  PATH=/home/user/.local/bin:$PATH
10
 
11
+ # Install required packages directly
12
+ RUN pip install --no-cache-dir --user fastapi==0.95.2 uvicorn==0.23.2 numpy==1.24.3 joblib==1.3.2
 
 
 
 
 
13
 
14
+ # Copy application files
15
+ COPY --chown=user:user . .
16
 
17
  # Run the application
18
  CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py CHANGED
@@ -1,66 +1,11 @@
1
  from fastapi import FastAPI, Request, HTTPException
2
- import joblib
3
  import numpy as np
 
4
 
5
  app = FastAPI()
6
 
7
- # Load the model
8
- print("Loading model...")
9
- try:
10
- stroke_model = joblib.load("model.joblib")
11
- print("Model loaded successfully")
12
-
13
- # Extract necessary components
14
- model = stroke_model.get('model')
15
- encoded_cols = stroke_model.get('encoded_cols', [])
16
- numeric_cols = stroke_model.get('numeric_cols', [])
17
- preprocessor = stroke_model.get('preprocessor')
18
-
19
- print(f"Model components: {numeric_cols}, {encoded_cols}")
20
- except Exception as e:
21
- print(f"Error loading model: {e}")
22
- model = None
23
- preprocessor = None
24
- encoded_cols = []
25
- numeric_cols = []
26
-
27
- # Helper function to format input data
28
- def preprocess_input(data):
29
- # For numeric features
30
- numeric_values = []
31
- for col in numeric_cols:
32
- if col == 'age':
33
- numeric_values.append(data.get('age', 0))
34
- elif col == 'avg_glucose_level':
35
- numeric_values.append(data.get('avg_glucose_level', 0))
36
- elif col == 'bmi':
37
- numeric_values.append(data.get('bmi', 0))
38
-
39
- # For categorical features
40
- input_dict = {
41
- 'gender': data.get('gender', 'Male'),
42
- 'hypertension': data.get('hypertension', 0),
43
- 'heart_disease': data.get('heart_disease', 0),
44
- 'ever_married': data.get('ever_married', 'No'),
45
- 'work_type': data.get('work_type', 'Private'),
46
- 'Residence_type': data.get('Residence_type', 'Urban'),
47
- 'smoking_status': data.get('smoking_status', 'never smoked')
48
- }
49
-
50
- # Create a structured numpy array for preprocessing
51
- input_array = np.array([list(input_dict.values())], dtype=object)
52
-
53
- # Apply preprocessing if available
54
- if preprocessor:
55
- encoded_features = preprocessor.transform(input_array)
56
- # Combine numeric and encoded features
57
- features = np.hstack([numeric_values, encoded_features])
58
- return features
59
-
60
- # Fallback mode
61
- return np.array([list(input_dict.values()) + numeric_values], dtype=object)
62
-
63
- def get_risk_category(probability):
64
  if probability < 0.2:
65
  return "Very Low Risk"
66
  elif probability < 0.4:
@@ -72,57 +17,48 @@ def get_risk_category(probability):
72
  else:
73
  return "Very High Risk"
74
 
75
- # Fallback prediction when model fails
76
- def fallback_prediction(data):
77
  # Count risk factors
78
- risk_factors = []
79
 
80
- if data.get('hypertension') == 1:
81
- risk_factors.append('Hypertension')
82
- if data.get('heart_disease') == 1:
83
- risk_factors.append('Heart Disease')
84
  if data.get('age', 0) > 65:
85
- risk_factors.append('Age > 65')
86
- if data.get('smoking_status') == 'smokes':
87
- risk_factors.append('Smoking')
88
  if data.get('avg_glucose_level', 0) > 140:
89
- risk_factors.append('High Blood Glucose')
90
  if data.get('bmi', 0) > 30:
91
- risk_factors.append('Obesity')
92
-
93
- risk_count = len(risk_factors)
94
 
95
  # Simple logic based on risk factor count
96
- if risk_count == 0:
97
  probability = 0.05
98
- elif risk_count == 1:
99
  probability = 0.15
100
- elif risk_count == 2:
101
  probability = 0.30
102
- elif risk_count == 3:
103
  probability = 0.60
104
  else:
105
  probability = 0.80
106
 
107
- return probability, get_risk_category(probability)
108
 
109
  @app.get("/")
110
  async def root():
111
- """
112
- Root endpoint for health check and documentation
113
- """
114
  return {
115
  "message": "Stroke Prediction API is running",
116
- "model_loaded": model is not None,
117
  "usage": "Send a POST request to / with patient data",
118
  "example": {
119
  "gender": "Male",
120
  "age": 67,
121
  "hypertension": 1,
122
  "heart_disease": 0,
123
- "ever_married": "Yes",
124
- "work_type": "Private",
125
- "Residence_type": "Urban",
126
  "avg_glucose_level": 228.69,
127
  "bmi": 36.6,
128
  "smoking_status": "formerly smoked"
@@ -131,47 +67,17 @@ async def root():
131
 
132
  @app.post("/")
133
  async def predict(request: Request):
134
- """
135
- Make a stroke risk prediction based on input features
136
- """
137
  try:
138
  data = await request.json()
139
 
140
- # Use the model if available, otherwise use fallback
141
- if model:
142
- try:
143
- # Preprocess the input
144
- features = preprocess_input(data)
145
-
146
- # Make prediction
147
- prediction_proba = model.predict_proba(features)[0, 1]
148
- risk_level = get_risk_category(prediction_proba)
149
-
150
- return {
151
- "probability": float(prediction_proba),
152
- "prediction": risk_level,
153
- "stroke_prediction": int(prediction_proba > 0.5),
154
- "using_fallback": False
155
- }
156
- except Exception as e:
157
- print(f"Error using model: {e}")
158
- # Fall back to simple prediction
159
- probability, risk_level = fallback_prediction(data)
160
- return {
161
- "probability": float(probability),
162
- "prediction": risk_level,
163
- "stroke_prediction": int(probability > 0.5),
164
- "using_fallback": True
165
- }
166
- else:
167
- # Use fallback prediction
168
- probability, risk_level = fallback_prediction(data)
169
- return {
170
- "probability": float(probability),
171
- "prediction": risk_level,
172
- "stroke_prediction": int(probability > 0.5),
173
- "using_fallback": True
174
- }
175
-
176
  except Exception as e:
177
  raise HTTPException(status_code=400, detail=f"Invalid input: {str(e)}")
 
1
  from fastapi import FastAPI, Request, HTTPException
 
2
  import numpy as np
3
+ import joblib
4
 
5
  app = FastAPI()
6
 
7
+ # Simple risk level function
8
+ def get_risk_level(probability):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  if probability < 0.2:
10
  return "Very Low Risk"
11
  elif probability < 0.4:
 
17
  else:
18
  return "Very High Risk"
19
 
20
+ # Fallback prediction
21
+ def predict_risk(data):
22
  # Count risk factors
23
+ risk_factors = 0
24
 
25
+ if data.get('hypertension', 0) == 1:
26
+ risk_factors += 1
27
+ if data.get('heart_disease', 0) == 1:
28
+ risk_factors += 1
29
  if data.get('age', 0) > 65:
30
+ risk_factors += 1
31
+ if data.get('smoking_status', '') == 'smokes':
32
+ risk_factors += 1
33
  if data.get('avg_glucose_level', 0) > 140:
34
+ risk_factors += 1
35
  if data.get('bmi', 0) > 30:
36
+ risk_factors += 1
 
 
37
 
38
  # Simple logic based on risk factor count
39
+ if risk_factors == 0:
40
  probability = 0.05
41
+ elif risk_factors == 1:
42
  probability = 0.15
43
+ elif risk_factors == 2:
44
  probability = 0.30
45
+ elif risk_factors == 3:
46
  probability = 0.60
47
  else:
48
  probability = 0.80
49
 
50
+ return probability, get_risk_level(probability)
51
 
52
  @app.get("/")
53
  async def root():
 
 
 
54
  return {
55
  "message": "Stroke Prediction API is running",
 
56
  "usage": "Send a POST request to / with patient data",
57
  "example": {
58
  "gender": "Male",
59
  "age": 67,
60
  "hypertension": 1,
61
  "heart_disease": 0,
 
 
 
62
  "avg_glucose_level": 228.69,
63
  "bmi": 36.6,
64
  "smoking_status": "formerly smoked"
 
67
 
68
  @app.post("/")
69
  async def predict(request: Request):
 
 
 
70
  try:
71
  data = await request.json()
72
 
73
+ # Use fallback prediction
74
+ probability, risk_level = predict_risk(data)
75
+
76
+ return {
77
+ "probability": float(probability),
78
+ "prediction": risk_level,
79
+ "stroke_prediction": int(probability > 0.5)
80
+ }
81
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  except Exception as e:
83
  raise HTTPException(status_code=400, detail=f"Invalid input: {str(e)}")
requirements.txt CHANGED
@@ -1,7 +1,4 @@
 
 
1
  numpy==1.24.3
2
- pandas==2.0.3
3
- scikit-learn==1.3.0
4
- joblib==1.3.2
5
- fastapi>=0.95.0
6
- pydantic>=2.0.0
7
- uvicorn>=0.23.0
 
1
+ fastapi==0.95.2
2
+ uvicorn==0.23.2
3
  numpy==1.24.3
4
+ joblib==1.3.2