初始化项目,由ModelHub XC社区提供模型

Model: Vilyam888/Code_analyze.1.0
Source: Original Platform
This commit is contained in:
ModelHub XC
2026-06-14 23:21:12 +08:00
commit e742eaaf38
19 changed files with 1401 additions and 0 deletions

36
.gitattributes vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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}")

View 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
}
}

View 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
}
}

View 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
}
}

View 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
View 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 в протокол оценки данной модели **не входит**.

View 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"
}
}

View 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
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1211b3b8d562ad360b2b896a383081b835e769b54d3c2a6fc48b4c3b3a692427
size 6171927112

7
requirements_gradio.txt Normal file
View 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
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3fd169731d2cbde95e10bf356d66d5997fd885dd8dbb6fb4684da3f23b2585d8
size 11421892

29
tokenizer_config.json Normal file
View 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
}