| import numpy as np |
| from datascience import * |
| import gradio as gr |
|
|
| SPD = Table.read_table('Student_Performance_Data.csv') |
|
|
| def study_effectiveness(study_time, absences, parental_support, tutoring): |
| return (study_time * 1.5) + (parental_support * 2) + (tutoring * 3) - (absences * 0.7) |
|
|
| effectiveness_scores = SPD.apply( |
| study_effectiveness, |
| 'StudyTimeWeekly', |
| 'Absences', |
| 'ParentalSupport', |
| 'Tutoring' |
| ) |
|
|
| SPD = SPD.with_column('StudyEffectiveness', effectiveness_scores) |
|
|
| def grade_to_gpa(grade): |
| if grade == 0: |
| return 4.0 |
| elif grade == 1: |
| return 3.0 |
| elif grade == 2: |
| return 2.0 |
| elif grade == 3: |
| return 1.0 |
| else: |
| return 0.0 |
|
|
| gpas = SPD.apply(grade_to_gpa, 'GradeClass') |
| SPD = SPD.with_column('GPA', gpas) |
|
|
| effectiveness_array = np.array(SPD.column('StudyEffectiveness')) |
| gpa_array = np.array(SPD.column('GPA')) |
|
|
| slope = ( |
| np.sum( |
| (effectiveness_array - np.mean(effectiveness_array)) * |
| (gpa_array - np.mean(gpa_array)) |
| ) |
| / |
| np.sum( |
| (effectiveness_array - np.mean(effectiveness_array)) ** 2 |
| ) |
| ) |
|
|
| intercept = np.mean(gpa_array) - (slope * np.mean(effectiveness_array)) |
|
|
| def linear_regression_gpa(effectiveness): |
| gpa = intercept + (slope * effectiveness) |
| if gpa < 0: |
| gpa = 0 |
| if gpa > 4: |
| gpa = 4 |
| return round(gpa, 2) |
|
|
| def predict_tree_gpa( |
| study_time, |
| absences, |
| parental_support, |
| tutoring, |
| extracurricular, |
| sports, |
| music, |
| volunteering, |
| effectiveness |
| ): |
| if effectiveness >= 18: |
| gpa = 3.6 + (study_time * 0.02) - (absences * 0.01) |
| elif effectiveness >= 14: |
| if absences <= 18: |
| gpa = 2.8 + (study_time * 0.03) - (absences * 0.015) |
| else: |
| gpa = 1.7 - (absences * 0.02) |
| elif effectiveness >= 10: |
| if study_time >= 10 and absences <= 12: |
| gpa = 2.4 + (study_time * 0.03) |
| elif tutoring == 1 and parental_support >= 3: |
| gpa = 2.2 + (parental_support * 0.08) |
| else: |
| gpa = 1.5 - (absences * 0.02) |
| elif effectiveness >= 6: |
| if study_time >= 12 and absences < 8: |
| gpa = 2.1 + (study_time * 0.025) |
| elif extracurricular == 1 or sports == 1 or music == 1 or volunteering == 1: |
| if absences < 12 and parental_support >= 2: |
| gpa = 2.0 + (parental_support * 0.05) |
| else: |
| gpa = 1.3 |
| else: |
| gpa = 1.0 |
| else: |
| gpa = 0.6 |
|
|
| if gpa < 0: |
| gpa = 0 |
| if gpa > 4: |
| gpa = 4 |
| return round(gpa, 2) |
|
|
| data = SPD.select( |
| 'Age', |
| 'Gender', |
| 'Ethnicity', |
| 'ParentalEducation', |
| 'StudyTimeWeekly', |
| 'Absences', |
| 'Tutoring', |
| 'ParentalSupport', |
| 'Extracurricular', |
| 'Sports', |
| 'Music', |
| 'Volunteering', |
| 'StudyEffectiveness', |
| 'GPA' |
| ) |
|
|
| np.random.seed(1) |
| shuffled = data.sample(with_replacement=False) |
| size = int(data.num_rows * 0.8) |
| train = shuffled.take(np.arange(size)) |
|
|
| def distance(r1, r2): |
| total = 0 |
| total += (r1.item('Age') - r2.item('Age'))**2 |
| total += (r1.item('Gender') - r2.item('Gender'))**2 |
| total += (r1.item('Ethnicity') - r2.item('Ethnicity'))**2 |
| total += (r1.item('ParentalEducation') - r2.item('ParentalEducation'))**2 |
| total += (r1.item('StudyTimeWeekly') - r2.item('StudyTimeWeekly'))**2 |
| total += (r1.item('Absences') - r2.item('Absences'))**2 |
| total += (r1.item('Tutoring') - r2.item('Tutoring'))**2 |
| total += (r1.item('ParentalSupport') - r2.item('ParentalSupport'))**2 |
| total += (r1.item('Extracurricular') - r2.item('Extracurricular'))**2 |
| total += (r1.item('Sports') - r2.item('Sports'))**2 |
| total += (r1.item('Music') - r2.item('Music'))**2 |
| total += (r1.item('Volunteering') - r2.item('Volunteering'))**2 |
| total += (r1.item('StudyEffectiveness') - r2.item('StudyEffectiveness'))**2 |
| return np.sqrt(total) |
|
|
| def knn_neighbors(test_row, k): |
| dists = make_array() |
| for i in np.arange(train.num_rows): |
| row = train.row(i) |
| d = distance(test_row, row) |
| dists = np.append(dists, d) |
| temp = train.with_column('Distance', dists) |
| nearest = temp.sort('Distance').take(np.arange(k)) |
| return nearest |
|
|
| def knn_gpa(test_row, k): |
| nearest = knn_neighbors(test_row, k) |
| gpa = np.mean(nearest.column('GPA')) |
| if gpa < 0: |
| gpa = 0 |
| if gpa > 4: |
| gpa = 4 |
| return round(gpa, 2) |
|
|
| k = 5 |
|
|
| def predict_models( |
| outside_study_time, |
| in_class_learning_time, |
| attentiveness, |
| absences, |
| tutoring, |
| parental_support, |
| extracurricular, |
| sports, |
| music, |
| volunteering |
| ): |
| attention_multiplier = attentiveness / 10 |
| study_time = outside_study_time + (in_class_learning_time * attention_multiplier) |
|
|
| study_effect = ( |
| (study_time * 1.5) |
| + (parental_support * 2) |
| + (tutoring * 3) |
| - (absences * 0.7) |
| ) |
|
|
| tree_gpa = predict_tree_gpa( |
| study_time, |
| absences, |
| parental_support, |
| tutoring, |
| extracurricular, |
| sports, |
| music, |
| volunteering, |
| study_effect |
| ) |
|
|
| linear_gpa = linear_regression_gpa(study_effect) |
|
|
| test_row = Table().with_columns( |
| 'Age', [17], |
| 'Gender', [0], |
| 'Ethnicity', [0], |
| 'ParentalEducation', [2], |
| 'StudyTimeWeekly', [study_time], |
| 'Absences', [absences], |
| 'Tutoring', [int(tutoring)], |
| 'ParentalSupport', [parental_support], |
| 'Extracurricular', [int(extracurricular)], |
| 'Sports', [int(sports)], |
| 'Music', [int(music)], |
| 'Volunteering', [int(volunteering)], |
| 'StudyEffectiveness', [study_effect], |
| 'GPA', [0] |
| ).row(0) |
|
|
| knn_prediction = knn_gpa(test_row, k) |
|
|
| final_score = (tree_gpa + linear_gpa + knn_prediction) / 3 |
|
|
| tree_label = "PASS" if tree_gpa >= 2.0 else "FAIL" |
| linear_label = "PASS" if linear_gpa >= 2.0 else "FAIL" |
| knn_label = "PASS" if knn_prediction >= 2.0 else "FAIL" |
| final_label = "PASS" if final_score >= 2.0 else "FAIL" |
|
|
| final_output = f""" |
| <div style="text-align:center; font-size:34px; font-weight:800; margin-top:10px;"> |
| {final_label} |
| </div> |
| <div style="text-align:center; font-size:18px; margin-top:10px;"> |
| |
| </div> |
| """ |
|
|
| return tree_label, linear_label, knn_label, final_output |
|
|
| theme = gr.themes.Soft( |
| primary_hue="blue", |
| secondary_hue="indigo", |
| neutral_hue="slate", |
| radius_size="lg", |
| text_size="lg" |
| ) |
|
|
| with gr.Blocks(theme=theme, fill_height=True) as app: |
|
|
| gr.Markdown(""" |
| # Student Performance Predictor |
| ### Individual model results + final pass/fail prediction |
| """) |
|
|
| with gr.Row(equal_height=True): |
|
|
| with gr.Column(scale=1): |
|
|
| with gr.Group(): |
|
|
| outside_study_time = gr.Slider(0, 20, value=8, label="Study Time Outside Class Weekly") |
| in_class_learning_time = gr.Slider(0, 25, value=15, label="Learning Time In Class Weekly") |
| attentiveness = gr.Slider(1, 10, value=5, step=1, label="Attentiveness In Class") |
| absences = gr.Slider(0, 30, value=5, label="Absences") |
| parental_support = gr.Slider(0, 4, value=2, step=1, label="Parental Support") |
|
|
| tutoring = gr.Checkbox(label="Tutoring") |
| extracurricular = gr.Checkbox(label="Extracurricular Activities") |
| sports = gr.Checkbox(label="Sports") |
| music = gr.Checkbox(label="Music") |
| volunteering = gr.Checkbox(label="Volunteering") |
|
|
| btn = gr.Button("Predict Performance", variant="primary", size="lg") |
|
|
| with gr.Column(scale=1): |
|
|
| tree_output = gr.Textbox(label="Decision Tree", interactive=False) |
| linear_output = gr.Textbox(label="Linear Regression", interactive=False) |
| knn_output = gr.Textbox(label="KNN", interactive=False) |
|
|
| final_output = gr.HTML(label="Final Result") |
|
|
| btn.click( |
| predict_models, |
| inputs=[ |
| outside_study_time, |
| in_class_learning_time, |
| attentiveness, |
| absences, |
| tutoring, |
| parental_support, |
| extracurricular, |
| sports, |
| music, |
| volunteering |
| ], |
| outputs=[ |
| tree_output, |
| linear_output, |
| knn_output, |
| final_output |
| ] |
| ) |
|
|
| app.launch() |