Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import numpy as np | |
| import pandas as pd | |
| # ββ Constants ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| LABEL_MAP = { | |
| 0: "WALKING", | |
| 1: "WALKING_UPSTAIRS", | |
| 2: "WALKING_DOWNSTAIRS", | |
| 3: "SITTING", | |
| 4: "STANDING", | |
| 5: "LAYING", | |
| } | |
| EXPLANATIONS = { | |
| "LAYING": "Minimal movement detected across all axes with low acceleration magnitude β consistent with a stationary horizontal posture.", | |
| "SITTING": "Low dynamic acceleration with a stable gravity component suggests a stationary upright posture with little body movement.", | |
| "STANDING": "Similar to sitting but with slight postural micro-movements. This class is often the hardest to distinguish from sitting.", | |
| "WALKING": "Rhythmic periodic acceleration with peaks on the vertical axis β consistent with level walking at normal cadence.", | |
| "WALKING_DOWNSTAIRS": "Downward gravitational shift with higher impact peaks characteristic of descending a staircase.", | |
| "WALKING_UPSTAIRS": "Elevated vertical acceleration effort with upward body displacement β consistent with climbing stairs.", | |
| } | |
| # ββ Model loader ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def load_model(): | |
| try: | |
| import tensorflow as tf | |
| from model_def import FeedForwardNetwork | |
| model = tf.keras.models.load_model( | |
| "model.keras", | |
| custom_objects={"FeedForwardNetwork": FeedForwardNetwork}, | |
| ) | |
| return model, "ready" | |
| except Exception as e: | |
| return None, f"error: {e}" | |
| # ββ Page config βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| st.set_page_config( | |
| page_title="Human Activity Recognition", | |
| page_icon="π", | |
| layout="centered" | |
| ) | |
| st.title("Human Activity Recognition") | |
| st.markdown( | |
| "Deep learning classifier trained on 561 smartphone sensor features " | |
| "from the [UCI HAR dataset](https://www.kaggle.com/datasets/uciml/human-activity-recognition-with-smartphones). " | |
| "Classifies six daily activities from accelerometer and gyroscope readings." | |
| ) | |
| # ββ Sidebar ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with st.sidebar: | |
| st.header("About") | |
| st.markdown(""" | |
| **Dataset:** UCI Human Activity Recognition | |
| **Subjects:** 30 volunteers aged 19β48 | |
| **Sensor:** Samsung Galaxy S II (waist-mounted) | |
| **Sampling rate:** 50Hz | |
| **Features:** 561 time + frequency domain features | |
| **Classes:** 6 activities of daily living | |
| """) | |
| st.markdown("---") | |
| st.markdown("**Model performance on test set**") | |
| st.metric("Architecture", "FFN 512β256β128") | |
| st.metric("Status", "FFN live Β· CNN pending") | |
| st.markdown("---") | |
| st.caption("DAT606 Group Assignment Β· Pan-Atlantic University") | |
| # ββ Model status βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| model, model_status = load_model() | |
| if model_status != "ready": | |
| st.warning(f"Model not loaded β {model_status}") | |
| # ββ Tabs βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| tab1, tab2 = st.tabs(["Select a Sample", "Upload Phyphox CSV"]) | |
| # ββ Tab 1: Sample selector βββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with tab1: | |
| st.subheader("Select a pre-loaded test sample") | |
| st.caption( | |
| "Each sample is one 2.56-second window of sensor data " | |
| "from a test subject the model has never seen during training." | |
| ) | |
| try: | |
| samples_df = pd.read_csv("data/samples.csv") | |
| feature_cols = [ | |
| c for c in samples_df.columns | |
| if c not in ["Activity", "subject"] | |
| ] | |
| sample_labels = [ | |
| f"Sample {i+1} β {row['Activity']}" | |
| for i, (_, row) in enumerate(samples_df.iterrows()) | |
| ] | |
| selected = st.selectbox("Choose a sample:", sample_labels) | |
| selected_idx = sample_labels.index(selected) | |
| selected_row = samples_df.iloc[selected_idx] | |
| true_label = selected_row["Activity"] | |
| feature_vector = selected_row[feature_cols].values.astype(np.float32) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.metric("True Activity", true_label) | |
| with col2: | |
| st.metric("Feature count", len(feature_vector)) | |
| if st.button("Classify this sample", type="primary"): | |
| if model_status == "no_model": | |
| st.error("Model not loaded β cannot predict yet.") | |
| else: | |
| arr = feature_vector.reshape(1, -1) | |
| probs = model.predict(arr, verbose=0)[0] | |
| pred_idx = int(np.argmax(probs)) | |
| pred_label = LABEL_MAP[pred_idx] | |
| confidence = float(probs[pred_idx]) * 100 | |
| correct = pred_label == true_label | |
| st.markdown("---") | |
| st.subheader("Result") | |
| if correct: | |
| st.success( | |
| f"**{pred_label}** Β· {confidence:.1f}% confidence Β· β Correct" | |
| ) | |
| else: | |
| st.error( | |
| f"**{pred_label}** Β· {confidence:.1f}% confidence Β· " | |
| f"β Incorrect (true: {true_label})" | |
| ) | |
| st.markdown(f"_{EXPLANATIONS[pred_label]}_") | |
| st.markdown("**Confidence across all classes**") | |
| chart_data = pd.DataFrame({ | |
| "Confidence (%)": [ | |
| float(probs[i]) * 100 for i in range(6) | |
| ] | |
| }, index=[LABEL_MAP[i] for i in range(6)]) | |
| st.bar_chart(chart_data) | |
| except FileNotFoundError: | |
| st.error("Sample data file not found. Add `data/samples.csv` to the repo.") | |
| # ββ Tab 2: Phyphox upload (placeholder) βββββββββββββββββββββββββββββββββββββ | |
| with tab2: | |
| st.subheader("Upload Phyphox sensor recording") | |
| st.markdown(""" | |
| **How to record your own data:** | |
| 1. Install [Phyphox](https://phyphox.org/) on your phone | |
| 2. Open the **Acceleration (without g)** and **Gyroscope** experiments | |
| 3. Record at least 3 seconds of a single activity | |
| 4. Export as CSV and upload below | |
| """) | |
| uploaded_file = st.file_uploader( | |
| "Upload Phyphox CSV export", | |
| type=["csv"], | |
| help="Export from Phyphox as CSV β must contain accelerometer and gyroscope columns" | |
| ) | |
| if uploaded_file is not None: | |
| st.info( | |
| "Phyphox pipeline coming soon. " | |
| "Feature extraction from raw sensor readings " | |
| "(filtering β jerk β FFT β 561 features) is under development." | |
| ) | |
| try: | |
| preview = pd.read_csv(uploaded_file) | |
| st.markdown("**File preview:**") | |
| st.dataframe(preview.head(10)) | |
| st.caption( | |
| f"{len(preview)} rows Β· {len(preview.columns)} columns detected" | |
| ) | |
| except Exception as e: | |
| st.error(f"Could not read file: {e}") | |