msgasu commited on
Commit
fa6e48f
·
verified ·
1 Parent(s): 34fb376

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +221 -158
app.py CHANGED
@@ -1,206 +1,269 @@
1
- import gradio as gr
2
  import joblib
3
  import pandas as pd
4
  import numpy as np
 
 
5
 
6
  # Load your trained model
7
  model = joblib.load('trained_model.joblib')
8
 
9
- # Define the four fixed electives
10
- FIXED_ELECTIVES = ["Elective Maths", "Biology", "Chemistry", "Physics"]
 
 
 
11
 
12
- # Define grade to numeric conversion
13
  def grade_to_numeric(grade):
14
  if pd.isna(grade) or grade == "":
15
  return np.nan
 
16
  grade_map = {
17
  "A1": 1, "B2": 2, "B3": 3, "C4": 4, "C5": 5, "C6": 6,
18
  "D7": 7, "E8": 8, "F9": 9
19
  }
20
  return grade_map.get(grade, np.nan)
21
 
22
- def create_student_data(desired_career, aggregate, english, core_maths, science,
23
- social_studies, interests, strengths, elective_grades):
24
  """
25
- Creates a complete student data record with:
26
- - The four fixed electives
27
- - Properly formatted grades
28
- - Processed interests and strengths
29
  """
30
- # Start with core academic data
31
- student_data = {
32
- "StudentID": "STU_GRADIO",
33
- "Desired_Career": desired_career,
34
- "Aggregate": aggregate,
35
- "English": english,
36
- "Core Maths": core_maths,
37
- "Science": science,
38
- "Social Studies": social_studies,
39
- "Interests": interests,
40
- "Strengths": strengths,
41
- "Electives": ", ".join(FIXED_ELECTIVES) # Fixed electives list
42
- }
43
-
44
- # Add all four elective grades
45
- for elective in FIXED_ELECTIVES:
46
- student_data[elective] = elective_grades.get(elective, "")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
- # Convert to DataFrame
49
- df = pd.DataFrame([student_data])
50
 
51
- # Convert all grades to numerical
52
- grade_cols = ['English', 'Core Maths', 'Science', 'Social Studies'] + FIXED_ELECTIVES
53
- for col in grade_cols:
54
- df[col] = df[col].apply(grade_to_numeric)
55
 
56
- # Process interests and strengths into binary features
57
- for interest in [i.strip() for i in interests.split(',')]:
58
- df[f"interest_{interest}"] = 1
59
 
60
- for strength in [s.strip() for s in strengths.split(',')]:
61
- df[f"strength_{strength}"] = 1
 
 
62
 
63
- # Fill missing binary features with 0
64
- for col in df.columns:
65
- if col.startswith(('interest_', 'strength_')):
66
- df[col] = df[col].fillna(0)
67
 
68
- return df
 
 
 
 
 
 
 
 
69
 
70
- def get_recommendations(student_df):
71
- """Get course recommendations from the model"""
72
- try:
73
- probabilities = model.predict_proba(student_df)[0]
74
- classes = model.classes_
75
- top5_idx = np.argsort(probabilities)[::-1][:5]
76
- return [(classes[i], float(probabilities[i])) for i in top5_idx]
77
- except Exception as e:
78
- return [(f"Error: {str(e)}", 0.0)]
79
-
80
- def explain_recommendation(student_df, top_course):
81
- """Generate explanation for the top recommended course"""
82
- explanation = f"## Recommended Course: {top_course[0]}\n\n"
83
- explanation += "### Basis for Recommendation:\n"
84
-
85
  # Career alignment
86
- explanation += f"- Career Interest: {student_df['Desired_Career'].iloc[0]}\n"
87
-
88
  # Academic strengths
89
- strong_subjects = []
90
- for subject in ['Core Maths', 'English', 'Science'] + FIXED_ELECTIVES:
91
- if subject in student_df.columns and student_df[subject].iloc[0] <= 3: # Good grades (A1-B3)
92
- strong_subjects.append(subject)
93
- if strong_subjects:
94
- explanation += f"- Strong Performance in: {', '.join(strong_subjects)}\n"
95
-
96
- # Interests and strengths
97
- explanation += f"- Key Interests: {student_df['Interests'].iloc[0]}\n"
98
- explanation += f"- Core Strengths: {student_df['Strengths'].iloc[0]}\n"
99
-
100
- # Aggregate score
101
- agg = student_df['Aggregate'].iloc[0]
102
- if agg < 10:
103
- explanation += f"- Exceptional Academic Performance (Aggregate: {agg})\n"
104
- elif agg < 15:
105
- explanation += f"- Strong Academic Performance (Aggregate: {agg})\n"
106
- else:
107
- explanation += f"- Good Academic Foundation (Aggregate: {agg})\n"
108
-
109
  return explanation
