diff --git a/streamlit_app.py b/streamlit_app.py
index 2478d4b..e19a180 100644
--- a/streamlit_app.py
+++ b/streamlit_app.py
@@ -10,6 +10,7 @@ import pickle
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
+import time
# Configure Streamlit page
st.set_page_config(
@@ -19,46 +20,279 @@ st.set_page_config(
initial_sidebar_state="expanded"
)
-# Custom CSS for beautiful styling
+# Rose Pine Dark Theme CSS
st.markdown("""
""", unsafe_allow_html=True)
@@ -252,7 +486,10 @@ def main():
# Header
st.markdown('
Student Success Predictor
', unsafe_allow_html=True)
- st.markdown("**Predict whether a student will Graduate, Dropout, or remain Enrolled based on academic and demographic factors.**")
+ st.markdown('Predict whether a student will Graduate, Dropout, or remain Enrolled based on academic and demographic factors using advanced machine learning.
', unsafe_allow_html=True)
+
+ # Progress indicator (shows completion percentage)
+ progress_placeholder = st.empty()
# Sidebar for input
st.sidebar.markdown('', unsafe_allow_html=True)
@@ -260,10 +497,12 @@ def main():
# Create input form
with st.sidebar:
# Quick presets
- st.markdown("### Quick Start")
+ st.markdown('', unsafe_allow_html=True)
# Set default values based on preset
defaults = {
@@ -274,10 +513,16 @@ def main():
}
if preset != "Custom Entry":
- st.info(f"Loading {preset} preset values. You can modify any field below.")
+ st.markdown(f'โ
Loading {preset} preset values. You can modify any field below.
', unsafe_allow_html=True)
+
+ # Form progress tracking
+ form_sections = ["Personal Information", "Academic Background", "Family Background", "Financial & Social", "1st Semester Performance", "2nd Semester Performance", "Economic Indicators"]
+ current_section = 0
# Personal Information
- st.markdown("### Personal Information")
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### ๐ค Personal Information")
+ st.markdown('Basic demographic information about the student
', unsafe_allow_html=True)
marital_status = st.selectbox(
"Marital Status",
@@ -291,7 +536,9 @@ def main():
nationality = st.selectbox("Nationality", [1, 2, 6, 11, 13, 14, 17, 21, 22, 24, 25, 26, 32, 41, 62, 100, 101, 103, 105, 108, 109], index=0)
# Academic Background
- st.markdown("### Academic Background")
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### ๐ Academic Background")
+ st.markdown('Information about the student\'s application and academic history
', unsafe_allow_html=True)
application_mode = st.selectbox(
"Application Mode",
@@ -324,7 +571,9 @@ def main():
admission_grade = st.number_input("Admission Grade", min_value=95, max_value=190, value=defaults[preset]["adm_grade"], step=1)
# Family Background
- st.markdown("### Family Background")
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### ๐จโ๐ฉโ๐งโ๐ฆ Family Background")
+ st.markdown('Parent education and occupation information
', unsafe_allow_html=True)
mothers_qualification = st.selectbox(
"Mother's Qualification",
@@ -351,7 +600,9 @@ def main():
)
# Financial and Social Factors
- st.markdown("### Financial & Social")
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### ๐ฐ Financial & Social")
+ st.markdown('Student financial status and special circumstances
', unsafe_allow_html=True)
col1, col2 = st.columns(2)
with col1:
@@ -364,8 +615,9 @@ def main():
international = st.radio("International Student", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes", horizontal=True)
# Academic Performance - 1st Semester
- st.markdown("### 1st Semester Performance")
- st.caption("Enter the student's academic performance for their first semester")
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### ๐ 1st Semester Performance")
+ st.markdown('โ ๏ธ Important: Academic performance is a key predictor of student success
', unsafe_allow_html=True)
# Set default academic values based on preset
first_sem_defaults = {
@@ -386,8 +638,9 @@ def main():
curricular_units_1st_sem_without_evaluations = st.number_input("Without Evaluations", min_value=0, max_value=14, value=first_sem_defaults[preset]["without"], step=1, key="1st_without", help="Courses registered but not evaluated")
# Academic Performance - 2nd Semester
- st.markdown("### 2nd Semester Performance")
- st.caption("Enter the student's academic performance for their second semester")
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### ๐ 2nd Semester Performance")
+ st.markdown('Second semester data helps improve prediction accuracy
', unsafe_allow_html=True)
# Set default academic values for 2nd semester based on preset
second_sem_defaults = {
@@ -408,8 +661,9 @@ def main():
curricular_units_2nd_sem_without_evaluations = st.number_input("Without Evaluations", min_value=0, max_value=12, value=second_sem_defaults[preset]["without"], step=1, key="2nd_without", help="Courses registered but not evaluated")
# Economic Indicators
- st.markdown("### Economic Indicators")
- st.caption("These are typically set by the institution based on current economic conditions")
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### ๐ Economic Indicators")
+ st.markdown('๐ Economic context data - typically set by institution based on current conditions
', unsafe_allow_html=True)
col1, col2, col3 = st.columns(3)
with col1:
@@ -465,30 +719,93 @@ def main():
with col1:
st.markdown('', unsafe_allow_html=True)
- # Make prediction
- if st.button("Predict Student Outcome", type="primary"):
- with st.spinner("Analyzing student data..."):
- # Preprocess input
- processed_input = preprocess_input(user_input, preprocessing_info)
+ # Prediction button with enhanced styling
+ predict_button = st.button("๐ฌ Analyze Student Data", type="primary", use_container_width=True)
+
+ if predict_button:
+ # Enhanced loading animation
+ progress_bar = st.progress(0)
+ status_text = st.empty()
+
+ # Simulate processing steps
+ steps = [
+ ("Loading student data...", 20),
+ ("Preprocessing features...", 40),
+ ("Running machine learning model...", 70),
+ ("Calculating prediction confidence...", 90),
+ ("Finalizing results...", 100)
+ ]
+
+ for step, progress in steps:
+ status_text.text(step)
+ progress_bar.progress(progress)
+ time.sleep(0.3)
+
+ # Clear progress indicators
+ progress_bar.empty()
+ status_text.empty()
+
+ # Preprocess input
+ processed_input = preprocess_input(user_input, preprocessing_info)
+
+ # Make prediction
+ prediction = model.predict(processed_input)[0]
+ prediction_proba = model.predict_proba(processed_input)[0]
+
+ # Get prediction label
+ target_reverse_mapping = preprocessing_info['target_reverse_mapping']
+ predicted_outcome = target_reverse_mapping[prediction]
+
+ # Store in session state for export
+ st.session_state['last_prediction'] = {
+ 'outcome': predicted_outcome,
+ 'probabilities': prediction_proba,
+ 'timestamp': time.time()
+ }
+
+ # Enhanced prediction display with confidence indicators
+ confidence_level = max(prediction_proba)
+ confidence_text = "High" if confidence_level > 0.7 else "Medium" if confidence_level > 0.5 else "Low"
+
+ # Display prediction with enhanced styling and confidence
+ if predicted_outcome == "Graduate":
+ st.markdown(f'''
+ ๐ GRADUATE
+
Confidence: {confidence_level:.1%} ({confidence_text})
+
''', unsafe_allow_html=True)
+ st.balloons()
+ elif predicted_outcome == "Dropout":
+ st.markdown(f'''
+ โ ๏ธ AT RISK OF DROPOUT
+
Confidence: {confidence_level:.1%} ({confidence_text})
+
''', unsafe_allow_html=True)
+ else:
+ st.markdown(f'''
+ ๐ LIKELY TO STAY ENROLLED
+
Confidence: {confidence_level:.1%} ({confidence_text})
+
''', unsafe_allow_html=True)
- # Make prediction
- prediction = model.predict(processed_input)[0]
- prediction_proba = model.predict_proba(processed_input)[0]
+ # Add personalized recommendations based on prediction
+ st.markdown("### ๐ก Personalized Recommendations")
- # Get prediction label
- target_reverse_mapping = preprocessing_info['target_reverse_mapping']
- predicted_outcome = target_reverse_mapping[prediction]
-
- # Display prediction with styling
if predicted_outcome == "Graduate":
- st.markdown(f'Predicted Outcome: GRADUATE
', unsafe_allow_html=True)
+ st.markdown('๐ฏ Success Indicators: This student shows strong potential for graduation. Continue supporting their academic journey.
', unsafe_allow_html=True)
elif predicted_outcome == "Dropout":
- st.markdown(f'Predicted Outcome: DROPOUT
', unsafe_allow_html=True)
+ recommendations = []
+ if user_input['Curricular units 1st sem (approved)'] == 0:
+ recommendations.append("๐ **Academic Support:** Provide tutoring for struggling courses")
+ if user_input['Scholarship holder'] == 0:
+ recommendations.append("๐ฐ **Financial Aid:** Consider scholarship opportunities")
+ if user_input['Age at enrollment'] > 25:
+ recommendations.append("๐ **Flexible Scheduling:** Offer evening or part-time options")
+
+ if recommendations:
+ st.markdown('๐ฏ Intervention Strategies:
' + '
'.join(recommendations) + '
', unsafe_allow_html=True)
else:
- st.markdown(f'Predicted Outcome: ENROLLED
', unsafe_allow_html=True)
+ st.markdown('๐ Monitoring Needed: This student may benefit from regular check-ins and academic support.
', unsafe_allow_html=True)
# Display probabilities
- st.markdown("### Prediction Confidence")
+ st.markdown("### ๐ Prediction Confidence")
prob_df = pd.DataFrame({
'Outcome': ['Dropout', 'Enrolled', 'Graduate'],
@@ -539,16 +856,40 @@ def main():
""", unsafe_allow_html=True)
with col2:
- st.markdown('', unsafe_allow_html=True)
+ st.markdown('', unsafe_allow_html=True)
- st.info("""
- **Model Details:**
+ # Dynamic model information based on current inputs
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("""
+ **๐ค Model Details:**
- **Algorithm:** Random Forest Classifier
- - **Features:** 36 student characteristics
+ - **Features:** 36 student characteristics
- **Training Accuracy:** 100%
- **Test Accuracy:** 93.84%
- **Classes:** Graduate, Dropout, Enrolled
""")
+ st.markdown('
', unsafe_allow_html=True)
+
+ # Add input validation feedback
+ st.markdown("### ๐ Input Validation")
+ validation_container = st.container()
+
+ # Basic validation checks
+ validation_issues = []
+
+ # Check for unrealistic combinations
+ if user_input['Age at enrollment'] < 17:
+ validation_issues.append("โ ๏ธ Age seems too low for enrollment")
+ if user_input['Curricular units 1st sem (approved)'] > user_input['Curricular units 1st sem (enrolled)']:
+ validation_issues.append("โ ๏ธ Approved units exceed enrolled units (1st sem)")
+ if user_input['Curricular units 2nd sem (approved)'] > user_input['Curricular units 2nd sem (enrolled)']:
+ validation_issues.append("โ ๏ธ Approved units exceed enrolled units (2nd sem)")
+
+ if validation_issues:
+ for issue in validation_issues:
+ st.warning(issue)
+ else:
+ st.success("โ
All inputs look valid!")
st.markdown("### Key Factors")
st.markdown("""
@@ -593,10 +934,47 @@ def main():
)
st.plotly_chart(fig_perf, use_container_width=True)
+
+ # Add export functionality
+ st.markdown("### ๐ฅ Export Results")
+
+ if st.session_state.get('last_prediction'):
+ export_data = {
+ 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
+ 'prediction': st.session_state['last_prediction']['outcome'],
+ 'confidence': f"{max(st.session_state['last_prediction']['probabilities']):.1%}",
+ 'student_data': user_input
+ }
+
+ # Convert to JSON for download
+ import json
+ json_str = json.dumps(export_data, indent=2, ensure_ascii=False)
+
+ st.download_button(
+ label="๐ Download Prediction Report",
+ data=json_str,
+ file_name=f"student_prediction_{time.strftime('%Y%m%d_%H%M%S')}.json",
+ mime="application/json"
+ )
+
+ # Enhanced Footer with additional info
+ st.markdown('', unsafe_allow_html=True)
+ col1, col2, col3 = st.columns(3)
+
+ with col1:
+ st.markdown("**๐ Data Source**")
+ st.caption("UCI ML Repository - Student Academic Success")
+
+ with col2:
+ st.markdown("**๐ฌ Model Info**")
+ st.caption("Random Forest with 93.84% accuracy")
+
+ with col3:
+ st.markdown("**๐ ๏ธ Built With**")
+ st.caption("Streamlit โข scikit-learn โข Plotly")
- # Footer
st.markdown("---")
- st.markdown("*Developed using Streamlit and scikit-learn*")
+ st.markdown('๐ Empowering educational institutions with data-driven insights for student success
', unsafe_allow_html=True)
if __name__ == "__main__":
main()
\ No newline at end of file