/
NonerCo
/
StudentSystem
Обзор
Документация
Войти
/
NonerCo
/
StudentSystem
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/models.py
163 строки
6 KB
NonerCo
create src/models.py
13 янв 2026, 20:54
13 янв 2026, 20:54
c7f46df
Код
Авторство
О чём код?
""" Модели машинного обучения для прогнозирования успеваемости. """ import numpy as np from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, f1_score, classification_report from sklearn.neighbors import KNeighborsClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline import joblib class PerformancePredictor: """Класс для прогнозирования успеваемости студентов.""" def __init__(self, model_type='knn', params=None): """ Инициализация модели. Args: model_type: 'knn', 'random_forest', или 'logistic' params: Параметры модели """ self.model_type = model_type self.params = params or {} self.model = self._create_model() self.scaler = StandardScaler() def _create_model(self): """Создание модели в зависимости от типа.""" if self.model_type == 'knn': return KNeighborsClassifier( n_neighbors=self.params.get('n_neighbors', 5), weights=self.params.get('weights', 'distance') ) elif self.model_type == 'random_forest': return RandomForestClassifier( n_estimators=self.params.get('n_estimators', 100), max_depth=self.params.get('max_depth', None), random_state=42 ) else: raise ValueError(f"Unknown model type: {self.model_type}") def train_and_evaluate(self, X, y, test_size=0.2, random_state=42): """ Обучение и оценка модели. Args: X: Признаки y: Целевая переменная test_size: Размер тестовой выборки random_state: Seed для воспроизводимости Returns: dict: Метрики модели """ # Разделение данных X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=test_size, random_state=random_state, stratify=y # Для сбалансированности классов ) # Масштабирование X_train_scaled = self.scaler.fit_transform(X_train) X_test_scaled = self.scaler.transform(X_test) # Обучение self.model.fit(X_train_scaled, y_train) # Предсказания y_pred = self.model.predict(X_test_scaled) # Метрики metrics = { 'accuracy': accuracy_score(y_test, y_pred), 'f1_score': f1_score(y_test, y_pred, average='weighted'), 'classification_report': classification_report(y_test, y_pred, output_dict=True), 'model_type': self.model_type, 'test_size': len(X_test), 'train_size': len(X_train) } return metrics def predict_student(self, student_features): """ Прогнозирование успеваемости для одного студента. Args: student_features: Признаки студента Returns: tuple: (predicted_class, probability) """ features_scaled = self.scaler.transform([student_features]) prediction = self.model.predict(features_scaled)[0] if hasattr(self.model, 'predict_proba'): probability = self.model.predict_proba(features_scaled)[0] else: probability = None return prediction, probability def save_model(self, path='models/performance_predictor.pkl'): """Сохранение модели.""" joblib.dump({ 'model': self.model, 'scaler': self.scaler, 'model_type': self.model_type }, path) @classmethod def load_model(cls, path='models/performance_predictor.pkl'): """Загрузка модели.""" data = joblib.load(path) predictor = cls(model_type=data['model_type']) predictor.model = data['model'] predictor.scaler = data['scaler'] return predictor class CustomKNN: """Кастомная реализация k-NN для образовательных целей.""" def __init__(self, k=5, distance_metric='euclidean'): self.k = k self.distance_metric = distance_metric self.X_train = None self.y_train = None def fit(self, X, y): """Обучение k-NN (просто запоминание данных).""" self.X_train = X self.y_train = y return self def predict(self, X): """Предсказание для набора точек.""" predictions = [] for x in X: predictions.append(self._predict_single(x)) return np.array(predictions) def _predict_single(self, x): """Предсказание для одной точки.""" # Вычисление расстояний if self.distance_metric == 'euclidean': distances = np.sqrt(np.sum((self.X_train - x) ** 2, axis=1)) elif self.distance_metric == 'manhattan': distances = np.sum(np.abs(self.X_train - x), axis=1) else: raise ValueError(f"Unknown distance metric: {self.distance_metric}") # Получение k ближайших соседей nearest_indices = np.argsort(distances)[:self.k] nearest_labels = self.y_train[nearest_indices] # Голосование (для классификации) unique, counts = np.unique(nearest_labels, return_counts=True) return unique[np.argmax(counts)]