110
 
111
- def predict_and_explain(desired_career, aggregate, english, core_maths, science,
112
- social_studies, interests, strengths,
113
- elective_maths, chemistry, physics, biology):
114
- # Prepare elective grades dictionary
115
- elective_grades = {
 
 
 
 
 
 
 
 
 
 
116
  "Elective Maths": elective_maths,
117
- "Chemistry": chemistry,
118
  "Physics": physics,
119
- "Biology": biology
 
120
  }
121
 
122
- # Create complete student data
123
- student_df = create_student_data(
124
- desired_career=desired_career,
125
- aggregate=aggregate,
126
- english=english,
127
- core_maths=core_maths,
128
- science=science,
129
- social_studies=social_studies,
130
- interests=interests,
131
- strengths=strengths,
132
- elective_grades=elective_grades
133
- )
134
-
135
  # Get recommendations
136
- recommendations = get_recommendations(student_df)
137
 
138
- # Prepare output
139
- output = "## Top 5 Course Recommendations\n\n"
140
- for course, prob in recommendations:
141
- output += f"- {course} ({prob*100:.1f}% match)\n"
 
 
 
 
142
 
143
- # Add explanation for top recommendation if available
144
- if recommendations and recommendations[0][1] > 0:
145
- output += "\n" + explain_recommendation(student_df, recommendations[0])
146
 
147
- return output
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
- # Gradio Interface
150
- with gr.Blocks(title="Career Advisor") as interface:
151
- gr.Markdown("# University Course Recommendation System")
 
152
 
153
  with gr.Row():
154
- with gr.Column():
 
155
  desired_career = gr.Dropdown(
156
- ["Medicine", "Engineering", "Computer Science", "Business",
157
- "Law", "Agriculture", "Journalism", "Education"],
158
- label="Desired Career"
159
  )
160
- aggregate = gr.Number(label="Aggregate Score", minimum=6, maximum=36)
161
- interests = gr.Textbox(label="Your Interests (comma separated)")
162
- strengths = gr.Textbox(label="Your Strengths (comma separated)")
163
 
164
- with gr.Column():
165
- english = gr.Dropdown(["A1", "B2", "B3", "C4", "C5", "C6", "D7", "E8", "F9"], label="English")
166
- core_maths = gr.Dropdown(["A1", "B2", "B3", "C4", "C5", "C6", "D7", "E8", "F9"], label="Core Maths")
167
- science = gr.Dropdown(["A1", "B2", "B3", "C4", "C5", "C6", "D7", "E8", "F9"], label="Science")
168
- social_studies = gr.Dropdown(["A1", "B2", "B3", "C4", "C5", "C6", "D7", "E8", "F9"], label="Social Studies")
169
-
170
- # Electives section with the four fixed options
171
- gr.Markdown("## Elective Subjects")
172
- with gr.Row():
173
- elective_maths = gr.Dropdown(["A1", "B2", "B3", "C4", "C5", "C6", "D7", "E8", "F9", ""], label="Elective Maths")
174
- chemistry = gr.Dropdown(["A1", "B2", "B3", "C4", "C5", "C6", "D7", "E8", "F9", ""], label="Chemistry")
175
- physics = gr.Dropdown(["A1", "B2", "B3", "C4", "C5", "C6", "D7", "E8", "F9", ""], label="Physics")
176
- biology = gr.Dropdown(["A1", "B2", "B3", "C4", "C5", "C6", "D7", "E8", "F9", ""], label="Biology")
177
-
178
- submit = gr.Button("Get Recommendations")
179
- output = gr.Markdown()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
- submit.click(
182
- fn=predict_and_explain,
183
- inputs=[
184
- desired_career, aggregate, english, core_maths, science,
185
- social_studies, interests, strengths,
186
- elective_maths, chemistry, physics, biology
187
- ],
188
  outputs=output
189
  )
