| import streamlit as st |
| import joblib |
| import pandas as pd |
| import numpy as np |
|
|
| |
| MODEL_PATH = 'src/kn_perormance_prediction.joblib' |
| ENCODERS_PATH = 'src/label_encoders.joblib' |
|
|
| |
| FEATURES = [ |
| 'gender', |
| 'race/ethnicity', |
| 'parental level of education', |
| 'lunch', |
| 'test preparation course', |
| 'math score', |
| 'reading score', |
| 'writing score', |
| 'total_score', |
| 'percentage' |
| ] |
|
|
| RACE_MAP = { |
| 'group A': 1, 'group B': 2, 'group C': 3, |
| 'group D': 4, 'group E': 5 |
| } |
|
|
| @st.cache_resource |
| def load_assets(): |
| try: |
| model = joblib.load(MODEL_PATH) |
| encoders = joblib.load(ENCODERS_PATH) |
| return model, encoders |
| except Exception as e: |
| st.error(f"Error loading model or encoders: {e}") |
| return None, None |
|
|
|
|
| def preprocess_and_predict(model, encoders, input_data): |
|
|
| df_input = pd.DataFrame([input_data]) |
|
|
| |
| df_input['race/ethnicity'] = df_input['race/ethnicity'].map(RACE_MAP) |
|
|
| |
| for col, le in encoders.items(): |
| df_input[col] = le.transform(df_input[col]) |
|
|
| |
| df_input['total_score'] = ( |
| df_input['math score'] + |
| df_input['reading score'] + |
| df_input['writing score'] |
| ) |
|
|
| df_input['percentage'] = df_input['total_score'] / 3 |
|
|
| |
| final_input_array = df_input[FEATURES].values |
|
|
| |
| prediction_label = model.predict(final_input_array) |
|
|
| return prediction_label[0] |
|
|
|
|
| |
| st.set_page_config(page_title="Student Performance", layout="centered") |
| st.title("📚 Student Final Grade Predictor (A–E)") |
| st.markdown("Enter student characteristics and scores to predict the final letter grade.") |
|
|
| model, encoders = load_assets() |
|
|
| if model is not None and encoders is not None: |
| st.sidebar.header("Student Information") |
|
|
| gender = st.sidebar.selectbox("Gender:", options=['male', 'female']) |
| race = st.sidebar.selectbox("Race/Ethnicity:", options=list(RACE_MAP.keys())) |
| parental_education = st.sidebar.selectbox( |
| "Parental Education:", |
| options=[ |
| 'some high school', 'high school', 'some college', |
| "associate's degree", "bachelor's degree", "master's degree" |
| ] |
| ) |
| lunch = st.sidebar.selectbox("Lunch:", options=['standard', 'free/reduced']) |
| prep_course = st.sidebar.selectbox("Test Prep Course:", options=['none', 'completed']) |
|
|
| st.sidebar.header("Scores (0-100)") |
| math = st.sidebar.slider("Math Score:", 0, 100, 70) |
| reading = st.sidebar.slider("Reading Score:", 0, 100, 75) |
| writing = st.sidebar.slider("Writing Score:", 0, 100, 72) |
|
|
| input_data = { |
| 'gender': gender, |
| 'race/ethnicity': race, |
| 'parental level of education': parental_education, |
| 'lunch': lunch, |
| 'test preparation course': prep_course, |
| 'math score': math, |
| 'reading score': reading, |
| 'writing score': writing |
| } |
|
|
| if st.button("Predict Final Grade"): |
| with st.spinner("Calculating prediction..."): |
| predicted_grade = preprocess_and_predict(model, encoders, input_data) |
| |
| st.success("Prediction Successful!") |
| st.markdown("### Predicted Letter Grade:") |
| st.markdown(f"**{predicted_grade}**") |