/
v1sik
/
data_analysis
Обзор
Документация
Войти
/
v1sik
/
data_analysis
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
main.py
374 строки
16 KB
v1sik
Обновлены main.py и student_dataset.csv
07 июн 2025, 17:52
07 июн 2025, 17:52
48148bf
Код
Авторство
О чём код?
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import skfuzzy as fuzz from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, mean_absolute_error, mean_squared_error from skfuzzy import control as ctrl from tqdm import tqdm import re # Настройки отображения pd.set_option('display.max_columns', None) sns.set(style="whitegrid") def analyze_data(): # 1. Загрузка данных file_path = "student_dataset.csv" # Замените на путь к своему файлу df = pd.read_csv(file_path) print("✅ Загружено строк:", len(df)) print(df.head()) # 2. Проверка пропусков print("\n🔍 Пропуски по столбцам:") print(df.isnull().sum()) # 3. Обработка аномалий numeric_cols = ["Math", "Physics", "History", "StudyHours", "Attendance"] for col in numeric_cols: df = df[df[col].between(0, 100 if col != "StudyHours" else 40)] print(f"\n📉 Осталось записей после фильтрации: {len(df)}") # 4. Обзорная статистика print("\n📊 Описательная статистика:") print(df[numeric_cols].describe()) # Корреляционная матрица print("\n📈 Корреляции:") print(df[numeric_cols].corr()) # 5. Визуализация распределений plt.figure(figsize=(16, 10)) for i, col in enumerate(numeric_cols): plt.subplot(2, 3, i+1) sns.histplot(df[col], kde=True, bins=30) plt.title(f"Распределение {col}") plt.tight_layout() plt.show() # 6. Boxplot plt.figure(figsize=(16, 10)) for i, col in enumerate(numeric_cols): plt.subplot(2, 3, i+1) sns.boxplot(x=df[col]) plt.title(f"Boxplot для {col}") plt.tight_layout() plt.show() # 7. Диаграммы рассеяния plt.figure(figsize=(12, 6)) sns.scatterplot(data=df, x="StudyHours", y="Math", hue="Interest") plt.title("Часы на учебу vs Оценка по математике") plt.show() plt.figure(figsize=(12, 6)) sns.scatterplot(data=df, x="Attendance", y="Physics", hue="FreeTime") plt.title("Посещаемость vs Оценка по физике") plt.show() pd.set_option('display.max_columns', None) sns.set(style="whitegrid") def recommend_for_student(): x_avg = np.linspace(40, 100, 100) x_attend = np.linspace(50, 100, 100) x_studyhours = np.linspace(0, 40, 100) x_perf = np.linspace(0, 100, 100) # Входные переменные avg_subject = ctrl.Antecedent(x_avg, 'avg_subject') attendance = ctrl.Antecedent(x_attend, 'attendance') studyhours = ctrl.Antecedent(x_studyhours, 'studyhours') # Выходная переменная predicted_performance = ctrl.Consequent(x_perf, 'predicted_performance') # Функции принадлежности avg_subject['низкий'] = fuzz.trimf(x_avg, [40, 45, 55]) avg_subject['средний'] = fuzz.trimf(x_avg, [52, 57, 65]) avg_subject['высокий'] = fuzz.trimf(x_avg, [63, 75, 100]) attendance['низкая'] = fuzz.trimf(x_attend, [50, 60, 70]) attendance['средняя'] = fuzz.trimf(x_attend, [68, 80, 90]) attendance['высокая'] = fuzz.trimf(x_attend, [88, 95, 100]) studyhours['мало'] = fuzz.trimf(x_studyhours, [0, 4, 12]) studyhours['средне'] = fuzz.trimf(x_studyhours, [10, 16, 22]) studyhours['много'] = fuzz.trimf(x_studyhours, [20, 30, 40]) predicted_performance['низкая'] = fuzz.trimf(x_perf, [0, 35, 55]) predicted_performance['средняя'] = fuzz.trimf(x_perf, [50, 60, 85]) predicted_performance['высокая'] = fuzz.trimf(x_perf, [85, 90, 100]) rule_descriptions = [ ("R1", ctrl.Rule(avg_subject['высокий'] & attendance['высокая'] & studyhours['много'], predicted_performance['высокая'])), ("R2", ctrl.Rule(avg_subject['высокий'] & (attendance['высокая'] | studyhours['много']), predicted_performance['высокая'])), ("R3", ctrl.Rule(avg_subject['высокий'] & studyhours['средне'], predicted_performance['высокая'])), ("R4", ctrl.Rule(avg_subject['средний'] & attendance['высокая'] & studyhours['много'], predicted_performance['средняя'])), ("R5", ctrl.Rule(avg_subject['средний'] & (attendance['высокая'] | studyhours['много']), predicted_performance['средняя'])), ("R6", ctrl.Rule(avg_subject['средний'] & (attendance['средняя'] | studyhours['средне']), predicted_performance['средняя'])), ("R7", ctrl.Rule(avg_subject['средний'] & studyhours['мало'], predicted_performance['средняя'])), ("R8", ctrl.Rule(avg_subject['низкий'], predicted_performance['низкая'])), ("R9", ctrl.Rule(attendance['низкая'], predicted_performance['низкая'])), ("R10", ctrl.Rule((avg_subject['низкий'] | attendance['низкая']) & studyhours['мало'], predicted_performance['низкая'])) ] rules = [r for _, r in rule_descriptions] prediction_ctrl = ctrl.ControlSystem(rules) predictor = ctrl.ControlSystemSimulation(prediction_ctrl) # 👉 Ввод значений студента — твой привычный способ input_values = { 'studyhours': 15, 'attendance': 78, 'avg_subject': 55 } predictor.input['studyhours'] = input_values['studyhours'] predictor.input['attendance'] = input_values['attendance'] predictor.input['avg_subject'] = input_values['avg_subject'] predictor.compute() result = predictor.output['predicted_performance'] print("Прогноз успеваемости:", result) def interpret_prediction(value): if value < 30: return "низкая успеваемость (рекомендуется поддержка и дополнительные занятия)" elif value < 70: return "средняя успеваемость (возможен рост при правильной поддержке)" else: return "высокая успеваемость (поддерживать и развивать)" print("📌 Интерпретация:", interpret_prediction(result)) # Вывод активных правил def fuzzy_degree(fset, value): return fuzz.interp_membership(fset.universe, fset.mf, value) print("\n📋 Активированные правила:") universes = { 'avg_subject': x_avg, 'attendance': x_attend, 'studyhours': x_studyhours } for desc, rule in rule_descriptions: vars_in_rule = rule.antecedent_terms # список Term degrees = [] for term in vars_in_rule: var_name = term.parent.label # имя переменной term_name = term.label # имя терма val = input_values[var_name] # значение для переменной mf = locals()[var_name][term_name].mf # функция принадлежности deg = fuzz.interp_membership(universes[var_name], mf, val) degrees.append(deg) strength = min(degrees) if degrees else 0 if strength > 0.05: print(f"✅ {desc} (сила активации: {strength:.2f})") def build_fuzzy_system(): x_avg = np.linspace(40, 100, 100) x_attend = np.linspace(50, 100, 100) x_studyhours = np.linspace(0, 40, 100) x_perf = np.linspace(0, 100, 100) # Входные переменные avg_subject = ctrl.Antecedent(x_avg, 'avg_subject') attendance = ctrl.Antecedent(x_attend, 'attendance') studyhours = ctrl.Antecedent(x_studyhours, 'studyhours') # Выходная переменная predicted_performance = ctrl.Consequent(x_perf, 'predicted_performance') # Функции принадлежности avg_subject['низкий'] = fuzz.trimf(x_avg, [40, 45, 55]) avg_subject['средний'] = fuzz.trimf(x_avg, [52, 57, 65]) avg_subject['высокий'] = fuzz.trimf(x_avg, [63, 75, 100]) attendance['низкая'] = fuzz.trimf(x_attend, [50, 60, 70]) attendance['средняя'] = fuzz.trimf(x_attend, [68, 80, 90]) attendance['высокая'] = fuzz.trimf(x_attend, [88, 95, 100]) studyhours['мало'] = fuzz.trimf(x_studyhours, [0, 4, 12]) studyhours['средне'] = fuzz.trimf(x_studyhours, [10, 16, 22]) studyhours['много'] = fuzz.trimf(x_studyhours, [20, 30, 40]) predicted_performance['низкая'] = fuzz.trimf(x_perf, [0, 35, 55]) predicted_performance['средняя'] = fuzz.trimf(x_perf, [50, 60, 85]) predicted_performance['высокая'] = fuzz.trimf(x_perf, [85, 90, 100]) rules = [ # Высокая успеваемость ctrl.Rule(avg_subject['высокий'] & attendance['высокая'] & studyhours['много'], predicted_performance['высокая']), # ctrl.Rule(avg_subject['высокий'] & (attendance['высокая'] | studyhours['много']), # predicted_performance['высокая']), ctrl.Rule(avg_subject['высокий'] & studyhours['средне'], predicted_performance['средняя']), ctrl.Rule(avg_subject['высокий'] & attendance['средняя'] & studyhours['мало'], predicted_performance['средняя']), # Средняя успеваемость ctrl.Rule(avg_subject['средний'] & attendance['высокая'] & studyhours['много'], predicted_performance['средняя']), ctrl.Rule(avg_subject['средний'] & (attendance['высокая'] | studyhours['много']), predicted_performance['средняя']), ctrl.Rule(avg_subject['средний'] & (attendance['средняя'] | studyhours['средне']), predicted_performance['средняя']), ctrl.Rule(avg_subject['средний'] & studyhours['мало'], predicted_performance['средняя']), ctrl.Rule(avg_subject['средний'] & attendance['средняя'] & studyhours['средне'], predicted_performance['средняя']), # Низкая успеваемость ctrl.Rule(avg_subject['низкий'], predicted_performance['низкая']), ctrl.Rule(attendance['низкая'], predicted_performance['низкая']), ctrl.Rule((avg_subject['низкий'] | attendance['низкая']) & studyhours['мало'], predicted_performance['низкая']), ] system = ctrl.ControlSystem(rules) return ctrl.ControlSystemSimulation(system) def evaluate_model(): df = pd.read_csv("student_dataset.csv") df = df[(df['Math'].between(0, 100)) & (df['Physics'].between(0, 100)) & (df['History'].between(0, 100)) & (df['StudyHours'].between(0, 40)) & (df['Attendance'].between(0, 100))] df['avg_subject'] = df[['Math', 'Physics', 'History']].mean(axis=1) # --- NEW: сохраняем оригинальные классы df['PerformanceClass'] = df['Performance'] # Отображаем классы в численные значения (для регрессии) performance_map = {'низкая': 35, 'средняя': 60, 'высокая': 90} df['Performance'] = df['Performance'].map(performance_map) print(df['PerformanceClass'].value_counts()) results = [] sim = build_fuzzy_system() for _, row in tqdm(df.iterrows(), total=len(df), desc="Прогнозирование"): sim.input['studyhours'] = row['StudyHours'] sim.input['attendance'] = row['Attendance'] sim.input['avg_subject'] = row['avg_subject'] try: sim.compute() predicted = sim.output['predicted_performance'] actual = row['Performance'] actual_class = row['PerformanceClass'] results.append({ 'actual': actual, 'predicted': predicted, 'actual_class': actual_class }) except: continue results = pd.DataFrame(results) print("NaN в results['actual']:", results['actual'].isna().sum()) print("NaN в results['predicted']:", results['predicted'].isna().sum()) # --- Оценка по численным метрикам --- mae = mean_absolute_error(results['actual'], results['predicted']) mse = mean_squared_error(results['actual'], results['predicted']) corr = np.corrcoef(results['actual'], results['predicted'])[0, 1] print(f"\n🔢 MAE: {mae:.2f}") print(f"📉 MSE: {mse:.2f}") print(f"📊 Корреляция: {corr:.3f}") # --- NEW: преобразуем предсказание в классы --- def classify(score): if score < 65: return 'низкая' elif score < 85: return 'средняя' else: return 'высокая' results['predicted_class'] = results['predicted'].apply(classify) # --- NEW: метрики классификации --- acc = accuracy_score(results['actual_class'], results['predicted_class']) print(f"\n✅ Accuracy по классам: {acc*100:.2f}%") print("\n🧮 Confusion Matrix:") print(confusion_matrix(results['actual_class'], results['predicted_class'], labels=["низкая", "средняя", "высокая"])) print("\n📋 Classification Report:") print(classification_report(results['actual_class'], results['predicted_class'], labels=["низкая", "средняя", "высокая"])) # --- Визуализация --- plt.hist(results['predicted'], bins=20, alpha=0.5, label='Predicted') plt.hist(results['actual'], bins=20, alpha=0.5, label='Actual') plt.legend() plt.title("Распределение фактической и предсказанной успеваемости") plt.show() plt.figure(figsize=(8, 6)) sns.scatterplot(x='actual', y='predicted', data=results) plt.plot([0, 100], [0, 100], 'r--') plt.xlabel('Фактическая успеваемость') plt.ylabel('Предсказанная успеваемость') plt.title('Сравнение фактической и предсказанной успеваемости') plt.grid(True) plt.show() # Меню def main_menu(): while True: print("\n===== Интеллектуальная система поддержки студента =====") print("1. Анализировать датасет студентов") print("2. Составить рекомендации для одного ученика") print("3. Анализ функций прогноза") print("0. Выйти из программы") choice = input("Выберите пункт (0, 1, 2 или 3): ") if choice == "1": analyze_data() elif choice == "2": recommend_for_student() elif choice == "3": evaluate_model() elif choice == "0": print("👋 Выход из программы. До свидания!") break else: print("❌ Неверный ввод. Попробуйте снова.") if __name__ == "__main__": main_menu()