190
-
191
- # Medical school example matching your Colab test case
192
- gr.Examples(
193
- examples=[[
194
- "Medicine", 6, "A1", "A1", "A1", "A1",
195
- "research, medicine, helping people",
196
- "analytical thinking, attention to detail",
197
- "A1", "A1", "A1", "A1" # Elective grades in order: Maths, Chem, Physics, Bio
198
- ]],
199
- inputs=[
200
- desired_career, aggregate, english, core_maths, science,
201
- social_studies, interests, strengths,
202
- elective_maths, chemistry, physics, biology
203
- ]
204
- )
205
 
206
- interface.launch()
 
 
 
 
1
  import joblib
2
  import pandas as pd
3
  import numpy as np
4
+ import gradio as gr
5
+ from sklearn.preprocessing import OneHotEncoder, StandardScaler
6
 
7
  # Load your trained model
8
  model = joblib.load('trained_model.joblib')
9
 
10
+ # Define all_traits dictionary (needed for preprocessing)
11
+ all_traits = {
12
+ 'Interests': set(['Reading', 'Dancing', 'Physics', 'Research', 'Cooking', 'Art', 'Playing Football', 'Creativity', 'Writing']),
13
+ 'Strengths': set(['Communication', 'Creativity', 'Logical Reasoning', 'Innovative Thinking', 'Teamwork', 'Hands-on Skills', 'Analytical Thinking'])
14
+ }
15
 
16
+ # Function to convert grades to numerical values
17
  def grade_to_numeric(grade):
18
  if pd.isna(grade) or grade == "":
19
  return np.nan
20
+
21
  grade_map = {
22
  "A1": 1, "B2": 2, "B3": 3, "C4": 4, "C5": 5, "C6": 6,
23
  "D7": 7, "E8": 8, "F9": 9
24
  }
25
  return grade_map.get(grade, np.nan)
26
 
27
+ # Function to extract interests and strengths into separate columns
28
+ def extract_traits(df, column_name, prefix, all_traits=None):
29
  """
30
+ Extracts traits from a column, creating binary columns for each trait.
 
 
 
31
  """
32
+ # Split the comma-separated values
33
+ trait_series = df[column_name].str.split(',', expand=True)
34
+
35
+ # Infer all_traits if not provided
36
+ if all_traits is None:
37
+ all_traits = set()
38
+ for col in trait_series.columns:
39
+ all_traits.update(trait_series[col].dropna().unique())
40
+
41
+ # Create binary columns for each trait
42
+ for trait in all_traits:
43
+ col_name = f"{prefix}_{trait.strip()}"
44
+ df[col_name] = df[column_name].str.contains(trait, case=False, na=False).astype(int)
45
+
46
+ return df
47
+
48
+ def preprocess_data(df, all_traits=None):
49
+ """
50
+ Preprocesses the student data.
51
+ """
52
+ # Create a copy to avoid modifying the original
53
+ processed_df = df.copy()
54
+
55
+ if all_traits is None:
56
+ all_traits = {
57
+ 'Interests': set(),
58
+ 'Strengths': set()
59
+ }
60
+ for _, row in processed_df.iterrows():
61
+ all_traits['Interests'].update(row['Interests'].split(',') if isinstance(row['Interests'], str) else [])
62
+ all_traits['Strengths'].update(row['Strengths'].split(',') if isinstance(row['Strengths'], str) else [])
63
+
64
+ processed_df = extract_traits(processed_df, "Interests", "interest", all_traits.get('Interests'))
65
+ processed_df = extract_traits(processed_df, "Strengths", "strength", all_traits.get('Strengths'))
66
+
67
+ return processed_df
68
+
69
+ # Create features and target variable
70
+ def prepare_model_data(processed_df):
71
+ # Identify categorical and numerical features
72
+ categorical_features = ["Desired_Career"]
73
+ numerical_features = ["Aggregate", "English", "Core Maths", "Science", "Social Studies",
74
+ "Physics", "Biology", "Elective Maths", "Chemistry"]
75
+
76
+ # Add the binary interest and strength columns
77
+ interest_strength_cols = [col for col in processed_df.columns if col.startswith('interest_') or col.startswith('strength_')]
78
+
79
+ # Convert grade columns to numerical values
80
+ for col in numerical_features:
81
+ if col in processed_df.columns: # Check if column exists
82
+ processed_df[col] = processed_df[col].apply(grade_to_numeric)
83
+
84
+ # Get features (using processed_df with numerical grades)
85
+ X = processed_df[categorical_features + numerical_features + interest_strength_cols]
86
+
87
+ return X
88
+
89
+ def get_course_recommendation(student_info):
90
+ """
91
+ Get course recommendations for a student based on their information.
92
+ """
93
+ # Convert student data to DataFrame
94
+ student_df = pd.DataFrame([student_info])
95
 
