{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "dd36cef2-4feb-44ed-900e-0fa6f75d74bd",
   "metadata": {},
   "source": [
    "**Цель задачи:**  \n",
    "Продемонстрировать применение метода **Comparing anomaly detection algorithms for outlier detection on toy datasets** для обнаружения аномалий в данных на основе их локальной плотности.  \n",
    "\n",
    "1. **Использовать** алгоритм LOF из scikit-learn (`LocalOutlierFactor, IsolationForest, OneClassSVM, EllipticEnvelope.`).  \n",
    "2. **Протестировать** на двух типах данных:  \n",
    "   - **Сгенерированный датасет**: `make_moons` плюс сгенерированные вбросы. \n",
    "   - **Реальный датасет**: annthyroid (аномалии в медицинских данных) из openml.org.  \n",
    "3. **Сравнить** результаты работы алгоритмов (визуализация границ решений для 2D‑случая, метрики классификации), проанализировать, какие типы выбросов лучше обнаруживает каждый метод, и интерпретировать причины различий.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "29f69c7b-93a0-44e6-91c8-b5651e8df0f2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 713328 characters]",
      "text/plain": [
       "<Figure size 1400x1250 with 25 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Сравнение алгоритмов обнаружения аномалий на синтетическом датасете make_moons\n",
    "\n",
    "import time\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "from sklearn import svm\n",
    "from sklearn.covariance import EllipticEnvelope\n",
    "from sklearn.datasets import make_moons\n",
    "from sklearn.ensemble import IsolationForest\n",
    "from sklearn.kernel_approximation import Nystroem\n",
    "from sklearn.linear_model import SGDOneClassSVM\n",
    "from sklearn.neighbors import LocalOutlierFactor\n",
    "from sklearn.pipeline import make_pipeline\n",
    "\n",
    "# Настройки \n",
    "n_samples = 300\n",
    "outliers_fraction = 0.15\n",
    "n_outliers = int(outliers_fraction * n_samples)\n",
    "n_inliers = n_samples - n_outliers\n",
    "\n",
    "# Алгоритмы \n",
    "anomaly_algorithms = [\n",
    "    (\"Robust covariance\", EllipticEnvelope(contamination=outliers_fraction, random_state=42)),\n",
    "    (\"One-Class SVM\", svm.OneClassSVM(nu=outliers_fraction, kernel=\"rbf\", gamma=0.1)),\n",
    "    (\"One-Class SVM (SGD)\", make_pipeline(\n",
    "        Nystroem(gamma=0.1, random_state=42, n_components=150),\n",
    "        SGDOneClassSVM(nu=outliers_fraction, shuffle=True, fit_intercept=True,\n",
    "                       random_state=42, tol=1e-6))),\n",
    "    (\"Isolation Forest\", IsolationForest(contamination=outliers_fraction, random_state=42)),\n",
    "    (\"Local Outlier Factor\", LocalOutlierFactor(n_neighbors=35, contamination=outliers_fraction)),\n",
    "]\n",
    "\n",
    "# Создаём 5 датасетов на основе make_moons\n",
    "blobs_params = dict(random_state=0, n_samples=n_inliers, n_features=2)\n",
    "datasets = []\n",
    "for _ in range(5):\n",
    "    # Генерация inliers: два полумесяца с масштабированием (как в эталоне)\n",
    "    X_inliers, _ = make_moons(n_samples=n_inliers, noise=0.05, random_state=0)\n",
    "    X_inliers = 4.0 * (X_inliers - np.array([0.5, 0.25]))\n",
    "    datasets.append(X_inliers)\n",
    "\n",
    "# Сетка для контуров (как в эталоне)\n",
    "xx, yy = np.meshgrid(np.linspace(-7, 7, 150), np.linspace(-7, 7, 150))\n",
    "\n",
    "plt.figure(figsize=(len(anomaly_algorithms) * 2 + 4, 12.5))\n",
    "plt.subplots_adjust(left=0.02, right=0.98, bottom=0.001, top=0.96, wspace=0.05, hspace=0.01)\n",
    "\n",
    "plot_num = 1\n",
    "rng = np.random.RandomState(42)\n",
    "\n",
    "for i_dataset, X_inliers in enumerate(datasets):\n",
    "    # Добавляем одинаковые выбросы (равномерные) для каждого датасета\n",
    "    X_outliers = rng.uniform(low=-6, high=6, size=(n_outliers, 2))\n",
    "    X = np.concatenate([X_inliers, X_outliers], axis=0)\n",
    "\n",
    "    for name, algorithm in anomaly_algorithms:\n",
    "        t0 = time.time()\n",
    "        if name == \"Local Outlier Factor\":\n",
    "            y_pred = algorithm.fit_predict(X)\n",
    "        else:\n",
    "            algorithm.fit(X)\n",
    "            y_pred = algorithm.predict(X)\n",
    "        t1 = time.time()\n",
    "\n",
    "        plt.subplot(len(datasets), len(anomaly_algorithms), plot_num)\n",
    "        if i_dataset == 0:\n",
    "            plt.title(name, size=18)\n",
    "\n",
    "        # Контур для методов с predict\n",
    "        if name != \"Local Outlier Factor\":\n",
    "            Z = algorithm.predict(np.c_[xx.ravel(), yy.ravel()])\n",
    "            Z = Z.reshape(xx.shape)\n",
    "            plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors=\"black\")\n",
    "\n",
    "        colors = np.array([\"#377eb8\", \"#ff7f00\"])\n",
    "        plt.scatter(X[:, 0], X[:, 1], s=10, color=colors[(y_pred + 1) // 2])\n",
    "\n",
    "        plt.xlim(-7, 7)\n",
    "        plt.ylim(-7, 7)\n",
    "        plt.xticks(())\n",
    "        plt.yticks(())\n",
    "        plt.text(0.99, 0.01, (\"%.2fs\" % (t1 - t0)).lstrip(\"0\"),\n",
    "                 transform=plt.gca().transAxes, size=15, horizontalalignment=\"right\")\n",
    "        plot_num += 1\n",
    "\n",
    "plt.suptitle(\"Сравнение алгоритмов обнаружения аномалий на датасете make_moons + выбросы (5 одинаковых наборов)\", size=16)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f55d07f3-dee9-4d57-b02e-e1282d3a61e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "Интерпретация результатов:\n",
    "- LOF хорошо находит локальные разреженные области, но может ошибаться на границах кластеров.\n",
    "- Isolation Forest очень эффективен – быстро изолирует выбросы.\n",
    "- One-Class SVM строит гладкую границу, включает часть шума.\n",
    "- Elliptic Envelope работает плохо, так как данные имеют неэллиптическую форму."
   ]
  }
 ],
 "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.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
