JoanaS's picture
Update app.py
0726909 verified
## Batch Evaluation Code
##Import Libraries
import pandas as pd
import json
from joblib import load
import gradio as gr
from sklearn.metrics import accuracy_score, classification_report
## Load Model
model = load("rf_activity_model.pkl") # ensure uploaded to HF Space
# Load from code(A–S) to int mapping
with open("label_map.json", "r") as f:
label_to_int = json.load(f)
## Reverse mapping from integer to code(A-S)
int_to_label = {v: k for k, v in label_to_int.items()}
# Load json containing activity name mapping (A–S) to the layman activity
with open("activity_names.json", "r") as f:
activity_names = json.load(f)
# Risk map of A-S to risk tier for alerting logic
risk_map = {
"A": "Medium", "B": "High", "C": "High", "D": "Low", "E": "Medium",
"F": "Low", "G": "Low", "H": "Medium", "I": "Medium", "J": "Medium",
"K": "Medium", "L": "Medium", "M": "High", "O": "High", "P": "High",
"Q": "Low", "R": "Low", "S": "Low"
}
# Threshold for triggering alert in samples
HIGH_THRESHOLD = 30
MEDIUM_THRESHOLD = 180
LOW_THRESHOLD = 90
def analyze_csv(file):
## Read CSV
df = pd.read_csv(file)
## Drop activity column, only taking the columns which are the features for inference
X = df.drop(columns=["ACTIVITY"])
preds_int = model.predict(X)
## Convert integers to code(A-S)
preds_code = [int_to_label[i] for i in preds_int]
## Convert code to human readable activity names
preds_activity = [activity_names[c] for c in preds_code]
## Convert codes to risk tiers(Low, Medium, High)
preds_risk = [risk_map[c] for c in preds_code]
## Build the result table for the user interface, showing the predicted activity, risk and the actual activity
results_df = pd.DataFrame({
#"pred_code": preds_code,
"Predicted_Activity": preds_activity,
"Risk Level": preds_risk
})
## Default message if the CSV lacks ground-truth label("ACTIVITY")
metrics_text = "⚠️ Ground truth labels not found in CSV"
## If CSV contain the ground-truth label("ACTIVITY")
if "ACTIVITY" in df.columns:
## Convert Ground Truth integer to code (A-S)
actual_codes = df["ACTIVITY"].map(int_to_label)
## Convert codes to human friendly readable activity names
actual_names = actual_codes.map(activity_names)
## Add ground-truth activity for side-by-side viewing
results_df["Actual_Activity"] = actual_names
# Checks the model's accuracy and generates a detailed report for each activity class
acc = accuracy_score(actual_codes, preds_code)
report = classification_report(actual_codes, preds_code, zero_division=0)
metrics_text = f"✅ Accuracy: {acc:.3f}\n\nClassification Report:\n{report}"
## Tracks consecutive counts per risk
high_count = medium_count = low_count = 0
## Collect alert messages for display
alerts = []
##Iterate through risk predictions in order to simulate timeline
for i, risk in enumerate(preds_risk):
if risk == "High":
## If high count exceeds the high threshold, print alert
high_count += 1; medium_count = 0; low_count = 0
if high_count >= HIGH_THRESHOLD:
alerts.append(f"⚠️ ALERT: Prolonged HIGH-RISK activity at index {i}")
high_count = 0
elif risk == "Medium":
## If medium count exceeds the medium threshold, print alert
medium_count += 1; high_count = 0; low_count = 0
if medium_count >= MEDIUM_THRESHOLD:
alerts.append(f"⚠️ ALERT: Prolonged MEDIUM-RISK activity at index {i}")
medium_count = 0
elif risk == "Low":
## If low count exceeds the low threshold, print alert
low_count += 1; high_count = 0; medium_count = 0
if low_count >= LOW_THRESHOLD:
alerts.append(f"⚠️ ALERT: Prolonged LOW-RISK activity at index {i}")
low_count = 0
# Return table, metrics summary, and alerts, or no alert message
return results_df, metrics_text, "\n".join(alerts) if alerts else "✅ No alerts triggered."
## Gradio User Interface
with gr.Blocks() as demo:
gr.Markdown("## Healthcare Activity Recognition")
gr.Markdown("Upload a CSV of sensor features. The model predicts activities, assigns risk levels, "
"and compares them to actuals if provided. Metrics (accuracy + classification report) are also displayed.")
with gr.Row():
##Row to input the file
file_input = gr.File(type="filepath", file_types=[".csv"], label="Upload CSV")
with gr.Row():
with gr.Column(scale=2):
results_df = gr.Dataframe(
headers=["Predicted_Activity", "Risk Level", "Actual_Activity"],
label="Predictions vs Actuals",
wrap=True,
##This is for fixing only 3 columns for consistency
datatype=["str", "str", "str"],
col_count=(3, "fixed"),
interactive=False
)
with gr.Column(scale=1):
##Show accuracy and classification report
metrics_box = gr.Textbox(label="Metrics", lines=8)
##Shows alert list or “No alerts”
alerts_box = gr.Textbox(label="Alerts", lines=6)
# When a file is uploaded, run analyze_csv() and show results in the table, metrics, and alerts
file_input.change(
fn=analyze_csv,
inputs=file_input,
outputs=[results_df, metrics_box, alerts_box]
)
##Start the Gradio app if this script is the main entry point
if __name__ == "__main__":
demo.launch()