Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions flask_backend/models/LungCancer/LungCancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import joblib
#Importing necessary modules from sklearn
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
Expand All @@ -11,8 +12,7 @@

#Importing Dataset GSE74777_series_matrix.txt.gz
# Tab-separated file
train_table = pd.read_csv(r"C:\Users\cpkbh\OneDrive\Desktop\PredictMod\GSE74777_series_matrix.csv"
)
train_table = pd.read_csv("GSE74777_series_matrix.csv")
# ignores lines starting with !
print("Table Loaded")
print(train_table.head())
Expand All @@ -32,6 +32,13 @@
X = train_table.drop(["Responder"], axis=1)
y = train_table["Responder"]

print(train_table.head(2))
train_table.head(1).to_csv("train_table_head.csv", index=False)
print('Printing json....')
train_table.head(2).to_json("testInput.json", orient='records')

train_table =train_table.iloc[2:].reset_index(drop=True) # drop first two rows (metadata)

# ---- Scale features ----
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
Expand All @@ -48,19 +55,21 @@
)

print("Ready to Go")

print(X_test[0,:])
#Viewing performance metrics of Random Forest Classifier

RF = RandomForestClassifier(random_state=123)
RF.fit(X_train,y_train)
print(f'RandomForestClassifier train score: {RF.score(X_train,y_train)}')
print(f'RandomForestClassifier test score: {RF.score(X_test,y_test)}')
print(confusion_matrix(y_test, RF.predict(X_test)))
print(classification_report(y_test, RF.predict(X_test)))
rf = RandomForestClassifier(random_state=123)
rf.fit(X_train,y_train)
print(f'RandomForestClassifier train score: {rf.score(X_train,y_train)}')
print(f'RandomForestClassifier test score: {rf.score(X_test,y_test)}')
print(confusion_matrix(y_test, rf.predict(X_test)))
print(classification_report(y_test, rf.predict(X_test)))
from sklearn.metrics import ConfusionMatrixDisplay

# Get predictions ONCE (cleaner)
y_pred = RF.predict(X_test)
y_pred = rf.predict(X_test)

data = {'classifier': rf, 'features': list(X.columns)}
joblib.dump(data, 'LungCancer_classifier_and_features.pickle')

# Plot confusion matrix
ConfusionMatrixDisplay.from_predictions(
Expand All @@ -78,7 +87,7 @@
from sklearn.metrics import roc_curve, auc

# Get probability predictions (NOT just 0/1 labels)
y_probs = RF.predict_proba(X_test)[:, 1]
y_probs = rf.predict_proba(X_test)[:, 1]

# Compute ROC curve
fpr, tpr, thresholds = roc_curve(y_test, y_probs)
Expand Down
14 changes: 14 additions & 0 deletions flask_backend/models/LungCancer/dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy your dictionary pickle file and script
COPY LungCancer_classifier_and_features.pickle .
COPY main.py .

EXPOSE 8080

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
58 changes: 58 additions & 0 deletions flask_backend/models/LungCancer/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import joblib
import pandas as pd
from typing import Dict, Any

app = FastAPI(title = "Lung Cancer Prediction API")

#load model file
data = joblib.load('LungCancer_classifier_and_features.pickle')

# Unpack classifier and required feature column names
model = data['classifier']
expected_features = data['features']

# Define flexible request payload (Dictionary matching feature names -> values)
class PredictRequest(BaseModel):
inputs: Dict[str, Any]

@app.get("/")
def home():
return {
"status": "online",
"expected_features": expected_features
}

@app.post("/predict")
def predict(request: PredictRequest):
try:
# Convert incoming JSON dict to a pandas DataFrame with exact column ordering
input_df = pd.DataFrame([request.inputs])
print("Received input: {input_df.to_dict(orient='records')[0]}") # Log the received input
# Ensure all required features are present in the incoming payload
missing_cols = set(expected_features) - set(input_df.columns)
if missing_cols:
raise HTTPException(
status_code=400,
detail=f"Missing feature columns: {list(missing_cols)}"
)

# Reorder columns to strictly match X.columns from training
input_df = input_df[expected_features]

# Predict using the extracted Random Forest model
prediction = model.predict(input_df)

# Optional: Get prediction probabilities if classification
probability = None
if hasattr(model, "predict_proba"):
probability = model.predict_proba(input_df).tolist()

return {
"prediction": int(prediction[0]) if hasattr(prediction[0], 'item') else prediction[0],
"probabilities": probability
}

except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
Empty file.
14 changes: 14 additions & 0 deletions flask_backend/models/LungCancer/readme.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
python -m venv .venv


source .venv/bin/activate
Create requirements.txt with list of libraries
pip install -r requirements.txt
save the model into a pickle file using joblib

created API server as main.python
load model and create HTTP endpoint
create dockerfile
uvicorn main:app --reload --host 127.0.0.1 --port 8080

curl -X POST "http://localhost:8080/predict" -H "Content-Type: application/json" -d @testInput.json
7 changes: 7 additions & 0 deletions flask_backend/models/LungCancer/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pandas
numpy
matplotlib
scikit-learn
fastapi
pydantic
uvicorn
Loading