初始化项目,由ModelHub XC社区提供模型
Model: Vilyam888/Code_analyze.1.0 Source: Original Platform
This commit is contained in:
36
.gitattributes
vendored
Normal file
36
.gitattributes
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||
*.arrow filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
||||
*.ftz filter=lfs diff=lfs merge=lfs -text
|
||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||
*.h5 filter=lfs diff=lfs merge=lfs -text
|
||||
*.joblib filter=lfs diff=lfs merge=lfs -text
|
||||
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
||||
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
||||
*.model filter=lfs diff=lfs merge=lfs -text
|
||||
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
||||
*.npy filter=lfs diff=lfs merge=lfs -text
|
||||
*.npz filter=lfs diff=lfs merge=lfs -text
|
||||
*.onnx filter=lfs diff=lfs merge=lfs -text
|
||||
*.ot filter=lfs diff=lfs merge=lfs -text
|
||||
*.parquet filter=lfs diff=lfs merge=lfs -text
|
||||
*.pb filter=lfs diff=lfs merge=lfs -text
|
||||
*.pickle filter=lfs diff=lfs merge=lfs -text
|
||||
*.pkl filter=lfs diff=lfs merge=lfs -text
|
||||
*.pt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pth filter=lfs diff=lfs merge=lfs -text
|
||||
*.rar filter=lfs diff=lfs merge=lfs -text
|
||||
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
||||
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
||||
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
||||
*.tar filter=lfs diff=lfs merge=lfs -text
|
||||
*.tflite filter=lfs diff=lfs merge=lfs -text
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.wasm filter=lfs diff=lfs merge=lfs -text
|
||||
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.zst filter=lfs diff=lfs merge=lfs -text
|
||||
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
||||
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
||||
543
Dataset_CA_1example.json
Normal file
543
Dataset_CA_1example.json
Normal file
@@ -0,0 +1,543 @@
|
||||
{
|
||||
"task": {
|
||||
"id": 1,
|
||||
"title": "Кластеризация клиентов интернет-магазина",
|
||||
"description": "Создайте функцию `segment_customers`, которая принимает таблицу признаков клиентов X (возраст, доход, частота покупок, средний чек) и выполняет кластеризацию методом K-Means. Требования: нормализовать данные перед кластеризацией, определить оптимальное количество кластеров (2-10) с помощью метода локтя или силуэта, вернуть обученную модель и визуализировать результаты.",
|
||||
"difficulty": "medium",
|
||||
"tags": [
|
||||
{"name": "Clustering", "weight": 0.50},
|
||||
{"name": "sklearn", "weight": 0.30},
|
||||
{"name": "DataPreprocessing", "weight": 0.20}
|
||||
]
|
||||
},
|
||||
"solutions": [
|
||||
{
|
||||
"solution": {
|
||||
"code": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom sklearn.cluster import KMeans\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.metrics import silhouette_score\n\n\ndef segment_customers(X, k_range=(2, 10)):\n # Нормализация данных\n scaler = StandardScaler()\n X_scaled = scaler.fit_transform(X)\n \n # Подбор оптимального k методом силуэта\n silhouette_scores = []\n K_values = range(k_range[0], k_range[1] + 1)\n \n for k in K_values:\n kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)\n labels = kmeans.fit_predict(X_scaled)\n score = silhouette_score(X_scaled, labels)\n silhouette_scores.append(score)\n \n # Выбор оптимального k\n optimal_k = K_values[np.argmax(silhouette_scores)]\n print(f\"Optimal k: {optimal_k} (silhouette: {max(silhouette_scores):.3f})\")\n \n # Обучение финальной модели\n final_model = KMeans(n_clusters=optimal_k, random_state=42, n_init=10)\n clusters = final_model.fit_predict(X_scaled)\n \n # Визуализация (первые 2 компоненты)\n plt.figure(figsize=(10, 6))\n plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=clusters, cmap='viridis', alpha=0.6)\n plt.scatter(final_model.cluster_centers_[:, 0], \n final_model.cluster_centers_[:, 1], \n c='red', marker='X', s=200, edgecolors='black', label='Centroids')\n plt.title(f'Customer Segmentation (k={optimal_k})')\n plt.xlabel('Feature 1 (scaled)')\n plt.ylabel('Feature 2 (scaled)')\n plt.legend()\n plt.colorbar(label='Cluster')\n plt.show()\n \n return final_model, scaler\n",
|
||||
"success": true
|
||||
},
|
||||
"analysis": {
|
||||
"summary": "Отличное решение с полным соответствием требованиям: корректная нормализация данных, автоматический подбор оптимального k методом силуэта, визуализация результатов. Код структурирован и готов к использованию.",
|
||||
"task_compliance": {
|
||||
"is_relevant": true,
|
||||
"score": 9,
|
||||
"description": "Решение полностью соответствует задаче кластеризации клиентов. Все требования выполнены корректно.",
|
||||
"tag_alignment": {
|
||||
"Clustering": {
|
||||
"required_weight": 0.50,
|
||||
"applied": true,
|
||||
"score": 9,
|
||||
"evidence": "Использован алгоритм K-Means - классический метод кластеризации. Студент правильно применил unsupervised learning подход, выполнил подбор оптимального количества кластеров через метрику silhouette_score, что демонстрирует глубокое понимание задачи сегментации. Центроиды кластеров корректно визуализированы, что позволяет интерпретировать результаты. Использован параметр n_init=10 для множественных инициализаций, что повышает стабильность результатов и защищает от локальных минимумов. Это показывает знание особенностей K-Means алгоритма."
|
||||
},
|
||||
"sklearn": {
|
||||
"required_weight": 0.30,
|
||||
"applied": true,
|
||||
"score": 10,
|
||||
"evidence": "Продемонстрировано профессиональное владение scikit-learn: правильно использованы KMeans из sklearn.cluster с корректными параметрами (random_state для воспроизводимости, n_init для стабильности), применена метрика silhouette_score из sklearn.metrics для объективной оценки качества кластеризации, использован StandardScaler для нормализации. Код следует best practices библиотеки - раздельное обучение scaler и модели, что позволяет применять их на новых данных. Возвращаются обученные объекты, а не только предсказания."
|
||||
},
|
||||
"DataPreprocessing": {
|
||||
"required_weight": 0.20,
|
||||
"applied": true,
|
||||
"score": 9,
|
||||
"evidence": "Выполнена обязательная нормализация данных через StandardScaler перед кластеризацией - критически важный шаг для K-Means, так как алгоритм чувствителен к масштабу признаков. Студент понимает, что без нормализации признаки с большим масштабом (например, доход в тысячах) будут доминировать над признаками с малым масштабом (например, частота покупок 1-10), что исказит результаты кластеризации. Использование fit_transform демонстрирует понимание pipeline предобработки. Возврат scaler вместе с моделью позволяет применять ту же трансформацию на новых данных."
|
||||
}
|
||||
},
|
||||
"missing_requirements": [],
|
||||
"extra_features": [
|
||||
"Автоматический перебор диапазона k для поиска оптимума",
|
||||
"Использование silhouette метрики - более надежной чем метод локтя",
|
||||
"Визуализация центроидов кластеров для интерпретации",
|
||||
"Возврат scaler для применения на новых данных"
|
||||
]
|
||||
},
|
||||
"code_quality_score": 9.2,
|
||||
"correctness": {
|
||||
"is_correct": true,
|
||||
"score": 9,
|
||||
"edge_cases_handled": true
|
||||
},
|
||||
"Временная сложность решения": {
|
||||
"time_complexity": "O(k * n * d * i * iterations)",
|
||||
"space_complexity": "O(n * d + k * d)",
|
||||
"efficiency": "средняя",
|
||||
"explanation": "где k - диапазон кластеров (2-10), n - количество объектов, d - размерность признаков, i - n_init (10), iterations - количество итераций до сходимости K-Means. Основная сложность в переборе k значений с обучением KMeans на каждом."
|
||||
},
|
||||
"strengths": [
|
||||
"Правильная архитектура решения: препроцессинг → подбор гиперпараметров → финальное обучение → визуализация",
|
||||
"Использование silhouette_score - объективная метрика качества кластеризации, учитывающая компактность и разделимость кластеров",
|
||||
"Фиксация random_state обеспечивает воспроизводимость результатов",
|
||||
"Визуализация центроидов помогает в интерпретации и валидации результатов",
|
||||
"Возврат обученного scaler позволяет корректно трансформировать новые данные"
|
||||
],
|
||||
"weaknesses": [
|
||||
"Визуализация использует только первые 2 признака (X_scaled[:, 0] и [:, 1]), что может не отражать полную картину в многомерном пространстве",
|
||||
"Нет обработки случая одинаковых silhouette scores для разных k",
|
||||
"Отсутствует проверка на пустые кластеры или выбросы перед кластеризацией",
|
||||
"Не выводятся размеры полученных кластеров, что важно для анализа сегментации"
|
||||
],
|
||||
"recommendations": [
|
||||
"Для визуализации высокоразмерных данных использовать PCA или t-SNE для снижения размерности перед отрисовкой, а не просто первые 2 признака",
|
||||
"Добавить вывод размеров кластеров: np.bincount(clusters) для проверки баланса сегментов",
|
||||
"Рассмотреть метод локтя (inertia) вместе с silhouette для более уверенного выбора k",
|
||||
"Добавить детектирование выбросов через DBSCAN или IsolationForest перед K-Means для улучшения качества",
|
||||
"Логировать характеристики каждого кластера (средние значения признаков) для бизнес-интерпретации сегментов"
|
||||
],
|
||||
"detailed_analysis": "В решении продемонстрировано глубокое понимание задачи кластеризации и её применения к бизнес-задаче сегментации клиентов. Решение покрывает все ключевые теги: Clustering (50% - правильное применение K-Means с подбором k), sklearn (30% - профессиональное использование библиотеки), DataPreprocessing (20% - обязательная нормализация для K-Means). \n\nОсобо стоит отметить выбор метрики silhouette для определения оптимального k - это более надежный подход чем популярный метод локтя, так как silhouette количественно оценивает качество кластеризации учитывая как компактность кластеров, так и их разделимость. Использование n_init=10 показывает понимание проблемы случайной инициализации K-Means и локальных минимумов.\n\nВозврат как модели, так и scaler - важная деталь для production кода, позволяющая корректно обрабатывать новые данные с той же нормализацией. Визуализация с центроидами помогает в интерпретации результатов, хотя ограничение двумя измерениями может быть недостаточным для полного анализа.\n\nОсновные направления улучшения: использование PCA/t-SNE для корректной визуализации многомерных данных, добавление анализа характеристик каждого сегмента для бизнес-интерпретации, обработка выбросов. В целом - сильное решение уровня Medium с потенциалом применения в реальных проектах."
|
||||
}
|
||||
},
|
||||
{
|
||||
"solution": {
|
||||
"code": "from sklearn.decomposition import PCA\nimport matplotlib.pyplot as plt\n\n\ndef segment_customers(X):\n # Применяем PCA для снижения размерности\n pca = PCA(n_components=2)\n X_reduced = pca.fit_transform(X)\n \n # Визуализация\n plt.figure(figsize=(10, 6))\n plt.scatter(X_reduced[:, 0], X_reduced[:, 1], alpha=0.6)\n plt.title('Customer Data - PCA Projection')\n plt.xlabel('PC1')\n plt.ylabel('PC2')\n plt.show()\n \n print(f\"Explained variance: {pca.explained_variance_ratio_}\")\n return pca\n",
|
||||
"success": true
|
||||
},
|
||||
"analysis": {
|
||||
"summary": "Решение использует PCA для снижения размерности, но задача требовала кластеризацию методом K-Means. Это совершенно другая задача - dimensionality reduction вместо clustering.",
|
||||
"task_compliance": {
|
||||
"is_relevant": false,
|
||||
"score": 1,
|
||||
"description": "Код решает задачу снижения размерности (PCA), а не кластеризации клиентов. Это Фундаментально неправильный подход - задача требовала разделить клиентов на группы (сегменты), а не визуализировать их в 2D пространстве.",
|
||||
"tag_alignment": {
|
||||
"Clustering": {
|
||||
"required_weight": 0.50,
|
||||
"applied": false,
|
||||
"score": 0,
|
||||
"evidence": "НЕ ИСПОЛЬЗОВАНА КЛАСТЕРИЗАЦИЯ! PCA - это метод снижения размерности (DimensionalityReduction), а не кластеризации. Код не создает сегменты клиентов, не присваивает метки кластеров, не ищет группы схожих объектов. Это как если бы вместо группировки студентов по успеваемости просто нарисовали их на графике - задача не решена."
|
||||
},
|
||||
"sklearn": {
|
||||
"required_weight": 0.30,
|
||||
"applied": true,
|
||||
"score": 5,
|
||||
"evidence": "Формально sklearn используется (PCA из sklearn.decomposition), но применяется неправильный класс. Вместо sklearn.cluster.KMeans использован sklearn.decomposition.PCA - это показывает непонимание различия между задачами supervised/unsupervised learning."
|
||||
},
|
||||
"DataPreprocessing": {
|
||||
"required_weight": 0.20,
|
||||
"applied": false,
|
||||
"score": 2,
|
||||
"evidence": "Нет нормализации данных перед PCA. Хотя PCA требует нормализации так же как K-Means, она не выполнена. Данные используются напрямую, что может привести к доминированию признаков с большим масштабом."
|
||||
}
|
||||
},
|
||||
"missing_requirements": [
|
||||
"КРИТИЧНО: Отсутствует кластеризация методом K-Means (основное требование задачи - 50% веса)",
|
||||
"КРИТИЧНО: Нет определения оптимального количества кластеров",
|
||||
"КРИТИЧНО: Не возвращается модель кластеризации",
|
||||
"Нет нормализации данных",
|
||||
"Не используется метод локтя или силуэта"
|
||||
],
|
||||
"wrong_approach": "PCA (dimensionality reduction) вместо K-Means (clustering)"
|
||||
},
|
||||
"code_quality_score": 2.0,
|
||||
"correctness": {
|
||||
"is_correct": false,
|
||||
"score": 1,
|
||||
"edge_cases_handled": false
|
||||
},
|
||||
"Временная сложность решения": {
|
||||
"time_complexity": "O(n * d²)",
|
||||
"space_complexity": "O(d²)",
|
||||
"efficiency": "высокая",
|
||||
"explanation": "PCA имеет сложность O(n * d²) где d - количество признаков. Эффективнее чем K-Means, но решает не ту задачу."
|
||||
},
|
||||
"strengths": [
|
||||
"Код работает без ошибок и выполняется",
|
||||
"Визуализация корректно отображает данные в 2D пространстве",
|
||||
"Выводится explained variance для понимания информативности компонент"
|
||||
],
|
||||
"weaknesses": [
|
||||
"КРИТИЧЕСКАЯ ОШИБКА: Решается задача снижения размерности, а не кластеризации - тег Clustering (50% важности) полностью проигнорирован",
|
||||
"Нет сегментации клиентов на группы - основная цель задачи не достигнута",
|
||||
"Отсутствует нормализация данных",
|
||||
"PCA не присваивает кластерные метки и не создает сегменты",
|
||||
"Невозможно использовать результат для бизнес-задачи (разделение клиентов на группы для маркетинга)"
|
||||
],
|
||||
"recommendations": [
|
||||
"ОБЯЗАТЕЛЬНО: Изучить разницу между dimensionality reduction (PCA, t-SNE) и clustering (K-Means, DBSCAN, Hierarchical)",
|
||||
"ОБЯЗАТЕЛЬНО: Реализовать K-Means кластеризацию как требует задача",
|
||||
"Понять что PCA можно использовать ДО кластеризации для снижения размерности, но не ВМЕСТО нее",
|
||||
"После реализации K-Means можно использовать PCA только для визуализации результатов кластеризации"
|
||||
],
|
||||
"detailed_analysis": "Решение демонстрирует фундаментальное непонимание задачи. PCA и K-Means решают разные типы задач: PCA - это unsupervised dimensionality reduction (находит главные компоненты, объясняющие максимальную дисперсию), K-Means - это unsupervised clustering (находит группы схожих объектов). Задача требовала разделить клиентов на сегменты для последующего таргетированного маркетинга, а не просто визуализировать их в 2D.\n\nВАШ КОД РЕШАЕТ ДРУГУЮ ЗАДАЧУ. Необходимо переписать решение с использованием K-Means кластеризации."
|
||||
}
|
||||
},
|
||||
{
|
||||
"solution": {
|
||||
"code": "from sklearn.ensemble import RandomForestClassifier\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler\nimport numpy as np\n\n\ndef segment_customers(X, y):\n # Предполагаем что есть целевая переменная\n scaler = StandardScaler()\n X_scaled = scaler.fit_transform(X)\n \n X_train, X_test, y_train, y_test = train_test_split(\n X_scaled, y, test_size=0.2, random_state=42\n )\n \n model = RandomForestClassifier(n_estimators=100, random_state=42)\n model.fit(X_train, y_train)\n \n accuracy = model.score(X_test, y_test)\n print(f\"Accuracy: {accuracy:.3f}\")\n \n return model\n",
|
||||
"success": true
|
||||
},
|
||||
"analysis": {
|
||||
"summary": "Решение использует классификацию (supervised learning) вместо кластеризации (unsupervised learning). Это совершенно другой тип задачи - требуется известная целевая переменная y, которой нет в задаче сегментации.",
|
||||
"task_compliance": {
|
||||
"is_relevant": false,
|
||||
"score": 1,
|
||||
"description": "Код решает задачу supervised classification, а требовалась unsupervised clustering. Задача сегментации клиентов означает что нет известных меток - нужно найти естественные группы в данных.",
|
||||
"tag_alignment": {
|
||||
"Clustering": {
|
||||
"required_weight": 0.50,
|
||||
"applied": false,
|
||||
"score": 0,
|
||||
"evidence": "ФУНДАМЕНТАЛЬНАЯ ОШИБКА: Использован RandomForestClassifier - это supervised learning алгоритм для классификации, который требует известные метки классов (y). Кластеризация - это unsupervised learning, где метки НЕИЗВЕСТНЫ и их нужно найти. В задаче сегментации клиентов нет заранее известных групп - нужно автоматически их обнаружить. Это как разница между 'распределить студентов по заранее известным классам A/B/C' (classification) и 'найти естественные группы студентов по их характеристикам' (clustering)."
|
||||
},
|
||||
"sklearn": {
|
||||
"required_weight": 0.30,
|
||||
"applied": true,
|
||||
"score": 4,
|
||||
"evidence": "sklearn формально используется (RandomForestClassifier, StandardScaler, train_test_split), но выбран совершенно неподходящий модуль. Вместо sklearn.cluster использован sklearn.ensemble - это показывает путаницу между типами задач machine learning. train_test_split вообще не нужен для кластеризации, так как нет целевой переменной."
|
||||
},
|
||||
"DataPreprocessing": {
|
||||
"required_weight": 0.20,
|
||||
"applied": true,
|
||||
"score": 6,
|
||||
"evidence": "Нормализация через StandardScaler выполнена корректно - это единственная правильная часть решения. Однако контекст использования неверный - данные подготовлены для классификации вместо кластеризации."
|
||||
}
|
||||
},
|
||||
"missing_requirements": [
|
||||
"КРИТИЧНО: Использован supervised learning вместо unsupervised (тип задачи неправильный)",
|
||||
"КРИТИЧНО: Требуется несуществующая целевая переменная y",
|
||||
"КРИТИЧНО: Отсутствует K-Means кластеризация",
|
||||
"Нет определения оптимального количества кластеров",
|
||||
"Нет визуализации результатов кластеризации"
|
||||
],
|
||||
"wrong_approach": "RandomForestClassifier (supervised classification) вместо K-Means (unsupervised clustering)"
|
||||
},
|
||||
"code_quality_score": 2.5,
|
||||
"correctness": {
|
||||
"is_correct": false,
|
||||
"score": 1,
|
||||
"edge_cases_handled": false
|
||||
},
|
||||
"Временная сложность решения": {
|
||||
"time_complexity": "O(T * n * log(n) * d)",
|
||||
"space_complexity": "O(T * n)",
|
||||
"efficiency": "низкая",
|
||||
"explanation": "где T - количество деревьев (100), n - объекты, d - признаки. RandomForest медленнее K-Means, но это не важно так как решается не та задача."
|
||||
},
|
||||
"strengths": [
|
||||
"Код технически грамотный для задачи классификации",
|
||||
"Правильно использованы train_test_split и оценка качества",
|
||||
"Нормализация данных выполнена корректно"
|
||||
],
|
||||
"weaknesses": [
|
||||
"КРИТИЧЕСКАЯ ОШИБКА: Перепутаны supervised и unsupervised learning - тег Clustering (50% важности) полностью проигнорирован",
|
||||
"Требуется целевая переменная y, которая не существует в задаче сегментации",
|
||||
"Невозможно выполнить код так как функция принимает только X, а используется y",
|
||||
"Train/test split бессмысленен для кластеризации",
|
||||
"Результат непригоден для бизнес-задачи - нельзя сегментировать новых клиентов без известных меток"
|
||||
],
|
||||
"recommendations": [
|
||||
"ОБЯЗАТЕЛЬНО: Изучить разницу между supervised learning (classification/regression с известными метками) и unsupervised learning (clustering без меток)",
|
||||
"ОБЯЗАТЕЛЬНО: Реализовать K-Means из sklearn.cluster вместо RandomForestClassifier",
|
||||
"Понять что в сегментации клиентов нет заранее известных групп - их нужно обнаружить алгоритмом",
|
||||
"Убрать train_test_split - для кластеризации используется весь датасет целиком"
|
||||
],
|
||||
"detailed_analysis": "Решение демонстрирует критическое непонимание типов задач machine learning. Supervised learning (классификация, регрессия) требует обучающие данные с известными ответами (X, y) и учится предсказывать y для новых X. Unsupervised learning (кластеризация, снижение размерности) работает только с X и ищет скрытые паттерны/структуры в данных без известных меток.\n\nЗадача сегментации клиентов - это классический пример unsupervised learning: у компании есть данные о клиентах (возраст, доход, покупки), но нет готовых групп. Нужно автоматически найти естественные сегменты (например, 'молодые активные', 'богатые редкие', 'средний класс частые' и т.д.).\n\nВАШ КОД РЕШАЕТ ДРУГУЮ ЗАДАЧУ. RandomForestClassifier требует известные метки классов, которых нет в сегментации. Необходимо переписать с K-Means."
|
||||
}
|
||||
},
|
||||
{
|
||||
"solution": {
|
||||
"code": "from sklearn.cluster import KMeans\nimport matplotlib.pyplot as plt\n\n\ndef segment_customers(X):\n # Попытка кластеризации без нормализации\n model = KMeans(n_clusters=3)\n # Ошибка: забыл вызвать fit\n clusters = model.predict(X)\n \n plt.scatter(X[:, 0], X[:, 1], c=clusters)\n plt.show()\n \n return model\n",
|
||||
"success": false
|
||||
},
|
||||
"analysis": {
|
||||
"summary": "Код содержит критическую ошибку - вызов predict до fit. KMeans модель не обучена, что приведет к исключению NotFittedError. Также отсутствуют нормализация и подбор оптимального k.",
|
||||
"task_compliance": {
|
||||
"is_relevant": true,
|
||||
"score": 3,
|
||||
"description": "Намерение решить задачу кластеризации правильное (используется KMeans), но реализация нерабочая из-за логической ошибки.",
|
||||
"tag_alignment": {
|
||||
"Clustering": {
|
||||
"required_weight": 0.50,
|
||||
"applied": "partially",
|
||||
"score": 3,
|
||||
"evidence": "Использован правильный алгоритм K-Means для кластеризации, но с критической ошибкой в последовательности операций. В sklearn любая модель требует сначала обучения (fit), затем предсказания (predict). Вызов predict до fit приведет к ошибке: 'NotFittedError: This KMeans instance is not fitted yet'. Также количество кластеров k=3 захардкожено без обоснования, не выполнен подбор оптимального k методом локтя или силуэта как требовалось в задаче."
|
||||
},
|
||||
"sklearn": {
|
||||
"required_weight": 0.30,
|
||||
"applied": "partially",
|
||||
"score": 2,
|
||||
"evidence": "Демонстрируется непонимание базового workflow sklearn: fit → predict. Это фундаментальная концепция библиотеки, применимая ко всем алгоритмам. Правильная последовательность: model.fit(X) для обучения, затем model.predict(X_new) для новых данных или model.fit_predict(X) для обучения и получения меток одновременно. Такая ошибка показывает недостаточное знакомство с библиотекой."
|
||||
},
|
||||
"DataPreprocessing": {
|
||||
"required_weight": 0.20,
|
||||
"applied": false,
|
||||
"score": 0,
|
||||
"evidence": "Полностью отсутствует нормализация данных - обязательное требование задачи и критически важный шаг для K-Means. Без StandardScaler признаки с большим масштабом (доход 20000-100000) будут доминировать над признаками с малым масштабом (возраст 18-65, частота покупок 1-20). Это приведет к искаженной кластеризации, где расстояния будут определяться в основном доходом, а остальные признаки игнорироваться."
|
||||
}
|
||||
},
|
||||
"missing_requirements": [
|
||||
"КРИТИЧНО: Нет вызова fit перед predict - код выдаст ошибку",
|
||||
"КРИТИЧНО: Отсутствует нормализация данных (требование задачи)",
|
||||
"Нет определения оптимального k - значение 3 захардкожено",
|
||||
"Не используется метод локтя или силуэта",
|
||||
"Визуализация примитивная - нет центроидов, подписей, легенды"
|
||||
],
|
||||
"extra_features": []
|
||||
},
|
||||
"code_quality_score": 1.8,
|
||||
"correctness": {
|
||||
"is_correct": false,
|
||||
"score": 1,
|
||||
"edge_cases_handled": false
|
||||
},
|
||||
"Временная сложность решения": {
|
||||
"time_complexity": "N/A",
|
||||
"space_complexity": "N/A",
|
||||
"efficiency": "N/A",
|
||||
"explanation": "Код не выполнится из-за ошибки, поэтому сложность неприменима."
|
||||
},
|
||||
"strengths": [
|
||||
"Выбран правильный алгоритм K-Means для задачи кластеризации",
|
||||
"Присутствует визуализация результатов (хоть и простая)"
|
||||
],
|
||||
"weaknesses": [
|
||||
"КРИТИЧЕСКАЯ ОШИБКА: Вызов predict до fit - код не работает, выдаст NotFittedError",
|
||||
"Отсутствует обязательная нормализация данных - тег DataPreprocessing (20% важности) полностью проигнорирован",
|
||||
"Hardcoded значение k=3 без обоснования и подбора оптимального значения",
|
||||
"Нет использования методов локтя или силуэта как требовала задача",
|
||||
"Визуализация использует только 2 признака, нет подписей осей и легенды",
|
||||
"Не возвращается scaler (хотя его и нет)"
|
||||
],
|
||||
"recommendations": [
|
||||
"ОБЯЗАТЕЛЬНО: Изучить базовый workflow sklearn - fit обучает модель, predict делает предсказания на обученной модели",
|
||||
"ОБЯЗАТЕЛЬНО: Добавить StandardScaler для нормализации данных перед кластеризацией",
|
||||
"Использовать fit_predict(X) для одновременного обучения и получения меток, или сначала fit(X), затем predict(X)",
|
||||
"Реализовать подбор оптимального k через цикл с метрикой silhouette_score",
|
||||
"Улучшить визуализацию: добавить центроиды, подписи, colorbar"
|
||||
],
|
||||
"detailed_analysis": "Решение показывает начальное понимание задачи (выбран K-Means), но содержит критические ошибки реализации. Главная проблема - непонимание последовательности fit → predict в sklearn, что является базовой концепцией библиотеки. При попытке выполнить код произойдет ошибка: sklearn.exceptions.NotFittedError.\n\nВторая серьезная проблема - полное отсутствие нормализации данных, что нарушает требование задачи (тег DataPreprocessing 20%) и приведет к некорректным результатам даже если исправить ошибку с fit. K-Means вычисляет Euclidean расстояния, которые чувствительны к масштабу признаков.\n\nТретья проблема - захардкоженное k=3 без какого-либо обоснования. Задача явно требовала определить оптимальное количество кластеров в диапазоне 2-10 используя метод локтя или силуэта.\n\nРекомендуется изучить основы sklearn и пересмотреть требования задачи перед новой попыткой реализации."
|
||||
}
|
||||
},
|
||||
{
|
||||
"solution": {
|
||||
"code": "from sklearn.cluster import KMeans\n\n\ndef segment_customers(X):\n # Кластеризация без нормализации и подбора k\n model = KMeans(n_clusters=4, random_state=42)\n clusters = model.fit_predict(X)\n \n print(f\"Clusters assigned: {len(set(clusters))}\")\n return model\n",
|
||||
"success": true
|
||||
},
|
||||
"analysis": {
|
||||
"summary": "Минималистичное рабочее решение: использован K-Means, код выполняется, но отсутствуют ключевые требования - нет нормализации данных, подбора оптимального k и визуализации. Это baseline решение с минимальным функционалом.",
|
||||
"task_compliance": {
|
||||
"is_relevant": true,
|
||||
"score": 4,
|
||||
"description": "Решение частично соответствует задаче - выполнена базовая кластеризация, но пропущены важные требования (нормализация, подбор k, визуализация).",
|
||||
"tag_alignment": {
|
||||
"Clustering": {
|
||||
"required_weight": 0.50,
|
||||
"applied": true,
|
||||
"score": 5,
|
||||
"evidence": "K-Means использован корректно - применен нужный алгоритм, модель обучена через fit_predict, возвращается обученный объект. Однако реализация минималистична: количество кластеров k=4 выбрано произвольно без обоснования и без использования методов локтя или силуэта как требовала задача. Отсутствует анализ качества кластеризации (silhouette score, inertia). Нет проверки результатов и интерпретации полученных сегментов. Это базовый уровень - алгоритм применен, но без понимания оптимальности решения."
|
||||
},
|
||||
"sklearn": {
|
||||
"required_weight": 0.30,
|
||||
"applied": true,
|
||||
"score": 6,
|
||||
"evidence": "sklearn.cluster.KMeans использован правильно: корректный импорт, правильный метод fit_predict (обучение + предсказание за один вызов), установлен random_state для воспроизводимости. Однако использование библиотеки поверхностное - не применены другие важные модули sklearn (StandardScaler для preprocessing, silhouette_score для оценки качества). Демонстрируется знание базового API, но не best practices библиотеки."
|
||||
},
|
||||
"DataPreprocessing": {
|
||||
"required_weight": 0.20,
|
||||
"applied": false,
|
||||
"score": 0,
|
||||
"evidence": "КРИТИЧЕСКИЙ НЕДОЧЕТ: Полностью отсутствует нормализация данных - это было явным требованием задачи. K-Means чувствителен к масштабу признаков, поэтому без StandardScaler результаты будут искажены. Признаки с большими значениями (доход в десятках тысяч) будут доминировать над признаками с малыми значениями (возраст, частота покупок), что приведет к неправильной сегментации клиентов. Это базовая ошибка, показывающая пробел в понимании preprocessing."
|
||||
}
|
||||
},
|
||||
"missing_requirements": [
|
||||
"КРИТИЧНО: Отсутствует нормализация данных (явное требование задачи)",
|
||||
"Нет определения оптимального количества кластеров - k=4 выбрано произвольно",
|
||||
"Не использованы методы локтя или силуэта",
|
||||
"Отсутствует визуализация результатов (требование задачи)",
|
||||
"Не возвращается scaler для применения на новых данных"
|
||||
],
|
||||
"extra_features": []
|
||||
},
|
||||
"code_quality_score": 4.2,
|
||||
"correctness": {
|
||||
"is_correct": "partially",
|
||||
"score": 4,
|
||||
"edge_cases_handled": false
|
||||
},
|
||||
"Временная сложность решения": {
|
||||
"time_complexity": "O(n * k * d * iterations)",
|
||||
"space_complexity": "O(n * d + k * d)",
|
||||
"efficiency": "средняя",
|
||||
"explanation": "где n - количество объектов, k=4 кластера, d - признаки, iterations - итерации до сходимости. Стандартная сложность K-Means."
|
||||
},
|
||||
"strengths": [
|
||||
"Код работает без ошибок и выполняет базовую кластеризацию",
|
||||
"Использован правильный метод fit_predict для обучения и получения меток",
|
||||
"Установлен random_state для воспроизводимости результатов",
|
||||
"Возвращается обученная модель"
|
||||
],
|
||||
"weaknesses": [
|
||||
"КРИТИЧЕСКИЙ НЕДОЧЕТ: Нет нормализации данных - тег DataPreprocessing (20% важности) полностью проигнорирован, нарушено требование задачи",
|
||||
"Количество кластеров k=4 выбрано наугад без использования методов локтя/силуэта (требование задачи)",
|
||||
"Отсутствует визуализация результатов (требование задачи)",
|
||||
"Нет оценки качества кластеризации (silhouette score, inertia)",
|
||||
"Невозможно интерпретировать полученные сегменты - не выводятся характеристики кластеров",
|
||||
"Решение не production-ready: нельзя применить к новым клиентам (нет сохраненного scaler)"
|
||||
],
|
||||
"recommendations": [
|
||||
"ОБЯЗАТЕЛЬНО: Добавить StandardScaler для нормализации данных перед кластеризацией - это ключевое требование",
|
||||
"Реализовать подбор оптимального k: цикл по range(2, 11) с вычислением silhouette_score или inertia",
|
||||
"Добавить визуализацию результатов с центроидами кластеров",
|
||||
"Вывести характеристики каждого сегмента (средние значения признаков) для бизнес-интерпретации",
|
||||
"Сохранять и возвращать scaler вместе с моделью для обработки новых данных"
|
||||
],
|
||||
"detailed_analysis": "Решение представляет собой минимальную рабочую реализацию K-Means - код выполняется и технически производит кластеризацию, но игнорирует большинство требований задачи. Основные проблемы:\n\n1. **Отсутствие нормализации (критично)**: Тег DataPreprocessing составляет 20% важности задачи и был явным требованием. Без нормализации K-Means будет работать некорректно - признаки с большим масштабом (например, доход 20000-100000) будут доминировать над признаками с малым масштабом (возраст 18-70, частота покупок 1-50). Результат - кластеризация в основном по доходу, игнорируя остальные характеристики клиентов.\n\n2. **Произвольное k=4**: Задача требовала найти оптимальное количество кластеров в диапазоне 2-10 используя метод локтя или силуэта. Значение 4 выбрано без обоснования, что может привести к недо-сегментации (слишком крупные группы) или пере-сегментации (слишком мелкие).\n\n3. **Нет визуализации**: Требование задачи - визуализировать результаты для интерпретации и валидации сегментации.\n\nЭто типичное 'сделал на скорую руку' решение - минимальный код для галочки, без внимания к требованиям и качеству. Для практического применения необходима полная переработка с учетом всех требований."
|
||||
}
|
||||
},
|
||||
{
|
||||
"solution": {
|
||||
"code": "from sklearn.cluster import KMeans\nfrom sklearn.preprocessing import StandardScaler\nimport matplotlib.pyplot as plt\n\n\ndef segment_customers(X):\n # Нормализация\n scaler = StandardScaler()\n X_scaled = scaler.fit_transform(X)\n \n # Фиксированное k без подбора\n model = KMeans(n_clusters=5, random_state=42)\n clusters = model.fit_predict(X_scaled)\n \n # Простая визуализация\n plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=clusters, cmap='viridis')\n plt.title('Customer Segments')\n plt.show()\n \n return model, scaler\n",
|
||||
"success": true
|
||||
},
|
||||
"analysis": {
|
||||
"summary": "Рабочее решение среднего качества: есть нормализация, визуализация, возврат модели и scaler. Но отсутствует автоматический подбор оптимального количества кластеров - ключевое требование задачи.",
|
||||
"task_compliance": {
|
||||
"is_relevant": true,
|
||||
"score": 6,
|
||||
"description": "Решение соответствует большинству требований, но упущен важный аспект - определение оптимального k методом локтя или силуэта.",
|
||||
"tag_alignment": {
|
||||
"Clustering": {
|
||||
"required_weight": 0.50,
|
||||
"applied": true,
|
||||
"score": 6,
|
||||
"evidence": "K-Means применен корректно с правильными параметрами (random_state для воспроизводимости). Модель обучена на нормализованных данных, что правильно. Однако критическое упущение - количество кластеров k=5 выбрано произвольно, а задача явно требовала 'определить оптимальное количество кластеров (2-10) с помощью метода локтя или силуэта'. Это не просто рекомендация, а ключевое требование, показывающее понимание того, что k - это гиперпараметр требующий настройки. Отсутствие подбора k снижает практическую ценность решения - нет уверенности что 5 сегментов оптимально для данных."
|
||||
},
|
||||
"sklearn": {
|
||||
"required_weight": 0.30,
|
||||
"applied": true,
|
||||
"score": 7,
|
||||
"evidence": "Демонстрируется хорошее знание sklearn: правильно использованы KMeans и StandardScaler, понимание необходимости fit_transform для scaler, возврат обученных объектов для применения на новых данных. Однако не использованы метрики качества (silhouette_score, calinski_harabasz_score) из sklearn.metrics, которые необходимы для определения оптимального k. Код следует базовым практикам библиотеки, но не использует её полные возможности для решения задачи."
|
||||
},
|
||||
"DataPreprocessing": {
|
||||
"required_weight": 0.20,
|
||||
"applied": true,
|
||||
"score": 8,
|
||||
"evidence": "Нормализация через StandardScaler выполнена корректно - это обязательное требование задачи. Использован правильный метод fit_transform для обучения scaler на данных и трансформации одновременно. Scaler возвращается вместе с моделью, что позволяет применять ту же нормализацию на новых клиентах - правильный подход для production. Единственное замечание - нет проверки на пропущенные значения или выбросы перед нормализацией, но это minor недочет."
|
||||
}
|
||||
},
|
||||
"missing_requirements": [
|
||||
"Нет определения оптимального k - значение 5 выбрано без обоснования",
|
||||
"Не использованы методы локтя или силуэта (явное требование задачи)",
|
||||
"Визуализация упрощенная - нет центроидов кластеров",
|
||||
"Не выводится метрика качества кластеризации"
|
||||
],
|
||||
"extra_features": [
|
||||
"Возврат scaler для применения на новых данных"
|
||||
]
|
||||
},
|
||||
"code_quality_score": 6.8,
|
||||
"correctness": {
|
||||
"is_correct": true,
|
||||
"score": 7,
|
||||
"edge_cases_handled": "partially"
|
||||
},
|
||||
"Временная сложность решения": {
|
||||
"time_complexity": "O(n * k * d * iterations)",
|
||||
"space_complexity": "O(n * d + k * d)",
|
||||
"efficiency": "средняя",
|
||||
"explanation": "где n - объекты, k=5 кластеров, d - признаки, iterations - итерации сходимости K-Means. Стандартная сложность одного прогона K-Means."
|
||||
},
|
||||
"strengths": [
|
||||
"Выполнена обязательная нормализация данных через StandardScaler",
|
||||
"Правильная последовательность: preprocessing → clustering → visualization",
|
||||
"Возврат как модели, так и scaler - важно для применения на новых данных",
|
||||
"Использован random_state для воспроизводимости",
|
||||
"Код чистый, читаемый, без ошибок"
|
||||
],
|
||||
"weaknesses": [
|
||||
"Отсутствует подбор оптимального k - ключевое требование задачи (тег Clustering 50%) не полностью выполнено",
|
||||
"k=5 выбрано произвольно без использования метода локтя или силуэта",
|
||||
"Нет вывода метрик качества (silhouette score) для оценки кластеризации",
|
||||
"Визуализация базовая - нет центроидов, которые важны для интерпретации сегментов",
|
||||
"Не выводятся характеристики кластеров (размеры, средние значения признаков)"
|
||||
],
|
||||
"recommendations": [
|
||||
"Добавить цикл по k в range(2, 11) с вычислением silhouette_score для каждого k",
|
||||
"Выбирать оптимальное k как argmax(silhouette_scores) или по методу локтя (elbow на inertia)",
|
||||
"Визуализировать центроиды кластеров для лучшей интерпретации сегментов",
|
||||
"Вывести silhouette score финальной модели для оценки качества разделения",
|
||||
"Добавить анализ размеров кластеров (np.bincount) для проверки сбалансированности сегментов"
|
||||
],
|
||||
"detailed_analysis": "Решение демонстрирует понимание основных аспектов задачи кластеризации и правильную реализацию большинства требований. Положительные моменты: корректная нормализация данных (тег DataPreprocessing 20% полностью покрыт), правильное использование sklearn (тег sklearn 30% хорошо покрыт), возврат обученных объектов для production использования.\n\nОднако упущен важный аспект задачи - определение оптимального количества кластеров. Задача явно требовала: 'определить оптимальное количество кластеров (2-10) с помощью метода локтя или силуэта'. Это не опциональная рекомендация, а ключевое требование, показывающее понимание что k - это гиперпараметр, требующий настройки. Выбор k=5 наугад может привести к субоптимальной сегментации.\n\nМетоды определения k:\n- **Метод локтя (elbow)**: график inertia vs k, ищем 'локоть' где улучшение замедляется\n- **Silhouette analysis**: выбираем k с максимальным silhouette score (мера качества кластеризации от -1 до 1)\n\nВизуализация присутствует, но упрощенная - нет центроидов кластеров, которые важны для интерпретации: 'кластер 1 - молодые с низким доходом', 'кластер 2 - состоятельные редкие покупатели' и т.д.\n\nВ целом это решение уровня 6-7/10 - работает, покрывает большинство требований, но упускает ключевой аспект автоматического подбора гиперпараметров. Для полноценного соответствия задаче необходимо добавить подбор оптимального k."
|
||||
}
|
||||
},
|
||||
{
|
||||
"solution": {
|
||||
"code": "from sklearn.cluster import DBSCAN\nfrom sklearn.preprocessing import StandardScaler\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n\ndef segment_customers(X, eps=0.5, min_samples=5):\n # Нормализация\n scaler = StandardScaler()\n X_scaled = scaler.fit_transform(X)\n \n # DBSCAN вместо K-Means\n model = DBSCAN(eps=eps, min_samples=min_samples)\n clusters = model.fit_predict(X_scaled)\n \n n_clusters = len(set(clusters)) - (1 if -1 in clusters else 0)\n n_noise = list(clusters).count(-1)\n \n print(f\"Кластеров найдено: {n_clusters}\")\n print(f\"Выбросов: {n_noise}\")\n \n # Визуализация\n plt.figure(figsize=(10, 6))\n plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=clusters, cmap='viridis', alpha=0.6)\n plt.title(f'DBSCAN Clustering (clusters: {n_clusters})')\n plt.colorbar(label='Cluster')\n plt.show()\n \n return model, scaler\n",
|
||||
"success": true
|
||||
},
|
||||
"analysis": {
|
||||
"summary": "Решение использует DBSCAN - другой алгоритм кластеризации, чем требовалось. Задача явно требовала K-Means, но реализован density-based подход. Это хорошее решение для другой задачи, но не соответствует требованиям.",
|
||||
"task_compliance": {
|
||||
"is_relevant": "partially",
|
||||
"score": 5,
|
||||
"description": "Решение выполняет кластеризацию и покрывает некоторые требования (нормализация, визуализация), но использует неправильный алгоритм. Задача требовала K-Means, а реализован DBSCAN.",
|
||||
"tag_alignment": {
|
||||
"Clustering": {
|
||||
"required_weight": 0.50,
|
||||
"applied": true,
|
||||
"score": 5,
|
||||
"evidence": "Выполнена кластеризация, но использован DBSCAN вместо требуемого K-Means. Это разные подходы: K-Means - partition-based (делит данные на k групп), DBSCAN - density-based (находит области высокой плотности). Задача явно указывала 'выполняет кластеризацию методом K-Means' - это не рекомендация, а требование. DBSCAN имеет преимущества (находит выбросы, не требует указывать k заранее), но в данном случае студент должен был продемонстрировать знание именно K-Means. Также отсутствует ключевое требование - определение оптимального k в диапазоне 2-10, которое неприменимо к DBSCAN."
|
||||
},
|
||||
"sklearn": {
|
||||
"required_weight": 0.30,
|
||||
"applied": true,
|
||||
"score": 8,
|
||||
"evidence": "Хорошее владение sklearn продемонстрировано: корректное использование DBSCAN из sklearn.cluster, правильная работа со StandardScaler, понимание особенностей DBSCAN (метки -1 для выбросов). Код следует практикам библиотеки, возвращаются обученные объекты. Однако выбран неподходящий класс - нужен был KMeans, а не DBSCAN. Это показывает знание sklearn, но непонимание или игнорирование требований задачи."
|
||||
},
|
||||
"DataPreprocessing": {
|
||||
"required_weight": 0.20,
|
||||
"applied": true,
|
||||
"score": 9,
|
||||
"evidence": "Нормализация выполнена корректно через StandardScaler - это обязательное требование задачи полностью соблюдено. Использован правильный подход с fit_transform, scaler возвращается для применения на новых данных. DBSCAN также требует нормализации (чувствителен к масштабу при вычислении eps-окрестностей), поэтому предобработка выполнена правильно для выбранного алгоритма."
|
||||
}
|
||||
},
|
||||
"missing_requirements": [
|
||||
"ВАЖНО: Использован DBSCAN вместо требуемого K-Means",
|
||||
"Невозможно определить оптимальное k (2-10) - DBSCAN сам определяет количество кластеров",
|
||||
"Не применены методы локтя или силуэта (они специфичны для K-Means)",
|
||||
"Нет визуализации центроидов (у DBSCAN нет концепции центроидов)"
|
||||
],
|
||||
"extra_features": [
|
||||
"Автоматическое определение количества кластеров",
|
||||
"Детектирование выбросов (шумовые точки)",
|
||||
"Вывод статистики по кластерам и выбросам"
|
||||
]
|
||||
},
|
||||
"code_quality_score": 7.5,
|
||||
"correctness": {
|
||||
"is_correct": "partially",
|
||||
"score": 5,
|
||||
"edge_cases_handled": true
|
||||
},
|
||||
"Временная сложность решения": {
|
||||
"time_complexity": "O(n²) или O(n log n) с индексацией",
|
||||
"space_complexity": "O(n²) или O(n) с индексацией",
|
||||
"efficiency": "низкая-средняя",
|
||||
"explanation": "DBSCAN имеет сложность O(n²) в naive реализации, O(n log n) с пространственными индексами (KD-tree). Медленнее чем K-Means."
|
||||
},
|
||||
"strengths": [
|
||||
"Код качественный и работает без ошибок",
|
||||
"Правильная нормализация данных через StandardScaler",
|
||||
"DBSCAN хорошо реализован - обработка выбросов, вывод статистики",
|
||||
"Визуализация информативная с подписями",
|
||||
"Возврат модели и scaler для применения на новых данных",
|
||||
"Автоматическое определение количества кластеров (преимущество DBSCAN)"
|
||||
],
|
||||
"weaknesses": [
|
||||
"КЛЮЧЕВАЯ ПРОБЛЕМА: Использован DBSCAN вместо K-Means - требование задачи не выполнено",
|
||||
"Невозможно продемонстрировать навык определения оптимального k методом локтя/силуэта",
|
||||
"Параметры eps и min_samples выбраны произвольно (0.5 и 5) без настройки",
|
||||
"DBSCAN может найти любое количество кластеров, не обязательно в диапазоне 2-10 как требовалось",
|
||||
"Результаты кластеризации могут сильно отличаться от K-Means"
|
||||
],
|
||||
"recommendations": [
|
||||
"ОБЯЗАТЕЛЬНО: Заменить DBSCAN на KMeans для соответствия требованиям задачи",
|
||||
"Реализовать подбор оптимального k в диапазоне 2-10 методом силуэта или локтя",
|
||||
"DBSCAN можно использовать как дополнительный анализ ПОСЛЕ выполнения основной задачи с K-Means",
|
||||
"Если хотите использовать DBSCAN, подберите оптимальные eps и min_samples (например, через k-distance graph)",
|
||||
"Внимательно читать требования задачи - 'метод K-Means' это конкретное указание, а не предложение"
|
||||
],
|
||||
"detailed_analysis": "Решение демонстрирует хорошее знание алгоритмов кластеризации и качественную реализацию, но страдает от критической проблемы - несоответствия требованиям. Задача явно указывала 'выполняет кластеризацию методом K-Means' и 'определить оптимальное количество кластеров (2-10)', что специфично для K-Means подхода.\n\nDBSCAN (Density-Based Spatial Clustering of Applications with Noise) - это другой тип алгоритма:\n- **K-Means**: partition-based, требует указать k заранее, присваивает все точки кластерам, ищет центроиды\n- **DBSCAN**: density-based, автоматически определяет количество кластеров, может маркировать точки как выбросы, находит области высокой плотности\n\nDBSCAN имеет преимущества (находит кластеры произвольной формы, устойчив к выбросам), но в образовательном контексте важно продемонстрировать знание именно того алгоритма, который требуется. Использование DBSCAN показывает широкий кругозор, но также игнорирование конкретных требований.\n\nАналогия: если на экзамене по физике требуется решить задачу законом Ньютона, а студент использует лагранжев формализм - технически правильно и даже более продвинуто, но требование не выполнено.\n\nРекомендация: реализовать K-Means как требует задача, а DBSCAN можно использовать как дополнительный сравнительный анализ. Это продемонстрирует и выполнение требований, и широту знаний."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
161
README.md
Normal file
161
README.md
Normal file
@@ -0,0 +1,161 @@
|
||||
---
|
||||
library_name: transformers
|
||||
license: apache-2.0
|
||||
base_model: Qwen/Qwen2.5-Coder-3B-Instruct
|
||||
pipeline_tag: text-generation
|
||||
inference: true
|
||||
tags:
|
||||
- code
|
||||
- code-analysis
|
||||
- qwen
|
||||
- qwen2
|
||||
- text-generation
|
||||
- transformers
|
||||
- fine-tuned
|
||||
widget:
|
||||
- text: "Задача:\nНапишите функцию, которая принимает список чисел и возвращает сумму всех элементов.\n\nРешение (код):\n```python\ndef sum_list(numbers):\n total = 0\n for num in numbers:\n total += num\n return total\n```\n\nОтвет:\n"
|
||||
example_title: "Анализ кода - сумма списка"
|
||||
- text: "Задача:\nСоздайте функцию для вычисления факториала числа.\n\nРешение (код):\n```python\ndef factorial(n):\n if n <= 1:\n return 1\n return n * factorial(n-1)\n```\n\nОтвет:\n"
|
||||
example_title: "Анализ кода - факториал"
|
||||
---
|
||||
|
||||
# Code Analyzer Model
|
||||
|
||||
Fine-tuned версия модели Qwen2.5-Coder-3B-Instruct для анализа кода студента на основе условия задачи (for Machine Learning tasks).
|
||||
|
||||
## Описание модели
|
||||
|
||||
Эта модель предназнаечена для анализа кода студента. Модель принимает:
|
||||
- **Условие задачи** (текстовое описание)
|
||||
- **Код решения студента** (Python код)
|
||||
|
||||
И возвращает детальный анализ в формате JSON, включающий:
|
||||
- Оценку правильности решения
|
||||
- Анализ соответствия требованиям задачи
|
||||
- Оценку качества кода
|
||||
- Сильные и слабые стороны решения
|
||||
- Рекомендации по улучшению
|
||||
- Детальный анализ с обоснованием
|
||||
|
||||
Модель основана на Qwen2.5-Coder-3B-Instruct и дообучена с использованием LoRA (Low-Rank Adaptation).
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
### Вариант 1: Использование локально (Python)
|
||||
|
||||
**Установка зависимостей:**
|
||||
```bash
|
||||
pip install transformers torch
|
||||
```
|
||||
|
||||
**Простой пример использования:**
|
||||
```python
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||||
import torch
|
||||
import json
|
||||
|
||||
model_name = "Vilyam888/Code_analyze.1.0"
|
||||
|
||||
# Загрузка модели
|
||||
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
|
||||
model = AutoModelForCausalLM.from_pretrained(
|
||||
model_name,
|
||||
torch_dtype=torch.bfloat16,
|
||||
device_map="auto",
|
||||
trust_remote_code=True
|
||||
)
|
||||
|
||||
# Условие задачи
|
||||
task = "Напишите функцию, которая принимает список чисел и возвращает сумму всех элементов."
|
||||
|
||||
# Код студента
|
||||
code = """def sum_list(numbers):
|
||||
total = 0
|
||||
for num in numbers:
|
||||
total += num
|
||||
return total"""
|
||||
|
||||
# Форматирование входа
|
||||
input_text = f"Задача:\n{task}\n\nРешение (код):\n```python\n{code}\n```"
|
||||
prompt = f"{input_text}\n\nОтвет:\n"
|
||||
|
||||
# Генерация анализа
|
||||
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
|
||||
with torch.no_grad():
|
||||
outputs = model.generate(
|
||||
**inputs,
|
||||
max_new_tokens=1024,
|
||||
temperature=0.7,
|
||||
top_p=0.8,
|
||||
top_k=20,
|
||||
repetition_penalty=1.05,
|
||||
do_sample=True
|
||||
)
|
||||
|
||||
# Декодирование и парсинг JSON
|
||||
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
||||
result = response.split("Ответ:")[-1].strip()
|
||||
analysis = json.loads(result)
|
||||
|
||||
print(json.dumps(analysis, ensure_ascii=False, indent=2))
|
||||
```
|
||||
|
||||
**Или используйте готовые скрипты из репозитория:**
|
||||
|
||||
Простой пример (минимальный код):
|
||||
```bash
|
||||
python scripts/quick_start_example.py
|
||||
```
|
||||
|
||||
Полный пример с интерактивным режимом:
|
||||
```bash
|
||||
python scripts/use_model_example.py
|
||||
```
|
||||
|
||||
|
||||
## Детали обучения
|
||||
|
||||
- **Базовая модель:** Qwen/Qwen2.5-Coder-3B-Instruct
|
||||
- **Метод обучения:** LoRA (Low-Rank Adaptation)
|
||||
- **Параметры LoRA:**
|
||||
- `r`: 16
|
||||
- `lora_alpha`: 32
|
||||
- `lora_dropout`: 0.05
|
||||
- **Фреймворк:** TRL (Transformer Reinforcement Learning)
|
||||
- **Формат данных:** JSONL с полями `input` и `output`
|
||||
|
||||
## Ограничения
|
||||
|
||||
- Модель обучена на русском языке для анализа кода
|
||||
- Может генерировать неточные или неполные ответы
|
||||
- Требует GPU для эффективной работы
|
||||
|
||||
## Использование через API
|
||||
|
||||
Модель можно использовать через несколько способов:
|
||||
|
||||
### 1. Через transformers (Python)
|
||||
```python
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||||
```
|
||||
|
||||
### 2. Через Hugging Face Inference API
|
||||
```python
|
||||
import requests
|
||||
API_URL = "https://api-inference.huggingface.co/models/Vilyam888/Code_analyze.1.0"
|
||||
```
|
||||
|
||||
### 3. Через Gradio Space API
|
||||
Если создан Gradio Space, можно использовать его API endpoint.
|
||||
|
||||
### 4. Интеграция в Backend проект
|
||||
Примеры для FastAPI, Flask, Django, Node.js и других фреймворков.
|
||||
|
||||
|
||||
## Лицензия
|
||||
|
||||
Apache 2.0
|
||||
|
||||
## Авторы
|
||||
|
||||
Fine-tuned by Vilyam888
|
||||
187
app.py
Normal file
187
app.py
Normal file
@@ -0,0 +1,187 @@
|
||||
"""
|
||||
Gradio Space для интерактивного использования модели Code Analyzer
|
||||
Модель анализирует код студента на основе условия задачи
|
||||
Поддерживает как веб-интерфейс, так и API endpoint
|
||||
"""
|
||||
import gradio as gr
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||||
import torch
|
||||
import json
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
# Загрузка модели (будет выполнена при первом запуске)
|
||||
MODEL_NAME = "Vilyam888/Code_analyze.1.0"
|
||||
|
||||
def load_model():
|
||||
"""Загружает модель один раз при старте и сохраняет в глобальные переменные"""
|
||||
global model, tokenizer
|
||||
|
||||
if model is None or tokenizer is None:
|
||||
print("Загрузка модели...")
|
||||
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
|
||||
model = AutoModelForCausalLM.from_pretrained(
|
||||
MODEL_NAME,
|
||||
torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
|
||||
device_map="auto",
|
||||
trust_remote_code=True
|
||||
)
|
||||
print("Модель загружена успешно!")
|
||||
|
||||
# Глобальные переменные для модели
|
||||
model, tokenizer = None, None
|
||||
|
||||
def build_input(task, code):
|
||||
"""Форматирует вход в том же формате, что использовался при обучении"""
|
||||
parts = []
|
||||
if task.strip():
|
||||
parts.append(f"Задача:\n{task.strip()}")
|
||||
if code.strip():
|
||||
parts.append(f"Решение (код):\n```python\n{code.strip()}\n```")
|
||||
return "\n\n".join(parts)
|
||||
|
||||
def analyze_code(task, code):
|
||||
"""Анализирует код студента и возвращает результат в формате JSON"""
|
||||
global model, tokenizer
|
||||
|
||||
if model is None or tokenizer is None:
|
||||
return "⏳ Загрузка модели... Пожалуйста, подождите."
|
||||
|
||||
if not task.strip():
|
||||
return "❌ Пожалуйста, введите условие задачи."
|
||||
|
||||
if not code.strip():
|
||||
return "❌ Пожалуйста, введите код решения студента."
|
||||
|
||||
try:
|
||||
# Форматирование входа в стиле обучения
|
||||
input_text = build_input(task, code)
|
||||
prompt = f"{input_text}\n\nОтвет:\n"
|
||||
|
||||
# Токенизация
|
||||
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
|
||||
|
||||
# Генерация ответа
|
||||
with torch.no_grad():
|
||||
outputs = model.generate(
|
||||
**inputs,
|
||||
max_new_tokens=600, # Оптимизировано для CPU
|
||||
temperature=0.7,
|
||||
top_p=0.85,
|
||||
top_k=20,
|
||||
repetition_penalty=1.05,
|
||||
do_sample=True,
|
||||
pad_token_id=tokenizer.eos_token_id,
|
||||
eos_token_id=tokenizer.eos_token_id
|
||||
)
|
||||
|
||||
# Декодирование ответа
|
||||
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
||||
|
||||
# Извлечение JSON ответа
|
||||
if "Ответ:" in response:
|
||||
json_str = response.split("Ответ:")[-1].strip()
|
||||
else:
|
||||
json_str = response
|
||||
|
||||
# Попытка распарсить JSON
|
||||
try:
|
||||
result = json.loads(json_str)
|
||||
# Форматируем JSON для красивого отображения
|
||||
return json.dumps(result, ensure_ascii=False, indent=2)
|
||||
except json.JSONDecodeError:
|
||||
# Если не JSON, возвращаем как есть
|
||||
return json_str
|
||||
|
||||
except Exception as e:
|
||||
return f"❌ Ошибка: {str(e)}"
|
||||
|
||||
# Создание Gradio интерфейса
|
||||
with gr.Blocks(title="Code Analyzer Model") as demo:
|
||||
gr.Markdown("""
|
||||
# 🔍 Code Analyzer Model
|
||||
|
||||
Модель для анализа кода студента на основе условия задачи.
|
||||
|
||||
**Как использовать:**
|
||||
1. Введите условие задачи в первое поле
|
||||
2. Введите код решения студента во второе поле
|
||||
3. Нажмите "Анализировать код"
|
||||
4. Получите детальный анализ в формате JSON
|
||||
|
||||
**API Endpoint:** `/api/predict` - используйте для интеграции в другие проекты
|
||||
""")
|
||||
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
task_input = gr.Textbox(
|
||||
label="Условие задачи",
|
||||
placeholder="Введите условие задачи...",
|
||||
lines=5
|
||||
)
|
||||
code_input = gr.Textbox(
|
||||
label="Код решения студента",
|
||||
placeholder="Введите код решения...",
|
||||
lines=10
|
||||
)
|
||||
submit_btn = gr.Button("Анализировать код", variant="primary", size="lg")
|
||||
|
||||
with gr.Column():
|
||||
result_output = gr.JSON(
|
||||
label="Результат анализа"
|
||||
)
|
||||
# Также показываем как текст для удобства копирования
|
||||
result_text = gr.Textbox(
|
||||
label="Результат (JSON текст)",
|
||||
lines=15,
|
||||
interactive=False
|
||||
)
|
||||
|
||||
# Примеры
|
||||
gr.Examples(
|
||||
examples=[
|
||||
[
|
||||
"Напишите функцию, которая принимает список чисел и возвращает сумму всех элементов.",
|
||||
"def sum_list(numbers):\n total = 0\n for num in numbers:\n total += num\n return total"
|
||||
],
|
||||
[
|
||||
"Создайте функцию для вычисления факториала числа.",
|
||||
"def factorial(n):\n if n <= 1:\n return 1\n return n * factorial(n-1)"
|
||||
],
|
||||
],
|
||||
inputs=[task_input, code_input]
|
||||
)
|
||||
|
||||
def analyze_and_format(task, code):
|
||||
"""Анализирует код и форматирует результат"""
|
||||
result_str = analyze_code(task, code)
|
||||
try:
|
||||
result_json = json.loads(result_str)
|
||||
return result_json, result_str
|
||||
except:
|
||||
return None, result_str
|
||||
|
||||
# Загрузка модели при старте
|
||||
demo.load(load_model, outputs=None)
|
||||
|
||||
# Обработчик кнопки
|
||||
submit_btn.click(
|
||||
fn=analyze_and_format,
|
||||
inputs=[task_input, code_input],
|
||||
outputs=[result_output, result_text]
|
||||
)
|
||||
|
||||
# Обработчик Enter в поле кода
|
||||
code_input.submit(
|
||||
fn=analyze_and_format,
|
||||
inputs=[task_input, code_input],
|
||||
outputs=[result_output, result_text]
|
||||
)
|
||||
|
||||
# Gradio автоматически создает API endpoint на /api/predict
|
||||
# Для использования из других проектов:
|
||||
# POST https://YOUR_SPACE_URL.hf.space/api/predict
|
||||
# Body: {"data": ["task", "code"]}
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch(theme=gr.themes.Soft(), server_name="0.0.0.0")
|
||||
54
chat_template.jinja
Normal file
54
chat_template.jinja
Normal file
@@ -0,0 +1,54 @@
|
||||
{%- if tools %}
|
||||
{{- '<|im_start|>system\n' }}
|
||||
{%- if messages[0]['role'] == 'system' %}
|
||||
{{- messages[0]['content'] }}
|
||||
{%- else %}
|
||||
{{- 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.' }}
|
||||
{%- endif %}
|
||||
{{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
|
||||
{%- for tool in tools %}
|
||||
{{- "\n" }}
|
||||
{{- tool | tojson }}
|
||||
{%- endfor %}
|
||||
{{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
|
||||
{%- else %}
|
||||
{%- if messages[0]['role'] == 'system' %}
|
||||
{{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }}
|
||||
{%- else %}
|
||||
{{- '<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\n' }}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- for message in messages %}
|
||||
{%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %}
|
||||
{{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
|
||||
{%- elif message.role == "assistant" %}
|
||||
{{- '<|im_start|>' + message.role }}
|
||||
{%- if message.content %}
|
||||
{{- '\n' + message.content }}
|
||||
{%- endif %}
|
||||
{%- for tool_call in message.tool_calls %}
|
||||
{%- if tool_call.function is defined %}
|
||||
{%- set tool_call = tool_call.function %}
|
||||
{%- endif %}
|
||||
{{- '\n<tool_call>\n{"name": "' }}
|
||||
{{- tool_call.name }}
|
||||
{{- '", "arguments": ' }}
|
||||
{{- tool_call.arguments | tojson }}
|
||||
{{- '}\n</tool_call>' }}
|
||||
{%- endfor %}
|
||||
{{- '<|im_end|>\n' }}
|
||||
{%- elif message.role == "tool" %}
|
||||
{%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %}
|
||||
{{- '<|im_start|>user' }}
|
||||
{%- endif %}
|
||||
{{- '\n<tool_response>\n' }}
|
||||
{{- message.content }}
|
||||
{{- '\n</tool_response>' }}
|
||||
{%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
|
||||
{{- '<|im_end|>\n' }}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{%- if add_generation_prompt %}
|
||||
{{- '<|im_start|>assistant\n' }}
|
||||
{%- endif %}
|
||||
69
config.json
Normal file
69
config.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"architectures": [
|
||||
"Qwen2ForCausalLM"
|
||||
],
|
||||
"attention_dropout": 0.0,
|
||||
"bos_token_id": 151643,
|
||||
"dtype": "bfloat16",
|
||||
"eos_token_id": 151645,
|
||||
"hidden_act": "silu",
|
||||
"hidden_size": 2048,
|
||||
"initializer_range": 0.02,
|
||||
"intermediate_size": 11008,
|
||||
"layer_types": [
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention",
|
||||
"full_attention"
|
||||
],
|
||||
"max_position_embeddings": 32768,
|
||||
"max_window_layers": 36,
|
||||
"model_type": "qwen2",
|
||||
"num_attention_heads": 16,
|
||||
"num_hidden_layers": 36,
|
||||
"num_key_value_heads": 2,
|
||||
"pad_token_id": null,
|
||||
"rms_norm_eps": 1e-06,
|
||||
"rope_parameters": {
|
||||
"rope_theta": 1000000.0,
|
||||
"rope_type": "default"
|
||||
},
|
||||
"sliding_window": null,
|
||||
"tie_word_embeddings": true,
|
||||
"transformers_version": "5.0.0",
|
||||
"use_cache": true,
|
||||
"use_sliding_window": false,
|
||||
"vocab_size": 151936
|
||||
}
|
||||
14
generation_config.json
Normal file
14
generation_config.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"bos_token_id": 151643,
|
||||
"do_sample": true,
|
||||
"eos_token_id": [
|
||||
151645,
|
||||
151643
|
||||
],
|
||||
"pad_token_id": 151643,
|
||||
"repetition_penalty": 1.05,
|
||||
"temperature": 0.7,
|
||||
"top_k": 20,
|
||||
"top_p": 0.8,
|
||||
"transformers_version": "5.0.0"
|
||||
}
|
||||
99
inference.py
Normal file
99
inference.py
Normal file
@@ -0,0 +1,99 @@
|
||||
"""
|
||||
Inference code for Code Analyzer Model
|
||||
This file enables the "Use this model" button on Hugging Face.
|
||||
"""
|
||||
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||||
import torch
|
||||
|
||||
|
||||
def load_model_and_tokenizer(model_name: str):
|
||||
"""Load model and tokenizer"""
|
||||
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
|
||||
model = AutoModelForCausalLM.from_pretrained(
|
||||
model_name,
|
||||
torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
|
||||
device_map="auto",
|
||||
trust_remote_code=True
|
||||
)
|
||||
return model, tokenizer
|
||||
|
||||
|
||||
def build_input(task, code):
|
||||
"""Build input in the same format as used during training"""
|
||||
parts = []
|
||||
if task.strip():
|
||||
parts.append(f"Задача:\n{task.strip()}")
|
||||
if code.strip():
|
||||
parts.append(f"Решение (код):\n```python\n{code.strip()}\n```")
|
||||
return "\n\n".join(parts)
|
||||
|
||||
|
||||
def generate_response(
|
||||
model,
|
||||
tokenizer,
|
||||
task: str,
|
||||
code: str,
|
||||
max_new_tokens: int = 1024,
|
||||
temperature: float = 0.7,
|
||||
top_p: float = 0.8,
|
||||
top_k: int = 20,
|
||||
repetition_penalty: float = 1.05,
|
||||
):
|
||||
"""Generate analysis response for task and student code"""
|
||||
# Format input in training style
|
||||
input_text = build_input(task, code)
|
||||
prompt = f"{input_text}\n\nОтвет:\n"
|
||||
|
||||
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
|
||||
|
||||
with torch.no_grad():
|
||||
outputs = model.generate(
|
||||
**inputs,
|
||||
max_new_tokens=max_new_tokens,
|
||||
temperature=temperature,
|
||||
top_p=top_p,
|
||||
top_k=top_k,
|
||||
repetition_penalty=repetition_penalty,
|
||||
do_sample=True,
|
||||
pad_token_id=tokenizer.eos_token_id
|
||||
)
|
||||
|
||||
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
||||
# Extract only the answer part
|
||||
if "Ответ:" in response:
|
||||
response = response.split("Ответ:")[-1].strip()
|
||||
|
||||
return response
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
import json
|
||||
|
||||
model_name = "Vilyam888/Code_analyze.1.0"
|
||||
|
||||
print("Loading model...")
|
||||
model, tokenizer = load_model_and_tokenizer(model_name)
|
||||
|
||||
# Example: task and student code
|
||||
task = "Напишите функцию, которая принимает список чисел и возвращает сумму всех элементов."
|
||||
code = """def sum_list(numbers):
|
||||
total = 0
|
||||
for num in numbers:
|
||||
total += num
|
||||
return total"""
|
||||
|
||||
print(f"\nЗадача: {task}")
|
||||
print(f"\nКод студента:\n{code}\n")
|
||||
print("Generating analysis...")
|
||||
|
||||
response = generate_response(model, tokenizer, task, code)
|
||||
|
||||
# Try to parse as JSON
|
||||
try:
|
||||
result = json.loads(response)
|
||||
print(f"\nРезультат анализа (JSON):")
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
except json.JSONDecodeError:
|
||||
print(f"\nРезультат анализа:\n{response}")
|
||||
21
metrics/01_training_perplexity.json
Normal file
21
metrics/01_training_perplexity.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"metric_group": "training_perplexity",
|
||||
"model": "Code_analyze.1.0",
|
||||
"hf_model": "Vilyam888/Code_analyze.1.0",
|
||||
"base_model": "Qwen/Qwen2.5-Coder-3B-Instruct",
|
||||
"finetuning_method": "LoRA",
|
||||
"base_model_quantization": "none",
|
||||
"inference_dtype": "bfloat16",
|
||||
"checkpoint": "outputs/code-analyze-qlora/checkpoint-222",
|
||||
"source": "outputs/code-analyze-qlora/checkpoint-222/trainer_state.json",
|
||||
"validation_file": "prepared_data/code_analyze/val.jsonl",
|
||||
"evaluation_date": "2026-06-11",
|
||||
"metrics": {
|
||||
"train_loss_final": 0.241,
|
||||
"eval_loss_final": 0.2776,
|
||||
"eval_mean_token_accuracy": 0.925,
|
||||
"perplexity_validation": 1.32,
|
||||
"num_train_epochs": 2,
|
||||
"global_step": 222
|
||||
}
|
||||
}
|
||||
37
metrics/02_json_validity.json
Normal file
37
metrics/02_json_validity.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"metric_group": "json_validity",
|
||||
"model": "Code_analyze.1.0",
|
||||
"hf_model": "Vilyam888/Code_analyze.1.0",
|
||||
"evaluation_file": "prepared_data/code_analyze/test.jsonl",
|
||||
"evaluation_date": "2026-06-11",
|
||||
"samples_evaluated": 100,
|
||||
"generation_params": {
|
||||
"temperature": 0.2,
|
||||
"top_p": 0.95,
|
||||
"max_new_tokens": 2048,
|
||||
"seed": 42
|
||||
},
|
||||
"required_fields": [
|
||||
"summary",
|
||||
"tags",
|
||||
"suggested_tags",
|
||||
"overall_score",
|
||||
"code_quality_score",
|
||||
"correctness",
|
||||
"task_compliance",
|
||||
"strengths",
|
||||
"weaknesses",
|
||||
"recommendations",
|
||||
"detailed_analysis"
|
||||
],
|
||||
"metrics": {
|
||||
"valid_json_rate": 0.93,
|
||||
"required_fields_rate": 0.9,
|
||||
"tag_name_match_rate": 0.88
|
||||
},
|
||||
"metrics_counts": {
|
||||
"valid_json": 93,
|
||||
"required_fields_complete": 90,
|
||||
"tag_name_match": 88
|
||||
}
|
||||
}
|
||||
26
metrics/03_bleu_rouge.json
Normal file
26
metrics/03_bleu_rouge.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"metric_group": "bleu_rouge",
|
||||
"model": "Code_analyze.1.0",
|
||||
"hf_model": "Vilyam888/Code_analyze.1.0",
|
||||
"evaluation_file": "prepared_data/code_analyze/test.jsonl",
|
||||
"evaluation_date": "2026-06-11",
|
||||
"text_fields": [
|
||||
"summary",
|
||||
"detailed_analysis",
|
||||
"recommendations"
|
||||
],
|
||||
"pairs_evaluated": 93,
|
||||
"generation_params": {
|
||||
"temperature": 0.2,
|
||||
"top_p": 0.95,
|
||||
"max_new_tokens": 2048,
|
||||
"seed": 42
|
||||
},
|
||||
"metrics": {
|
||||
"bleu4_corpus": 0.7,
|
||||
"bleu4_summary": 0.72,
|
||||
"rouge1_f1": 0.71,
|
||||
"rouge2_f1": 0.56,
|
||||
"rougeL_f1": 0.69
|
||||
}
|
||||
}
|
||||
7
metrics/04_code_metrics.json
Normal file
7
metrics/04_code_metrics.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"metric_group": "code_metrics",
|
||||
"model": "Code_analyze.1.0",
|
||||
"status": "not_applicable",
|
||||
"reason": "Модель генерирует JSON-анализ кода; метрика CodeBLEU не входит в протокол оценки.",
|
||||
"metrics": {}
|
||||
}
|
||||
37
metrics/README.md
Normal file
37
metrics/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Метрики оценки Code_analyze.1.0
|
||||
|
||||
Автоматическая оценка дообученной модели [Vilyam888/Code_analyze.1.0](https://huggingface.co/Vilyam888/Code_analyze.1.0) на hold-out выборке.
|
||||
|
||||
## Протокол оценки
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Базовая модель | Qwen/Qwen2.5-Coder-3B-Instruct |
|
||||
| Метод дообучения | LoRA (без 4-bit квантизации), 2 эпохи, checkpoint-222 |
|
||||
| Инференс | bfloat16, merged-модель |
|
||||
| Тестовая выборка | `prepared_data/code_analyze/test.jsonl`, N = 100 |
|
||||
| Reference | Поля JSON из test split |
|
||||
| Temperature | 0.2 |
|
||||
| max_new_tokens | 2048 |
|
||||
|
||||
## Итоговые метрики
|
||||
|
||||
| Метрика | Значение |
|
||||
|---------|----------|
|
||||
| Perplexity (validation) | **1.32** |
|
||||
| valid_json_rate | **93 %** |
|
||||
| required_fields_rate | **90 %** |
|
||||
| tag_name_match_rate | **88 %** |
|
||||
| BLEU-4 (corpus) | **0.70** |
|
||||
| ROUGE-L F1 | **0.69** |
|
||||
| CodeBLEU | не применяется |
|
||||
|
||||
## Файлы
|
||||
|
||||
- `evaluation_report.json` / `evaluation_report.txt` — сводный отчёт
|
||||
- `01_training_perplexity.json` — метрики обучения (loss, PPL)
|
||||
- `02_json_validity.json` — валидность и полнота JSON
|
||||
- `03_bleu_rouge.json` — BLEU и ROUGE по текстовым полям
|
||||
- `04_code_metrics.json` — пояснение по CodeBLEU
|
||||
|
||||
Human Evaluation в протокол оценки данной модели **не входит**.
|
||||
35
metrics/evaluation_report.json
Normal file
35
metrics/evaluation_report.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"title": "Отчёт об оценке модели Code_analyze.1.0",
|
||||
"model": "Code_analyze.1.0",
|
||||
"hf_model": "Vilyam888/Code_analyze.1.0",
|
||||
"base_model": "Qwen/Qwen2.5-Coder-3B-Instruct",
|
||||
"finetuning_method": "LoRA",
|
||||
"base_model_quantization": "none",
|
||||
"inference_dtype": "bfloat16",
|
||||
"evaluation_date": "2026-06-11",
|
||||
"evaluation_sample": "test.jsonl, N = 100",
|
||||
"reference_split": "hold-out test",
|
||||
"generation": {
|
||||
"temperature": 0.2,
|
||||
"max_new_tokens": 2048
|
||||
},
|
||||
"training": {
|
||||
"train_loss_final": 0.241,
|
||||
"eval_loss_final": 0.2776,
|
||||
"eval_mean_token_accuracy": 0.925,
|
||||
"perplexity_validation": 1.32,
|
||||
"num_train_epochs": 2,
|
||||
"global_step": 222
|
||||
},
|
||||
"generation_metrics": {
|
||||
"valid_json_rate": 0.93,
|
||||
"required_fields_rate": 0.9,
|
||||
"tag_name_match_rate": 0.88,
|
||||
"bleu4_corpus": 0.7,
|
||||
"bleu4_summary": 0.72,
|
||||
"rouge1_f1": 0.71,
|
||||
"rouge2_f1": 0.56,
|
||||
"rougeL_f1": 0.69,
|
||||
"codebleu_status": "not_applicable"
|
||||
}
|
||||
}
|
||||
33
metrics/evaluation_report.txt
Normal file
33
metrics/evaluation_report.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
ОТЧЁТ ОБ ОЦЕНКЕ МОДЕЛИ Code_analyze.1.0
|
||||
Репозиторий: Vilyam888/Code_analyze.1.0
|
||||
Базовая модель: Qwen/Qwen2.5-Coder-3B-Instruct
|
||||
Метод дообучения: LoRA (без 4-bit квантизации)
|
||||
Инференс: bfloat16, merged-модель
|
||||
Дата оценки: 2026-06-11
|
||||
Выборка: test.jsonl, N = 100 (hold-out test)
|
||||
Генерация: temperature = 0.2, max_new_tokens = 2048
|
||||
|
||||
1. Perplexity (validation, checkpoint-222):
|
||||
• train_loss_final: 0.241
|
||||
• eval_loss_final: 0.2776
|
||||
• eval_mean_token_accuracy: 0.925
|
||||
• perplexity_validation: 1.32
|
||||
• num_train_epochs: 2
|
||||
• global_step: 222
|
||||
|
||||
2. JSON validity:
|
||||
• valid_json_rate: 0.93
|
||||
• required_fields_rate: 0.9
|
||||
• tag_name_match_rate: 0.88
|
||||
• counts: valid_json=93, required_fields=90, tag_match=88
|
||||
|
||||
3. BLEU:
|
||||
• bleu4_corpus: 0.7
|
||||
• bleu4_summary: 0.72
|
||||
|
||||
4. ROUGE-N:
|
||||
• rouge1_f1: 0.71
|
||||
• rouge2_f1: 0.56
|
||||
• rougeL_f1: 0.69
|
||||
|
||||
5. CodeBLEU: не применяется (модель анализа кода, JSON-выход)
|
||||
3
model.safetensors
Normal file
3
model.safetensors
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1211b3b8d562ad360b2b896a383081b835e769b54d3c2a6fc48b4c3b3a692427
|
||||
size 6171927112
|
||||
7
requirements_gradio.txt
Normal file
7
requirements_gradio.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
gradio>=4.0.0
|
||||
transformers>=5.0.0
|
||||
torch>=2.0.0
|
||||
accelerate
|
||||
sentencepiece
|
||||
fastapi>=0.104.0
|
||||
uvicorn[standard]>=0.24.0
|
||||
3
tokenizer.json
Normal file
3
tokenizer.json
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3fd169731d2cbde95e10bf356d66d5997fd885dd8dbb6fb4684da3f23b2585d8
|
||||
size 11421892
|
||||
29
tokenizer_config.json
Normal file
29
tokenizer_config.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"add_prefix_space": false,
|
||||
"backend": "tokenizers",
|
||||
"bos_token": null,
|
||||
"clean_up_tokenization_spaces": false,
|
||||
"eos_token": "<|im_end|>",
|
||||
"errors": "replace",
|
||||
"extra_special_tokens": [
|
||||
"<|im_start|>",
|
||||
"<|im_end|>",
|
||||
"<|object_ref_start|>",
|
||||
"<|object_ref_end|>",
|
||||
"<|box_start|>",
|
||||
"<|box_end|>",
|
||||
"<|quad_start|>",
|
||||
"<|quad_end|>",
|
||||
"<|vision_start|>",
|
||||
"<|vision_end|>",
|
||||
"<|vision_pad|>",
|
||||
"<|image_pad|>",
|
||||
"<|video_pad|>"
|
||||
],
|
||||
"is_local": false,
|
||||
"model_max_length": 32768,
|
||||
"pad_token": "<|endoftext|>",
|
||||
"split_special_tokens": false,
|
||||
"tokenizer_class": "Qwen2Tokenizer",
|
||||
"unk_token": null
|
||||
}
|
||||
Reference in New Issue
Block a user