96
+ # Preprocess student data
97
+ processed_student = preprocess_data(student_df, all_traits)
98
 
99
+ # Extract features
100
+ student_features = prepare_model_data(processed_student)
 
 
101
 
102
+ # Make prediction
103
+ recommended_course = model.predict(student_features)[0]
104
+ probabilities = model.predict_proba(student_features)[0]
105
 
106
+ # Get top 3 recommendations with probabilities
107
+ class_indices = np.argsort(probabilities)[::-1][:3]
108
+ classes = model.classes_
109
+ top_recommendations = [(classes[idx], f"{probabilities[idx]:.2f}") for idx in class_indices]
110
 
111
+ # Format the output
112
+ result = "Top Course Recommendations:\n\n"
113
+ for i, (course, prob) in enumerate(top_recommendations, 1):
114
+ result += f"{i}. {course} (Confidence: {prob})\n\n"
115
 
116
+ return result
117
+
118
+ def explain_recommendation(student_info, top_recommendation):
119
+ """
120
+ Provide an explanation for why a particular course was recommended.
121
+ """
122
+ course = top_recommendation[0]
123
+
124
+ explanation = f"The course '{course}' was recommended based on:\n"
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  # Career alignment
127
+ explanation += f"- Your career interest in {student_info['Desired_Career']}\n"
128
+
129
  # Academic strengths
130
+ subjects = []
131
+ if grade_to_numeric(student_info.get('Core Maths', '')) <= 3:
132
+ subjects.append("Mathematics")
133
+ if grade_to_numeric(student_info.get('English', '')) <= 3:
134
+ subjects.append("English")
135
+ if grade_to_numeric(student_info.get('Science', '')) <= 3:
136
+ subjects.append("Science")
137
+ if subjects:
138
+ explanation += f"- Your strong performance in {', '.join(subjects)}\n"
139
+
140
+ # Interests and strengths match
141
+ explanation += f"- Your interests in {student_info['Interests']}\n"
142
+ explanation += f"- Your strengths in {student_info['Strengths']}\n"
143
+
144
+ # Aggregate score context
145
+ if student_info['Aggregate'] < 15:
146
+ explanation += "- Your excellent aggregate score\n"
147
+ elif student_info['Aggregate'] < 20:
148
+ explanation += "- Your good aggregate score\n"
149
+
150
  return explanation
151
 
152
+ def predict_career(desired_career, aggregate, interests, strengths, english, core_maths, science, social_studies,
153
+ elective_maths, physics, biology, chemistry):
154
+
155
+ # Create student data dictionary
156
+ student_info = {
157
+ "StudentID": "STU_TEMP",
158
+ "Desired_Career": desired_career,
159
+ "Recommended_Course": "", # Will be predicted
160
+ "Aggregate": aggregate,
161
+ "Interests": interests,
162
+ "Strengths": strengths,
163
+ "English": english,
164
+ "Core Maths": core_maths,
165
+ "Science": science,
166
+ "Social Studies": social_studies,
167
  "Elective Maths": elective_maths,
 
168
  "Physics": physics,
169
+ "Biology": biology,
170
+ "Chemistry": chemistry
171
  }
172
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  # Get recommendations
174
+ recommendations = get_course_recommendation(student_info)
175
 
176
+ # Get top recommendation for explanation
177
+ student_df = pd.DataFrame([student_info])
178
+ processed_student = preprocess_data(student_df, all_traits)
179
+ student_features = prepare_model_data(processed_student)
180
+ probabilities = model.predict_proba(student_features)[0]
181
+ class_indices = np.argsort(probabilities)[::-1][:1]
182
+ classes = model.classes_
183
+ top_recommendation = [(classes[idx], probabilities[idx]) for idx in class_indices][0]
184
 
185
+ # Get explanation
186
+ explanation = explain_recommendation(student_info, top_recommendation)
 
