markobinario commited on
Commit
8126956
·
verified ·
1 Parent(s): a4943e6

Delete database_recommender.py

Browse files
Files changed (1) hide show
  1. database_recommender.py +0 -293
database_recommender.py DELETED
@@ -1,293 +0,0 @@
1
- import pandas as pd
2
- import numpy as np
3
- from sklearn.neighbors import KNeighborsClassifier
4
- from sklearn.preprocessing import LabelEncoder, StandardScaler
5
- import joblib
6
- import json
7
-
8
- class CourseRecommender:
9
- def __init__(self):
10
- self.model = None
11
- self.label_encoders = {}
12
- self.scaler = StandardScaler()
13
- self.courses = self.get_courses()
14
- self.training_data = self.get_training_data()
15
- self.train_model()
16
-
17
- def get_courses(self):
18
- """Get static course data"""
19
- return {
20
- 'BSCS': 'Bachelor of Science in Computer Science',
21
- 'BSIT': 'Bachelor of Science in Information Technology',
22
- 'BSBA': 'Bachelor of Science in Business Administration',
23
- 'BSED': 'Bachelor of Science in Education',
24
- 'BSN': 'Bachelor of Science in Nursing',
25
- 'BSArch': 'Bachelor of Science in Architecture',
26
- 'BSIE': 'Bachelor of Science in Industrial Engineering',
27
- 'BSHM': 'Bachelor of Science in Hospitality Management',
28
- 'BSA': 'Bachelor of Science in Accountancy',
29
- 'BSPsych': 'Bachelor of Science in Psychology',
30
- 'BSAgri': 'Bachelor of Science in Agriculture'
31
- }
32
-
33
- def save_student_data(self, stanine, gwa, strand, course, rating, hobbies=None):
34
- """Save student feedback to in-memory storage (for demonstration purposes)"""
35
- try:
36
- # In a real implementation, you could save this to a file or external storage
37
- print(f"Student feedback saved: Stanine={stanine}, GWA={gwa}, Strand={strand}, Course={course}, Rating={rating}, Hobbies={hobbies}")
38
- return True
39
- except Exception as e:
40
- print(f"Error saving student feedback: {e}")
41
- return False
42
-
43
- def get_training_data(self):
44
- """Get static training data for demonstration purposes"""
45
- # Sample training data to demonstrate the recommender system
46
- training_data = [
47
- # STEM students
48
- (8, 95, 'STEM', 'BSCS', 5, 'programming, gaming, technology'),
49
- (7, 90, 'STEM', 'BSIT', 4, 'computers, software, coding'),
50
- (9, 98, 'STEM', 'BSCS', 5, 'programming, algorithms, math'),
51
- (6, 85, 'STEM', 'BSIT', 3, 'technology, computers'),
52
- (8, 92, 'STEM', 'BSArch', 4, 'design, drawing, creativity'),
53
- (7, 88, 'STEM', 'BSIE', 4, 'engineering, problem solving'),
54
-
55
- # ABM students
56
- (8, 90, 'ABM', 'BSBA', 5, 'business, management, leadership'),
57
- (7, 85, 'ABM', 'BSA', 4, 'accounting, numbers, finance'),
58
- (6, 82, 'ABM', 'BSBA', 3, 'business, marketing'),
59
- (9, 95, 'ABM', 'BSA', 5, 'accounting, finance, analysis'),
60
-
61
- # HUMSS students
62
- (8, 88, 'HUMSS', 'BSED', 5, 'teaching, helping, education'),
63
- (7, 85, 'HUMSS', 'BSPsych', 4, 'psychology, helping, people'),
64
- (6, 80, 'HUMSS', 'BSED', 3, 'teaching, children'),
65
- (9, 92, 'HUMSS', 'BSPsych', 5, 'psychology, counseling, people'),
66
-
67
- # General interests
68
- (7, 87, 'STEM', 'BSN', 4, 'helping, healthcare, caring'),
69
- (8, 89, 'ABM', 'BSHM', 4, 'hospitality, service, management'),
70
- (6, 83, 'HUMSS', 'BSAgri', 3, 'agriculture, environment, nature'),
71
- ]
72
-
73
- return pd.DataFrame(training_data, columns=['stanine', 'gwa', 'strand', 'course', 'rating', 'hobbies'])
74
-
75
- def train_model(self):
76
- """Train the recommendation model using the training data"""
77
- try:
78
- training_data = self.get_training_data()
79
-
80
- if training_data.empty:
81
- print("No training data available - using default recommendations")
82
- return
83
-
84
- # Prepare features (hobbies required)
85
- feature_columns = ['stanine', 'gwa', 'strand', 'hobbies']
86
-
87
- # Create feature matrix
88
- X = training_data[feature_columns].copy()
89
- y = training_data['course']
90
-
91
- # Handle categorical variables
92
- categorical_columns = ['strand', 'hobbies']
93
-
94
- # Refit encoders every training to incorporate new categories
95
- for col in categorical_columns:
96
- if col in X.columns:
97
- X[col] = X[col].fillna('unknown')
98
- self.label_encoders[col] = LabelEncoder()
99
- X[col] = self.label_encoders[col].fit_transform(X[col])
100
-
101
- # Scale numerical features
102
- numerical_columns = ['stanine', 'gwa']
103
- if not X[numerical_columns].empty:
104
- X[numerical_columns] = self.scaler.fit_transform(X[numerical_columns])
105
-
106
- # Train KNN model
107
- self.model = KNeighborsClassifier(n_neighbors=3, weights='distance')
108
- self.model.fit(X, y)
109
-
110
- print("✅ Model trained successfully (hobbies required and encoded)")
111
-
112
- except Exception as e:
113
- print(f"Error training model: {e}")
114
- self.model = None
115
-
116
- def get_default_recommendations(self, stanine, gwa, strand):
117
- """Provide default recommendations based on basic rules when no training data is available"""
118
- courses = self.courses
119
- recommendations = []
120
-
121
- # Basic rules for recommendations
122
- if strand == 'STEM':
123
- if stanine >= 8 and gwa >= 90:
124
- priority_courses = ['BSCS', 'BSIT']
125
- else:
126
- priority_courses = ['BSIT', 'BSCS']
127
- elif strand == 'ABM':
128
- priority_courses = ['BSBA']
129
- elif strand == 'HUMSS':
130
- priority_courses = ['BSED']
131
- else:
132
- priority_courses = list(courses.keys())
133
-
134
- # Add courses with default probabilities
135
- for i, course in enumerate(priority_courses[:2]): # Only take top 2
136
- if course in courses:
137
- recommendations.append({
138
- 'code': course,
139
- 'name': courses[course],
140
- 'probability': 1.0 - (i * 0.2) # Decreasing probability for each course
141
- })
142
-
143
- return recommendations
144
-
145
- def recommend_courses(self, stanine, gwa, strand, hobbies=None, top_n=5):
146
- """Recommend courses based on student profile (hobbies required)"""
147
- try:
148
- if self.model is None:
149
- return self.get_default_recommendations(stanine, gwa, strand)
150
-
151
- # Prepare input features
152
- input_data = pd.DataFrame([{
153
- 'stanine': stanine,
154
- 'gwa': gwa,
155
- 'strand': strand,
156
- 'hobbies': (hobbies or '').strip()
157
- }])
158
- # Validate hobbies
159
- if not input_data['hobbies'].iloc[0]:
160
- raise ValueError('hobbies is required for recommendations')
161
-
162
- # Encode categorical variables
163
- for col in ['strand', 'hobbies']:
164
- if col in input_data.columns and col in self.label_encoders:
165
- value = input_data[col].iloc[0]
166
- if value not in self.label_encoders[col].classes_:
167
- # Extend encoder classes to include unseen value at inference
168
- self.label_encoders[col].classes_ = np.append(self.label_encoders[col].classes_, value)
169
- input_data[col] = self.label_encoders[col].transform(input_data[col])
170
-
171
- # Scale numerical features
172
- numerical_columns = ['stanine', 'gwa']
173
- if not input_data[numerical_columns].empty:
174
- input_data[numerical_columns] = self.scaler.transform(input_data[numerical_columns])
175
-
176
- # Get predictions
177
- predictions = self.model.predict_proba(input_data)
178
- courses = self.model.classes_
179
-
180
- # Get top recommendations
181
- top_indices = np.argsort(predictions[0])[-top_n:][::-1]
182
- recommendations = []
183
-
184
- course_map = self.courses
185
- for idx in top_indices:
186
- code = courses[idx]
187
- confidence = predictions[0][idx]
188
- recommendations.append({
189
- 'code': code,
190
- 'name': course_map.get(code, code),
191
- 'rating': round(confidence * 100, 1)
192
- })
193
-
194
- return recommendations
195
-
196
- except Exception as e:
197
- print(f"Error recommending courses: {e}")
198
- return self.get_default_recommendations(stanine, gwa, strand)
199
-
200
- def _get_recommendation_reason(self, course, stanine, gwa, strand, hobbies, interests, personality_type, learning_style, career_goals):
201
- """Generate personalized reason for recommendation"""
202
- reasons = []
203
-
204
- # Academic performance reasons
205
- if stanine >= 8:
206
- reasons.append("Excellent academic performance")
207
- elif stanine >= 6:
208
- reasons.append("Good academic foundation")
209
-
210
- if gwa >= 85:
211
- reasons.append("High academic achievement")
212
- elif gwa >= 80:
213
- reasons.append("Strong academic record")
214
-
215
- # Strand alignment
216
- if strand == "STEM" and course in ["BSCS", "BSIT", "BSArch", "BSIE", "BSN"]:
217
- reasons.append("Perfect match with your STEM background")
218
- elif strand == "ABM" and course in ["BSBA", "BSA"]:
219
- reasons.append("Excellent alignment with your ABM strand")
220
- elif strand == "HUMSS" and course in ["BSED", "BSPsych"]:
221
- reasons.append("Great fit with your HUMSS background")
222
-
223
- # Hobbies and interests alignment
224
- if hobbies and any(hobby in hobbies.lower() for hobby in ["gaming", "programming", "technology", "computers"]):
225
- if course in ["BSCS", "BSIT"]:
226
- reasons.append("Matches your technology interests")
227
-
228
- if hobbies and any(hobby in hobbies.lower() for hobby in ["business", "leadership", "management"]):
229
- if course in ["BSBA", "BSA"]:
230
- reasons.append("Aligns with your business interests")
231
-
232
- if hobbies and any(hobby in hobbies.lower() for hobby in ["helping", "teaching", "caring"]):
233
- if course in ["BSED", "BSN", "BSPsych"]:
234
- reasons.append("Perfect for your helping nature")
235
-
236
- # Personality type alignment
237
- if personality_type == "introvert" and course in ["BSCS", "BSA", "BSArch"]:
238
- reasons.append("Suits your introverted personality")
239
- elif personality_type == "extrovert" and course in ["BSBA", "BSED", "BSHM"]:
240
- reasons.append("Great for your outgoing personality")
241
-
242
- # Learning style alignment
243
- if learning_style == "hands-on" and course in ["BSIT", "BSHM", "BSAgri"]:
244
- reasons.append("Matches your hands-on learning preference")
245
- elif learning_style == "visual" and course in ["BSArch", "BSCS"]:
246
- reasons.append("Perfect for your visual learning style")
247
-
248
- # Career goals alignment
249
- if career_goals and any(goal in career_goals.lower() for goal in ["developer", "programmer", "software"]):
250
- if course in ["BSCS", "BSIT"]:
251
- reasons.append("Direct path to your career goals")
252
-
253
- if career_goals and any(goal in career_goals.lower() for goal in ["business", "entrepreneur", "manager"]):
254
- if course in ["BSBA", "BSA"]:
255
- reasons.append("Direct path to your business goals")
256
-
257
- # Default reason if no specific matches
258
- if not reasons:
259
- reasons.append("Good academic and personal fit")
260
-
261
- return " • ".join(reasons[:3]) # Limit to top 3 reasons
262
-
263
- def save_model(self, model_path='course_recommender_model.joblib'):
264
- """Save the trained model"""
265
- if self.model is None:
266
- raise Exception("No model to save!")
267
-
268
- model_data = {
269
- 'model': self.model,
270
- 'scaler': self.scaler,
271
- 'label_encoders': self.label_encoders
272
- }
273
- joblib.dump(model_data, model_path)
274
-
275
- def load_model(self, model_path='course_recommender_model.joblib'):
276
- """Load a trained model"""
277
- model_data = joblib.load(model_path)
278
- self.model = model_data['model']
279
- self.scaler = model_data['scaler']
280
- self.label_encoders = model_data['label_encoders']
281
-
282
- # Example usage
283
- if __name__ == "__main__":
284
- recommender = CourseRecommender()
285
-
286
- # Example recommendation
287
- recommendations = recommender.recommend_courses(
288
- stanine=8,
289
- gwa=95,
290
- strand='STEM',
291
- hobbies='programming, gaming, technology'
292
- )
293
- print("Recommended courses:", json.dumps(recommendations, indent=2))