{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "9162727d-8a81-4fd9-b3c3-f92cdc1f0d0a",
   "metadata": {},
   "source": [
    "## 1. Описание задачи\n",
    "\n",
    "**Цель**: Демонстрация классификации рукописных цифр с использованием SVM на стандартном датасете scikit-learn.\n",
    "\n",
    "**Алгоритм**: \n",
    "- Support Vector Classifier (SVC) с параметром gamma=0.001\n",
    "- Ядро по умолчанию (RBF)\n",
    "\n",
    "**Источник данных**: \n",
    "- Встроенный датасет `load_digits` (scikit-learn)\n",
    "- 1797 изображений 8×8 пикселей\n",
    "- 10 классов (цифры 0-9)\n",
    "- Значения пикселей: 0-16 (градации серого)\n",
    "\n",
    "## 2. Препроцессинг данных\n",
    "\n",
    "\n",
    "# Загрузка данных\n",
    "digits = datasets.load_digits()\n",
    "\n",
    "# Преобразование изображений в 1D векторы\n",
    "n_samples = len(digits.images)\n",
    "data = digits.images.reshape((n_samples, -1))  # (1797, 64)\n",
    "\n",
    "# Разделение данных (50% train / 50% test)\n",
    "X_train, X_test, y_train, y_test = train_test_split(\n",
    "    data, digits.target, \n",
    "    test_size=0.5, \n",
    "    shuffle=False  # Для воспроизводимости\n",
    ")\n",
    "Особенности:\n",
    "\n",
    "Изображения преобразуются из 8×8 в 64-мерные векторы\n",
    "\n",
    "Тестовая выборка фиксирована (shuffle=False)\n",
    "\n",
    "## 3. Обучение модели\n",
    "\n",
    "# Создание и обучение SVM классификатора\n",
    "clf = svm.SVC(gamma=0.001)  # gamma контролирует влияние каждого примера\n",
    "clf.fit(X_train, y_train)\n",
    "\n",
    "# Предсказание на тестовых данных\n",
    "predicted = clf.predict(X_test)\n",
    "\n",
    "\n",
    "## 4. Визуализация\n",
    "Примеры изображений из обучающей выборки\n",
    "\n",
    "_, axes = plt.subplots(1, 4, figsize=(10, 3))\n",
    "for ax, image, label in zip(axes, digits.images[:4], digits.target[:4]):\n",
    "    ax.set_axis_off()\n",
    "    ax.imshow(image, cmap=plt.cm.gray_r, interpolation=\"nearest\")\n",
    "    ax.set_title(f\"Training: {label}\")\n",
    "    \n",
    "Примеры предсказаний\n",
    "\n",
    "_, axes = plt.subplots(1, 4, figsize=(10, 3))\n",
    "for ax, image, prediction in zip(axes, X_test[:4], predicted[:4]):\n",
    "    ax.set_axis_off()\n",
    "    ax.imshow(image.reshape(8, 8), cmap=plt.cm.gray_r)\n",
    "    ax.set_title(f\"Prediction: {prediction}\")\n",
    "    \n",
    "Матрица ошибок\n",
    "\n",
    "disp = metrics.ConfusionMatrixDisplay.from_predictions(y_test, predicted)\n",
    "disp.figure_.suptitle(\"Confusion Matrix\")\n",
    "plt.show()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "2c07d893-cfbd-4d98-86e1-fd75929a4cab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Classification report for classifier SVC(gamma=0.001):\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       1.00      0.99      0.99        88\n",
      "           1       0.99      0.97      0.98        91\n",
      "           2       0.99      0.99      0.99        86\n",
      "           3       0.98      0.87      0.92        91\n",
      "           4       0.99      0.96      0.97        92\n",
      "           5       0.95      0.97      0.96        91\n",
      "           6       0.99      0.99      0.99        91\n",
      "           7       0.96      0.99      0.97        89\n",
      "           8       0.94      1.00      0.97        88\n",
      "           9       0.93      0.98      0.95        92\n",
      "\n",
      "    accuracy                           0.97       899\n",
      "   macro avg       0.97      0.97      0.97       899\n",
      "weighted avg       0.97      0.97      0.97       899\n",
      "\n",
      "\n",
      "Confusion matrix:\n",
      "[[87  0  0  0  1  0  0  0  0  0]\n",
      " [ 0 88  1  0  0  0  0  0  1  1]\n",
      " [ 0  0 85  1  0  0  0  0  0  0]\n",
      " [ 0  0  0 79  0  3  0  4  5  0]\n",
      " [ 0  0  0  0 88  0  0  0  0  4]\n",
      " [ 0  0  0  0  0 88  1  0  0  2]\n",
      " [ 0  1  0  0  0  0 90  0  0  0]\n",
      " [ 0  0  0  0  0  1  0 88  0  0]\n",
      " [ 0  0  0  0  0  0  0  0 88  0]\n",
      " [ 0  0  0  1  0  1  0  0  0 90]]\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 5820 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 6312 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 37252 characters]",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Classification report rebuilt from confusion matrix:\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       1.00      0.99      0.99        88\n",
      "           1       0.99      0.97      0.98        91\n",
      "           2       0.99      0.99      0.99        86\n",
      "           3       0.98      0.87      0.92        91\n",
      "           4       0.99      0.96      0.97        92\n",
      "           5       0.95      0.97      0.96        91\n",
      "           6       0.99      0.99      0.99        91\n",
      "           7       0.96      0.99      0.97        89\n",
      "           8       0.94      1.00      0.97        88\n",
      "           9       0.93      0.98      0.95        92\n",
      "\n",
      "    accuracy                           0.97       899\n",
      "   macro avg       0.97      0.97      0.97       899\n",
      "weighted avg       0.97      0.97      0.97       899\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Authors: The scikit-learn developers\n",
    "# SPDX-License-Identifier: BSD-3-Clause\n",
    "\n",
    "# Standard scientific Python imports\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Import datasets, classifiers and performance metrics\n",
    "from sklearn import datasets, metrics, svm\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "\n",
    "digits = datasets.load_digits()\n",
    "\n",
    "_, axes = plt.subplots(nrows=1, ncols=4, figsize=(10, 3))\n",
    "for ax, image, label in zip(axes, digits.images, digits.target):\n",
    "    ax.set_axis_off()\n",
    "    ax.imshow(image, cmap=plt.cm.gray_r, interpolation=\"nearest\")\n",
    "    ax.set_title(\"Training: %i\" % label)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "    # flatten the images\n",
    "n_samples = len(digits.images)\n",
    "data = digits.images.reshape((n_samples, -1))\n",
    "\n",
    "# Create a classifier: a support vector classifier\n",
    "clf = svm.SVC(gamma=0.001)\n",
    "\n",
    "# Split data into 50% train and 50% test subsets\n",
    "X_train, X_test, y_train, y_test = train_test_split(\n",
    "    data, digits.target, test_size=0.5, shuffle=False\n",
    ")\n",
    "\n",
    "# Learn the digits on the train subset\n",
    "clf.fit(X_train, y_train)\n",
    "\n",
    "# Predict the value of the digit on the test subset\n",
    "predicted = clf.predict(X_test)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "_, axes = plt.subplots(nrows=1, ncols=4, figsize=(10, 3))\n",
    "for ax, image, prediction in zip(axes, X_test, predicted):\n",
    "    ax.set_axis_off()\n",
    "    image = image.reshape(8, 8)\n",
    "    ax.imshow(image, cmap=plt.cm.gray_r, interpolation=\"nearest\")\n",
    "    ax.set_title(f\"Prediction: {prediction}\")\n",
    "\n",
    "\n",
    "\n",
    "print(\n",
    "    f\"Classification report for classifier {clf}:\\n\"\n",
    "    f\"{metrics.classification_report(y_test, predicted)}\\n\"\n",
    ")\n",
    "\n",
    "\n",
    "\n",
    "disp = metrics.ConfusionMatrixDisplay.from_predictions(y_test, predicted)\n",
    "disp.figure_.suptitle(\"Confusion Matrix\")\n",
    "print(f\"Confusion matrix:\\n{disp.confusion_matrix}\")\n",
    "\n",
    "plt.show()\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# The ground truth and predicted lists\n",
    "y_true = []\n",
    "y_pred = []\n",
    "cm = disp.confusion_matrix\n",
    "\n",
    "# For each cell in the confusion matrix, add the corresponding ground truths\n",
    "# and predictions to the lists\n",
    "for gt in range(len(cm)):\n",
    "    for pred in range(len(cm)):\n",
    "        y_true += [gt] * cm[gt][pred]\n",
    "        y_pred += [pred] * cm[gt][pred]\n",
    "\n",
    "print(\n",
    "    \"Classification report rebuilt from confusion matrix:\\n\"\n",
    "    f\"{metrics.classification_report(y_true, y_pred)}\\n\"\n",
    ")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6ce8169-cd5b-47bb-8016-706a3e34ae82",
   "metadata": {},
   "source": [
    "## 5. Результаты и интерпретация\n",
    "Основные метрики (из classification_report): \n",
    "       precision    recall  f1-score   support\n",
    "\n",
    "           0       1.00      0.99      0.99        88\n",
    "           1       0.99      0.97      0.98        91\n",
    "           2       0.99      0.99      0.99        86\n",
    "           3       0.98      0.87      0.92        91\n",
    "           4       0.99      0.96      0.97        92\n",
    "           5       0.95      0.97      0.96        91\n",
    "           6       0.99      0.99      0.99        91\n",
    "           7       0.96      0.99      0.97        89\n",
    "           8       0.94      1.00      0.97        88\n",
    "           9       0.93      0.98      0.95        92\n",
    "\n",
    "    accuracy                           0.97       899\n",
    "   macro avg       0.97      0.97      0.97       899\n",
    "weighted avg       0.97      0.97      0.97       899\n",
    "\n",
    "Ключевые наблюдения:\n",
    "\n",
    "Общая точность: 97%\n",
    "\n",
    "Наилучшие результаты: цифры 0, 2, 6 (F1 > 0.99)\n",
    "\n",
    "Наибольшие трудности: цифра 3 (recall=0.87)\n",
    "\n",
    "Основные ошибки:\n",
    "\n",
    "3 ↔ 8 (11 случаев)\n",
    "\n",
    "5 ↔ 8 (5 случаев)\n",
    "\n",
    "4 ↔ 9 (4 случая)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "337529ea-b574-4491-8402-7121b267942a",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