187
 
188
+ return recommendations + "\n" + explanation
189
+
190
+ # Define grade options with descriptions
191
+ grade_options = [
192
+ ("", "Select Grade"),
193
+ ("A1", "A1 - Excellent (1)"),
194
+ ("B2", "B2 - Very Good (2)"),
195
+ ("B3", "B3 - Good (3)"),
196
+ ("C4", "C4 - Credit (4)"),
197
+ ("C5", "C5 - Credit (5)"),
198
+ ("C6", "C6 - Credit (6)"),
199
+ ("D7", "D7 - Pass (7)"),
200
+ ("E8", "E8 - Pass (8)"),
201
+ ("F9", "F9 - Fail (9)")
202
+ ]
203
 
204
+ # Create Gradio interface
205
+ with gr.Blocks(title="Career Course Recommendation System") as demo:
206
+ gr.Markdown("# Career Course Recommendation System")
207
+ gr.Markdown("Enter student information to get course recommendations")
208
 
209
  with gr.Row():
210
+ with gr.Column(scale=2):
211
+ gr.Markdown("### Student Information")
212
  desired_career = gr.Dropdown(
213
+ choices=["Medicine", "Pharmacy", "Law", "Computer Science", "Engineering", "Business", "Nursing", "Agriculture", "Journalism", "Education"],
214
+ label="Desired Career",
215
+ info="Select your desired career path"
216
  )
217
+ aggregate = gr.Slider(minimum=6, maximum=37, value=15, step=1, label="Aggregate Score", info="Lower is better (6 is best, 37 is worst)")
218
+ interests = gr.Textbox(label="Interests (comma separated)", placeholder="Reading,Dancing,Physics", info="List your interests separated by commas")
219
+ strengths = gr.Textbox(label="Strengths (comma separated)", placeholder="Communication,Creativity", info="List your strengths separated by commas")
220
 
221
+ gr.Markdown("### Core Subjects (Required)")
222
+ with gr.Row():
223
+ with gr.Column(scale=1):
224
+ english = gr.Dropdown(choices=grade_options, label="English", info="Grade in English")
225
+ core_maths = gr.Dropdown(choices=grade_options, label="Core Maths", info="Grade in Core Mathematics")
226
+
227
+ with gr.Column(scale=1):
228
+ science = gr.Dropdown(choices=grade_options, label="Science", info="Grade in Integrated Science")
229
+ social_studies = gr.Dropdown(choices=grade_options, label="Social Studies", info="Grade in Social Studies")
230
+
231
+ gr.Markdown("### Elective Subjects")
232
+ with gr.Row():
233
+ with gr.Column(scale=1):
234
+ elective_maths = gr.Dropdown(choices=grade_options, label="Elective Maths", info="Grade in Elective Mathematics")
235
+ physics = gr.Dropdown(choices=grade_options, label="Physics", info="Grade in Physics")
236
+
237
+ with gr.Column(scale=1):
238
+ chemistry = gr.Dropdown(choices=grade_options, label="Chemistry", info="Grade in Chemistry")
239
+ biology = gr.Dropdown(choices=grade_options, label="Biology", info="Grade in Biology")
240
+
241
+ with gr.Column(scale=1):
242
+ gr.Markdown("### Grade Scale Reference")
243
+ gr.Markdown("""
244
+ - A1: Excellent (1 point)
245
+ - B2: Very Good (2 points)
246
+ - B3: Good (3 points)
247
+ - C4: Credit (4 points)
248
+ - C5: Credit (5 points)
249
+ - C6: Credit (6 points)
250
+ - D7: Pass (7 points)
251
+ - E8: Pass (8 points)
252
+ - F9: Fail (9 points)
253
+
254
+ *Lower points are better. Aggregate is the sum of your best subjects.*
255
+ """)
256
+
257
+ submit_btn = gr.Button("Get Recommendations", variant="primary", size="lg")
258
+ output = gr.Textbox(label="Recommendations", lines=20)
259
 
260
+ submit_btn.click(
261
+ fn=predict_career,
262
+ inputs=[desired_career, aggregate, interests, strengths, english, core_maths, science, social_studies,
263
+ elective_maths, physics, biology, chemistry],
 
 
 
264
  outputs=output
265
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
+ # Launch the app
268
+ if __name__ == "__main__":
269
+ demo.launch()