Files
predictive_analysis/train_and_save_model.py
andwati ed2ff5b359 Add Streamlit app for student success prediction and model training script
- Created `streamlit_app.py` for a user-friendly dashboard to predict student outcomes using a Random Forest model.
- Added `requirements.txt` to specify necessary Python packages for the application.
- Implemented `train_and_save_model.py` to train the Random Forest model and save it along with preprocessing information.
- Included detailed user input forms for various student characteristics and academic performance metrics.
- Added custom styling for better UI/UX in the Streamlit app.
- Integrated prediction results display with probability metrics and model performance insig
2025-09-27 23:45:14 +03:00

163 lines
6.8 KiB
Python

"""
Model Training and Pickle Export Script
This script recreates the Random Forest model training process and saves the model and preprocessing pipeline.
"""
import pandas as pd
import numpy as np
import pickle
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score
def load_and_preprocess_data():
"""Load and preprocess the data exactly as done in the notebook"""
# Load data
dataFileNamePath = "./data/data.csv"
masterRawData = pd.read_csv(dataFileNamePath)
data = masterRawData.copy()
# Fix column name typo
data.rename(columns={'Nacionality': 'Nationality'}, inplace=True)
# Remove apostrophes from column names
for column_name in data.columns:
if "'" in column_name:
new_column_name = column_name.replace("'", "")
data.rename(columns={column_name: new_column_name}, inplace=True)
return data
def encode_target_variable(data):
"""Encode the target variable as done in the notebook"""
# Label mapping from the notebook analysis
target_mapping = {'Dropout': 0, 'Enrolled': 1, 'Graduate': 2}
data['Target_encoded'] = data['Target'].map(target_mapping)
return data
def prepare_features_for_modeling(data):
"""Prepare features exactly as done in the notebook"""
# Get all categorical columns that need one-hot encoding
categorical_columns = [
'Marital status', 'Application mode', 'Course', 'Daytime/evening attendance',
'Previous qualification', 'Nationality', 'Mothers qualification',
'Fathers qualification', 'Mothers occupation', 'Fathers occupation',
'Gender', 'Displaced', 'Educational special needs', 'Debtor',
'Tuition fees up to date', 'Scholarship holder', 'International'
]
# Additional columns that might be categorical (from notebook analysis)
for col in data.columns:
if col not in categorical_columns and col not in ['Target', 'Target_encoded']:
unique_vals = data[col].nunique()
# If low unique values, likely categorical
if unique_vals <= 20 and col not in ['Age at enrollment']:
categorical_columns.append(col)
# Create a copy for processing
processed_data = data.copy()
# Perform one-hot encoding for categorical columns
for column in categorical_columns:
if column in processed_data.columns:
# Get dummies with prefix
dummies = pd.get_dummies(processed_data[column], prefix=column)
# Concatenate with original data
processed_data = pd.concat([processed_data, dummies], axis=1)
# Drop original column
processed_data.drop(columns=[column], inplace=True)
# Drop the original Target column, keep Target_encoded
processed_data.drop(columns=['Target'], inplace=True)
return processed_data
def train_and_save_model():
"""Train the Random Forest model and save both model and preprocessing info"""
# Load and preprocess data
print("Loading and preprocessing data...")
data = load_and_preprocess_data()
# Encode target variable
data = encode_target_variable(data)
# Prepare features
processed_data = prepare_features_for_modeling(data)
# Separate features and target
X = processed_data.drop('Target_encoded', axis=1)
y = processed_data['Target_encoded']
print(f"Final dataset shape: {X.shape}")
print(f"Features: {X.columns.tolist()}")
# Split data (using 30% test size as in the notebook)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=42)
# Train Random Forest model
print("Training Random Forest model...")
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42)
rf_classifier.fit(X_train, y_train)
# Evaluate model
train_accuracy = rf_classifier.score(X_train, y_train)
test_accuracy = rf_classifier.score(X_test, y_test)
print(f"Training Accuracy: {train_accuracy:.4f}")
print(f"Test Accuracy: {test_accuracy:.4f}")
# Save the trained model
with open('random_forest_model.pkl', 'wb') as f:
pickle.dump(rf_classifier, f)
# Save feature names for consistency
feature_names = X.columns.tolist()
with open('feature_names.pkl', 'wb') as f:
pickle.dump(feature_names, f)
# Save preprocessing information
preprocessing_info = {
'target_mapping': {'Dropout': 0, 'Enrolled': 1, 'Graduate': 2},
'target_reverse_mapping': {0: 'Dropout', 1: 'Enrolled', 2: 'Graduate'},
'categorical_columns': [
'Marital status', 'Application mode', 'Course', 'Daytime/evening attendance',
'Previous qualification', 'Nationality', 'Mothers qualification',
'Fathers qualification', 'Mothers occupation', 'Fathers occupation',
'Gender', 'Displaced', 'Educational special needs', 'Debtor',
'Tuition fees up to date', 'Scholarship holder', 'International',
'Application order' # Adding this based on notebook analysis
],
'feature_names': feature_names,
'original_columns': [
'Marital status', 'Application mode', 'Application order', 'Course',
'Daytime/evening attendance', 'Previous qualification',
'Previous qualification (grade)', 'Nationality', 'Mothers qualification',
'Fathers qualification', 'Mothers occupation', 'Fathers occupation',
'Admission grade', 'Displaced', 'Educational special needs', 'Debtor',
'Tuition fees up to date', 'Gender', 'Scholarship holder',
'Age at enrollment', 'International', 'Curricular units 1st sem (credited)',
'Curricular units 1st sem (enrolled)', 'Curricular units 1st sem (evaluations)',
'Curricular units 1st sem (approved)', 'Curricular units 1st sem (grade)',
'Curricular units 1st sem (without evaluations)',
'Curricular units 2nd sem (credited)', 'Curricular units 2nd sem (enrolled)',
'Curricular units 2nd sem (evaluations)', 'Curricular units 2nd sem (approved)',
'Curricular units 2nd sem (grade)', 'Curricular units 2nd sem (without evaluations)',
'Unemployment rate', 'Inflation rate', 'GDP'
]
}
with open('preprocessing_info.pkl', 'wb') as f:
pickle.dump(preprocessing_info, f)
print("Model and preprocessing info saved successfully!")
print("Files created:")
print("- random_forest_model.pkl")
print("- feature_names.pkl")
print("- preprocessing_info.pkl")
return rf_classifier, preprocessing_info
if __name__ == "__main__":
train_and_save_model()