Files
ML/task9/[Base]_Sklearn_knn_normalize_cv_[2025_2026].ipynb
2025-11-18 02:55:01 +03:00

1.0 MiB
Raw Permalink Blame History

Машинное обучение. ВМК МГУ

Практическое задание 3: Основы sklearn на примере KNN. Нормализация признаков и Кросс-валидация

Уровень: Базовый (Base)

О формате сдачи

🔷 При решении ноутбука используйте данный шаблон

✅ Можно добавлять новые ячейки любых типов
❌ Не нужно удалять текстовые ячейки c разметкой частей ноутбука и формулировками заданий

🔷 При оценивании задач учитывается код

✅ Задания, в которых необходим код, обычно помечаются фразами "Your code here"/"Ваш код" и аналогичными
❌ Ответы на вопросы без сопутствующего кода оцениваются в 0 баллов
❌ Наличе работоспособного кода в ноутбуке, если на сказано иного, обязательно

🔷 При оценивании задач учитываются выводы

✅ Задания, в которых необходимы выводы, обычно помечаются фразами Вывод"/"Ответ на вопрос"/"Ваш текст" и аналогичными
✅ Обычно выводы подразумевают под собой текстовый ответ (можно писать markdown, latex).
✅ Сопутствующие изображения, графики, таблички - приветствуются!
❌ При отсутствии выводов задание не засчитается на полный балл

  • Многие из заданий можно выполнить несколькими способами. Не существуют единственно верного, но попробуйте максимально задействовать арсенал pandas и ориентируйтесь на простоту и понятность вашего кода. Не забывайте, что можно гуглить и что-то искать на stackoverflow, например.

Примерное время выполнения (execution time/время выполнения, если нажать run all) всех ячеек ноутбука при правильной реализации: 10 минут

Подготовка рабочей среды

Сначала установим нужные нам версии библиотек. Мы гарантируем, что в данных версиях задание будет корректно отрабатывать.

После установки нужных версий, возможно, нужно перезагрузить среду (runtime), но скорее всего вам это не понадобится

На скачивание файла и установку понадобится не более 5 минут.

Важно!

Устанавливать нужные версии нужно каждый раз, когда создается новый рантайм. Например, если вы 2 часа подряд делаете это задание, то подготовить библиотеки достаточно 1 раз. Но если вы, например, начали в понедельник, затем закрыли/выключили ноутбук, то при продолжении в среду, вам нужно будет запустить рантайм заново и следовательно заново установить библиотеки.

Важно! Если вы предпочитаете делать практические задания на своем личном ноутбуке, то проверьте, что вы установили рабочее окружение в соответствии с гайдом

In [1]:
! curl https://raw.githubusercontent.com/MSU-ML-COURSE/ML-COURSE-25-26/refs/heads/master/requirements/requirements.txt -o ./requirements_2025_26_for_colab_small.txt
! pip install -r ./requirements_2025_26_for_colab_small.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   360  100   360    0     0    696      0 --:--:-- --:--:-- --:--:--   697
Collecting catboost==1.2.8 (from -r ./requirements_2025_26_for_colab_small.txt (line 1))
  Downloading catboost-1.2.8-cp312-cp312-manylinux2014_x86_64.whl.metadata (1.2 kB)
Collecting gdown==5.2.0 (from -r ./requirements_2025_26_for_colab_small.txt (line 2))
  Downloading gdown-5.2.0-py3-none-any.whl.metadata (5.8 kB)
Collecting h5py==3.14.0 (from -r ./requirements_2025_26_for_colab_small.txt (line 3))
  Downloading h5py-3.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (2.7 kB)
Collecting hyperopt==0.2.7 (from -r ./requirements_2025_26_for_colab_small.txt (line 4))
  Downloading hyperopt-0.2.7-py2.py3-none-any.whl.metadata (1.7 kB)
Collecting ipympl==0.9.7 (from -r ./requirements_2025_26_for_colab_small.txt (line 5))
  Downloading ipympl-0.9.7-py3-none-any.whl.metadata (8.7 kB)
Collecting ipywidgets==7.7.1 (from -r ./requirements_2025_26_for_colab_small.txt (line 6))
  Downloading ipywidgets-7.7.1-py2.py3-none-any.whl.metadata (1.9 kB)
Collecting lightgbm==4.6.0 (from -r ./requirements_2025_26_for_colab_small.txt (line 7))
  Downloading lightgbm-4.6.0-py3-none-manylinux_2_28_x86_64.whl.metadata (17 kB)
Requirement already satisfied: matplotlib-inline==0.1.7 in /nix/store/xll44q41bdn0i1zcphwj7p95j5arz356-python3.12-matplotlib-inline-0.1.7/lib/python3.12/site-packages (from -r ./requirements_2025_26_for_colab_small.txt (line 8)) (0.1.7)
Collecting matplotlib==3.10.0 (from -r ./requirements_2025_26_for_colab_small.txt (line 9))
  Downloading matplotlib-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (11 kB)
Collecting numpy==2.0.2 (from -r ./requirements_2025_26_for_colab_small.txt (line 10))
  Downloading numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (60 kB)
Collecting pandas==2.2.2 (from -r ./requirements_2025_26_for_colab_small.txt (line 11))
  Downloading pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (19 kB)
Collecting pep8==1.7.1 (from -r ./requirements_2025_26_for_colab_small.txt (line 12))
  Downloading pep8-1.7.1-py2.py3-none-any.whl.metadata (22 kB)
Collecting plotly==5.24.1 (from -r ./requirements_2025_26_for_colab_small.txt (line 13))
  Downloading plotly-5.24.1-py3-none-any.whl.metadata (7.3 kB)
Collecting pycodestyle==2.14.0 (from -r ./requirements_2025_26_for_colab_small.txt (line 14))
  Downloading pycodestyle-2.14.0-py2.py3-none-any.whl.metadata (4.5 kB)
Collecting pytest==8.4.1 (from -r ./requirements_2025_26_for_colab_small.txt (line 15))
  Downloading pytest-8.4.1-py3-none-any.whl.metadata (7.7 kB)
Collecting scikit-image==0.25.2 (from -r ./requirements_2025_26_for_colab_small.txt (line 16))
  Downloading scikit_image-0.25.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (14 kB)
Collecting scikit-learn==1.6.1 (from -r ./requirements_2025_26_for_colab_small.txt (line 17))
  Downloading scikit_learn-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (18 kB)
Collecting scipy==1.16.1 (from -r ./requirements_2025_26_for_colab_small.txt (line 18))
  Downloading scipy-1.16.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (61 kB)
Collecting seaborn==0.13.2 (from -r ./requirements_2025_26_for_colab_small.txt (line 19))
  Downloading seaborn-0.13.2-py3-none-any.whl.metadata (5.4 kB)
Collecting tqdm==4.67.1 (from -r ./requirements_2025_26_for_colab_small.txt (line 20))
  Downloading tqdm-4.67.1-py3-none-any.whl.metadata (57 kB)
Collecting umap-learn==0.5.9.post2 (from -r ./requirements_2025_26_for_colab_small.txt (line 21))
  Downloading umap_learn-0.5.9.post2-py3-none-any.whl.metadata (25 kB)
Collecting xgboost==3.0.4 (from -r ./requirements_2025_26_for_colab_small.txt (line 22))
  Downloading xgboost-3.0.4-py3-none-manylinux_2_28_x86_64.whl.metadata (2.1 kB)
Collecting graphviz (from catboost==1.2.8->-r ./requirements_2025_26_for_colab_small.txt (line 1))
  Downloading graphviz-0.21-py3-none-any.whl.metadata (12 kB)
Requirement already satisfied: six in /nix/store/vfy6pmqhgw9kaxiqyhmlg8rmn2aaw6fd-python3.12-six-1.17.0/lib/python3.12/site-packages (from catboost==1.2.8->-r ./requirements_2025_26_for_colab_small.txt (line 1)) (1.17.0)
Requirement already satisfied: beautifulsoup4 in /nix/store/bwljsfpk78gbaq7rvm3wr3jyrqbwb8i9-python3.12-beautifulsoup4-4.12.3/lib/python3.12/site-packages (from gdown==5.2.0->-r ./requirements_2025_26_for_colab_small.txt (line 2)) (4.12.3)
Requirement already satisfied: filelock in /nix/store/zm1ag99a91zq3h525fbpka5s4yvnjx6c-python3.12-filelock-3.18.0/lib/python3.12/site-packages (from gdown==5.2.0->-r ./requirements_2025_26_for_colab_small.txt (line 2)) (3.18.0)
Requirement already satisfied: requests[socks] in /nix/store/7i5sy2qyz79gjkdlcrmdlgzmjlimq7sk-python3.12-requests-2.32.3/lib/python3.12/site-packages (from gdown==5.2.0->-r ./requirements_2025_26_for_colab_small.txt (line 2)) (2.32.3)
Collecting networkx>=2.2 (from hyperopt==0.2.7->-r ./requirements_2025_26_for_colab_small.txt (line 4))
  Downloading networkx-3.5-py3-none-any.whl.metadata (6.3 kB)
Collecting future (from hyperopt==0.2.7->-r ./requirements_2025_26_for_colab_small.txt (line 4))
  Downloading future-1.0.0-py3-none-any.whl.metadata (4.0 kB)
Collecting cloudpickle (from hyperopt==0.2.7->-r ./requirements_2025_26_for_colab_small.txt (line 4))
  Downloading cloudpickle-3.1.2-py3-none-any.whl.metadata (7.1 kB)
Collecting py4j (from hyperopt==0.2.7->-r ./requirements_2025_26_for_colab_small.txt (line 4))
  Downloading py4j-0.10.9.9-py2.py3-none-any.whl.metadata (1.3 kB)
Requirement already satisfied: ipython<10 in /nix/store/sx6qmhz6rv8fdx0z2jym3kg7pb4ihi9l-python3.12-ipython-9.2.0/lib/python3.12/site-packages (from ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (9.2.0)
Collecting pillow (from ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5))
  Downloading pillow-12.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (8.8 kB)
Requirement already satisfied: traitlets<6 in /nix/store/5fkvg2aiqnv0v6r3k9f4x41qbql50f78-python3.12-traitlets-5.14.3/lib/python3.12/site-packages (from ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (5.14.3)
Requirement already satisfied: ipykernel>=4.5.1 in /nix/store/pzz4808nm0p3lmjpzxnfyb7d3xb6csby-python3.12-ipykernel-6.29.5/lib/python3.12/site-packages (from ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (6.29.5)
Collecting ipython-genutils~=0.2.0 (from ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6))
  Downloading ipython_genutils-0.2.0-py2.py3-none-any.whl.metadata (755 bytes)
Collecting widgetsnbextension~=3.6.0 (from ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6))
  Downloading widgetsnbextension-3.6.10-py2.py3-none-any.whl.metadata (1.3 kB)
Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /home/krosh/Documents/Github/ML/.venv/lib/python3.12/site-packages (from ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (3.0.16)
Collecting contourpy>=1.0.1 (from matplotlib==3.10.0->-r ./requirements_2025_26_for_colab_small.txt (line 9))
  Downloading contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (5.5 kB)
Collecting cycler>=0.10 (from matplotlib==3.10.0->-r ./requirements_2025_26_for_colab_small.txt (line 9))
  Downloading cycler-0.12.1-py3-none-any.whl.metadata (3.8 kB)
Collecting fonttools>=4.22.0 (from matplotlib==3.10.0->-r ./requirements_2025_26_for_colab_small.txt (line 9))
  Downloading fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl.metadata (112 kB)
Collecting kiwisolver>=1.3.1 (from matplotlib==3.10.0->-r ./requirements_2025_26_for_colab_small.txt (line 9))
  Downloading kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (6.3 kB)
Requirement already satisfied: packaging>=20.0 in /nix/store/h1qsc2cb41r5iaix9n7s3gn4r5s2pdfw-python3.12-packaging-24.2/lib/python3.12/site-packages (from matplotlib==3.10.0->-r ./requirements_2025_26_for_colab_small.txt (line 9)) (24.2)
Collecting pyparsing>=2.3.1 (from matplotlib==3.10.0->-r ./requirements_2025_26_for_colab_small.txt (line 9))
  Downloading pyparsing-3.2.5-py3-none-any.whl.metadata (5.0 kB)
Requirement already satisfied: python-dateutil>=2.7 in /nix/store/dn6x1maxc5cxyq84fc51z8pzjk2f4wq6-python3.12-python-dateutil-2.9.0.post0/lib/python3.12/site-packages (from matplotlib==3.10.0->-r ./requirements_2025_26_for_colab_small.txt (line 9)) (2.9.0.post0)
Collecting pytz>=2020.1 (from pandas==2.2.2->-r ./requirements_2025_26_for_colab_small.txt (line 11))
  Downloading pytz-2025.2-py2.py3-none-any.whl.metadata (22 kB)
Collecting tzdata>=2022.7 (from pandas==2.2.2->-r ./requirements_2025_26_for_colab_small.txt (line 11))
  Using cached tzdata-2025.2-py2.py3-none-any.whl.metadata (1.4 kB)
Collecting tenacity>=6.2.0 (from plotly==5.24.1->-r ./requirements_2025_26_for_colab_small.txt (line 13))
  Downloading tenacity-9.1.2-py3-none-any.whl.metadata (1.2 kB)
Collecting iniconfig>=1 (from pytest==8.4.1->-r ./requirements_2025_26_for_colab_small.txt (line 15))
  Downloading iniconfig-2.3.0-py3-none-any.whl.metadata (2.5 kB)
Collecting pluggy<2,>=1.5 (from pytest==8.4.1->-r ./requirements_2025_26_for_colab_small.txt (line 15))
  Downloading pluggy-1.6.0-py3-none-any.whl.metadata (4.8 kB)
Requirement already satisfied: pygments>=2.7.2 in /nix/store/hdikjhn6cic0ibvb3j8cghy7lg3kv6yy-python3.12-pygments-2.19.1/lib/python3.12/site-packages (from pytest==8.4.1->-r ./requirements_2025_26_for_colab_small.txt (line 15)) (2.19.1)
Collecting imageio!=2.35.0,>=2.33 (from scikit-image==0.25.2->-r ./requirements_2025_26_for_colab_small.txt (line 16))
  Downloading imageio-2.37.2-py3-none-any.whl.metadata (9.7 kB)
Collecting tifffile>=2022.8.12 (from scikit-image==0.25.2->-r ./requirements_2025_26_for_colab_small.txt (line 16))
  Downloading tifffile-2025.10.16-py3-none-any.whl.metadata (31 kB)
Collecting lazy-loader>=0.4 (from scikit-image==0.25.2->-r ./requirements_2025_26_for_colab_small.txt (line 16))
  Downloading lazy_loader-0.4-py3-none-any.whl.metadata (7.6 kB)
Collecting joblib>=1.2.0 (from scikit-learn==1.6.1->-r ./requirements_2025_26_for_colab_small.txt (line 17))
  Downloading joblib-1.5.2-py3-none-any.whl.metadata (5.6 kB)
Collecting threadpoolctl>=3.1.0 (from scikit-learn==1.6.1->-r ./requirements_2025_26_for_colab_small.txt (line 17))
  Downloading threadpoolctl-3.6.0-py3-none-any.whl.metadata (13 kB)
Collecting numba>=0.51.2 (from umap-learn==0.5.9.post2->-r ./requirements_2025_26_for_colab_small.txt (line 21))
  Downloading numba-0.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (2.8 kB)
Collecting pynndescent>=0.5 (from umap-learn==0.5.9.post2->-r ./requirements_2025_26_for_colab_small.txt (line 21))
  Downloading pynndescent-0.5.13-py3-none-any.whl.metadata (6.8 kB)
Collecting nvidia-nccl-cu12 (from xgboost==3.0.4->-r ./requirements_2025_26_for_colab_small.txt (line 22))
  Downloading nvidia_nccl_cu12-2.28.7-py3-none-manylinux_2_18_x86_64.whl.metadata (2.0 kB)
Requirement already satisfied: comm>=0.1.1 in /nix/store/vav4k2c299vg67mk0x1pgzs50mv09p6q-python3.12-comm-0.2.2/lib/python3.12/site-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.2.2)
Requirement already satisfied: jupyter-client>=6.1.12 in /nix/store/ii8mmw13zhpg4zdwx6c5sp3qi5g9g0iv-python3.12-jupyter-client-8.6.3/lib/python3.12/site-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (8.6.3)
Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in /nix/store/ppsp7zdbnivzw04r8rrwr30rwkahxy6k-python3.12-jupyter-core-5.7.2/lib/python3.12/site-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (5.7.2)
Requirement already satisfied: nest-asyncio in /nix/store/ah04qkf51fnsq76dkk86gzhm059lbaqr-python3.12-nest-asyncio-1.6.0/lib/python3.12/site-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.6.0)
Requirement already satisfied: psutil in /nix/store/3hsnbwhiflh31c7b808nbai5bwm55ddj-python3.12-psutil-7.0.0/lib/python3.12/site-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (7.0.0)
Requirement already satisfied: pyzmq>=24 in /nix/store/h9nq7xr7pfwdksqlx1givw25fiv1fflh-python3.12-pyzmq-26.3.0/lib/python3.12/site-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (26.3.0)
Requirement already satisfied: tornado>=6.1 in /nix/store/ay14g4n81v3p75rdibn9ddp7m4idazgv-python3.12-tornado-6.5.1/lib/python3.12/site-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (6.5.1)
Requirement already satisfied: decorator in /nix/store/gkh0fg3v2zs85v3h3cw1nh2d6ncdzki6-python3.12-decorator-5.2.1/lib/python3.12/site-packages (from ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (5.2.1)
Requirement already satisfied: ipython-pygments-lexers in /nix/store/qqvbgszbfdlxpzfd41ggzxmh0p5wq0rj-python3.12-ipython-pygments-lexers-1.1.1/lib/python3.12/site-packages (from ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (1.1.1)
Requirement already satisfied: jedi>=0.16 in /nix/store/0g96bmz4qlk00rd58lsivm7xir6ljg0m-python3.12-jedi-0.19.2/lib/python3.12/site-packages (from ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (0.19.2)
Requirement already satisfied: pexpect>4.3 in /nix/store/hw5i2kd9750fndnb9gdl3x5prxx7mj5d-python3.12-pexpect-4.9.0/lib/python3.12/site-packages (from ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (4.9.0)
Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /nix/store/wzmw3slxlzycs29w5hjjc6a1529d0s6d-python3.12-prompt-toolkit-3.0.50/lib/python3.12/site-packages (from ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (3.0.50)
Requirement already satisfied: stack_data in /nix/store/61k17cinvnvwvyr0hxmf2c28407k9q2l-python3.12-stack-data-0.6.3/lib/python3.12/site-packages (from ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (0.6.3)
Collecting llvmlite<0.46,>=0.45.0dev0 (from numba>=0.51.2->umap-learn==0.5.9.post2->-r ./requirements_2025_26_for_colab_small.txt (line 21))
  Downloading llvmlite-0.45.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (4.9 kB)
Requirement already satisfied: notebook>=4.4.1 in /home/krosh/Documents/Github/ML/.venv/lib/python3.12/site-packages (from widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (7.4.7)
Requirement already satisfied: soupsieve>1.2 in /nix/store/j9ndbf8laq3gki56i3f748k0l66s7qzd-python3.12-soupsieve-2.6/lib/python3.12/site-packages (from beautifulsoup4->gdown==5.2.0->-r ./requirements_2025_26_for_colab_small.txt (line 2)) (2.6)
Requirement already satisfied: charset_normalizer<4,>=2 in /nix/store/znsiffn7xpr0bfmmbvh7j9dn0z815pf6-python3.12-charset-normalizer-3.4.1/lib/python3.12/site-packages (from requests[socks]->gdown==5.2.0->-r ./requirements_2025_26_for_colab_small.txt (line 2)) (3.4.1)
Requirement already satisfied: idna<4,>=2.5 in /nix/store/80zr7m04sb6a5kfaq55nd1rf2425gi7r-python3.12-idna-3.10/lib/python3.12/site-packages (from requests[socks]->gdown==5.2.0->-r ./requirements_2025_26_for_colab_small.txt (line 2)) (3.10)
Requirement already satisfied: urllib3<3,>=1.21.1 in /nix/store/d3n2v8v8m2874vn7gw7zrdggj86dincs-python3.12-urllib3-2.3.0/lib/python3.12/site-packages (from requests[socks]->gdown==5.2.0->-r ./requirements_2025_26_for_colab_small.txt (line 2)) (2.3.0)
Requirement already satisfied: certifi>=2017.4.17 in /nix/store/bk8dgkmkprc9wc6wcwc75bdyjk1ndbjk-python3.12-certifi-2025.01.31/lib/python3.12/site-packages (from requests[socks]->gdown==5.2.0->-r ./requirements_2025_26_for_colab_small.txt (line 2)) (2025.1.31)
Collecting PySocks!=1.5.7,>=1.5.6 (from requests[socks]->gdown==5.2.0->-r ./requirements_2025_26_for_colab_small.txt (line 2))
  Downloading PySocks-1.7.1-py3-none-any.whl.metadata (13 kB)
Requirement already satisfied: parso<0.9.0,>=0.8.4 in /nix/store/sw3hp8g6i6n5hcj0zk3dvdm8v7k67c6h-python3.12-parso-0.8.4/lib/python3.12/site-packages (from jedi>=0.16->ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (0.8.4)
Requirement already satisfied: platformdirs>=2.5 in /nix/store/ay5c0v86xdaq1w2x8l8z88kkiwv7i2cl-python3.12-platformdirs-4.3.7/lib/python3.12/site-packages (from jupyter-core!=5.0.*,>=4.12->ipykernel>=4.5.1->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (4.3.7)
Requirement already satisfied: jupyter-server<3,>=2.4.0 in /nix/store/zj57c9yx8bkqg83xjxz6bjwnxg65dk5c-python3.12-jupyter-server-2.15.0/lib/python3.12/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (2.15.0)
Requirement already satisfied: jupyterlab-server<3,>=2.27.1 in /nix/store/pd8cbi214wii25llx5g2ismw6pmvgkf5-python3.12-jupyterlab-server-2.27.3/lib/python3.12/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (2.27.3)
Collecting jupyterlab<4.5,>=4.4.9 (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6))
  Using cached jupyterlab-4.4.10-py3-none-any.whl.metadata (16 kB)
Requirement already satisfied: notebook-shim<0.3,>=0.2 in /nix/store/agvxbdh9lb9i7gm5v1qjx7a0bv22am8n-python3.12-notebook-shim-0.2.4/lib/python3.12/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.2.4)
Requirement already satisfied: ptyprocess>=0.5 in /nix/store/rz2ygcrnc8wx1n3pz0slcah47s71havg-python3.12-ptyprocess-0.7.0/lib/python3.12/site-packages (from pexpect>4.3->ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (0.7.0)
Requirement already satisfied: wcwidth in /nix/store/82wc5sicriaacpnavd97c9b2b3l88d1j-python3.12-wcwidth-0.2.13/lib/python3.12/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (0.2.13)
Requirement already satisfied: executing>=1.2.0 in /nix/store/vryr7qfzh6qp2v8whvc5357hz3f3xxpc-python3.12-executing-2.2.0/lib/python3.12/site-packages (from stack_data->ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (2.2.0)
Requirement already satisfied: asttokens>=2.1.0 in /nix/store/lh5is09vgpvw5rnvm9bgcxiasm7pidw1-python3.12-asttokens-3.0.0/lib/python3.12/site-packages (from stack_data->ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (3.0.0)
Requirement already satisfied: pure_eval in /nix/store/lab1jiw46l09zci0r8h1cl2wnb04w1s5-python3.12-pure-eval-0.2.3/lib/python3.12/site-packages (from stack_data->ipython<10->ipympl==0.9.7->-r ./requirements_2025_26_for_colab_small.txt (line 5)) (0.2.3)
Requirement already satisfied: anyio>=3.1.0 in /nix/store/slsfw31xlwaczcnqgg4r5qw3xpwm0nbq-python3.12-anyio-4.9.0/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (4.9.0)
Requirement already satisfied: argon2-cffi>=21.1 in /nix/store/1clmzlxvasiidjs72h4vx4pqcrkwg3zf-python3.12-argon2-cffi-23.1.0/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (23.1.0)
Requirement already satisfied: jinja2>=3.0.3 in /nix/store/svijzcfkrsxb8jripykx1d2krzi2q0fq-python3.12-jinja2-3.1.6/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (3.1.6)
Requirement already satisfied: jupyter-events>=0.11.0 in /nix/store/4jydas1rslfay93x8h61s7a16023pcql-python3.12-jupyter-events-0.11.0/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.11.0)
Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /nix/store/ly5g70s9xpnm9piajwcmrlrd8maixfh4-python3.12-jupyter-server-terminals-0.5.3/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.5.3)
Requirement already satisfied: nbconvert>=6.4.4 in /nix/store/5h2jqcxjgkyrp8yy28s1cxbmlps9llbr-python3.12-nbconvert-7.16.6/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (7.16.6)
Requirement already satisfied: nbformat>=5.3.0 in /nix/store/mha5x4r94hi8278p347v2ig89r7pg37i-python3.12-nbformat-5.10.4/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (5.10.4)
Requirement already satisfied: overrides>=5.0 in /nix/store/8hnr7s08x0zglraaqhsvxw9cxfb4m5vf-python3.12-overrides-7.7.0/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (7.7.0)
Requirement already satisfied: prometheus-client>=0.9 in /nix/store/hi0lchzh5wd2mima5ryzxv1sp8avpixv-python3.12-prometheus-client-0.21.1/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.21.1)
Requirement already satisfied: send2trash>=1.8.2 in /nix/store/qaybrn941lhzv68mmly22vml2bi9biln-python3.12-send2trash-1.8.3/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.8.3)
Requirement already satisfied: terminado>=0.8.3 in /nix/store/r0c0p4ycha98vxggn3ib9bmrsma9a5gq-python3.12-terminado-0.18.1/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.18.1)
Requirement already satisfied: websocket-client>=1.7 in /nix/store/maij4ca0hdq51yh6sc8ha0dbfksfvbs2-python3.12-websocket-client-1.8.0/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.8.0)
Requirement already satisfied: async-lru>=1.0.0 in /nix/store/appfbz4pp2rq674miy7y35llz30382ab-python3.12-async-lru-2.0.5/lib/python3.12/site-packages (from jupyterlab<4.5,>=4.4.9->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (2.0.5)
Requirement already satisfied: httpx<1,>=0.25.0 in /nix/store/83krrvn5s26brnzqfqb9w7cvsa94b9w6-python3.12-httpx-0.28.1/lib/python3.12/site-packages (from jupyterlab<4.5,>=4.4.9->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.28.1)
Requirement already satisfied: jupyter-lsp>=2.0.0 in /nix/store/w0fm4viprsj0s6vdymp1grlgq9gg24pp-python3.12-jupyter-lsp-2.2.5/lib/python3.12/site-packages (from jupyterlab<4.5,>=4.4.9->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (2.2.5)
Requirement already satisfied: setuptools>=41.1.0 in /nix/store/jahiclal74yv1j7py0jnlm30ji3wa1wr-python3.12-setuptools-78.1.1/lib/python3.12/site-packages (from jupyterlab<4.5,>=4.4.9->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (78.1.1.post0)
Requirement already satisfied: babel>=2.10 in /nix/store/0k8xz970r9zwm7c0bbmnps9ppya32jyx-python3.12-babel-2.17.0/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.27.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (2.17.0)
Requirement already satisfied: json5>=0.9.0 in /nix/store/m67k0bjvzldj8fg862y9jaqdn14fav0r-python3.12-json5-0.10.0/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.27.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.10.0)
Requirement already satisfied: jsonschema>=4.18.0 in /nix/store/cbv4a3ncj97dj8a7sz4ldw5hpajhnrgd-python3.12-jsonschema-4.23.0/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.27.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (4.23.0)
Requirement already satisfied: sniffio>=1.1 in /nix/store/6jdf3szr6xcvzdg3cdzrgvhy6dc6ppdp-python3.12-sniffio-1.3.1/lib/python3.12/site-packages (from anyio>=3.1.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.3.1)
Requirement already satisfied: typing_extensions>=4.5 in /nix/store/lpap2xy7m2z6qs3pjgx57whdvn0gmrld-python3.12-typing-extensions-4.13.2/lib/python3.12/site-packages (from anyio>=3.1.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (4.13.2)
Requirement already satisfied: argon2-cffi-bindings in /nix/store/xs11y0i84x084h3f9va5xn3vw71g9sn5-python3.12-argon2-cffi-bindings-21.2.0/lib/python3.12/site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (21.2.0)
Requirement already satisfied: httpcore==1.* in /nix/store/45mbjl9s9pv0libawf8ikmh588k831zz-python3.12-httpcore-1.0.9/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab<4.5,>=4.4.9->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.0.9)
Requirement already satisfied: h11>=0.16 in /nix/store/ndg6nlcirvbl8w5sdz49r0x28x4hnfr7-python3.12-h11-0.16.0/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.25.0->jupyterlab<4.5,>=4.4.9->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.16.0)
Requirement already satisfied: MarkupSafe>=2.0 in /nix/store/s1s7cngw3wc3wm6ysqyjkwq8nq4cz4vl-python3.12-markupsafe-3.0.2/lib/python3.12/site-packages (from jinja2>=3.0.3->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (3.0.2)
Requirement already satisfied: attrs>=22.2.0 in /nix/store/aj8dzb2ampzwwmjy7i47ypbp9vdcb4zy-python3.12-attrs-25.3.0/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.27.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (25.3.0)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /nix/store/vd97fs6kjvygdndlsnh2c9166z4d0xh3-python3.12-jsonschema-specifications-2024.10.1/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.27.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (2024.10.1)
Requirement already satisfied: referencing>=0.28.4 in /nix/store/n7knhq0j8jmls8dckxyim8qhslw399ng-python3.12-referencing-0.36.2/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.27.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.36.2)
Requirement already satisfied: rpds-py>=0.7.1 in /nix/store/8a2h77svk68xqlhbp0bi2xk8rwj9j50j-python3.12-rpds-py-0.24.0/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.27.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.24.0)
Requirement already satisfied: python-json-logger>=2.0.4 in /nix/store/p56rsir3w5f044svipd9mpa6qqxgsa78-python3.12-python-json-logger-3.2.1/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (3.2.1)
Requirement already satisfied: pyyaml>=5.3 in /nix/store/9ap0fph2ybcfnl0f1rsklj990n25ll84-python3.12-pyyaml-6.0.2/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (6.0.2)
Requirement already satisfied: rfc3339-validator in /nix/store/14rqw00zqxk6jcslmab0skzzf3qcp5xw-python3.12-rfc3339-validator-0.1.4/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.1.4)
Requirement already satisfied: rfc3986-validator>=0.1.1 in /nix/store/zqnambrrca5dzmfiizygsslmgakhiigc-python3.12-rfc3986-validator-0.1.1/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.1.1)
Requirement already satisfied: bleach!=5.0.0 in /nix/store/0svbzbngdvar6sdz7p4iscpjhcp5i7aq-python3.12-bleach-6.2.0/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (6.2.0)
Requirement already satisfied: defusedxml in /nix/store/4l429an1q3m5m7gbmr004zi4mzhbksn1-python3.12-defusedxml-0.8.0rc2/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.8.0rc2)
Requirement already satisfied: jupyterlab-pygments in /nix/store/fm0shwwm682kdk11hx331ya0axmx6357-python3.12-jupyterlab-pygments-0.3.0/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.3.0)
Requirement already satisfied: mistune<4,>=2.0.3 in /nix/store/9mln2k5sj8y5jr1mggmd55zbj6m5i4vb-python3.12-mistune-3.1.2/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (3.1.2)
Requirement already satisfied: nbclient>=0.5.0 in /nix/store/yhm4rkd5j81xfwmcr8s749m67z9099pa-python3.12-nbclient-0.10.2/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.10.2)
Requirement already satisfied: pandocfilters>=1.4.1 in /nix/store/n76h7wginvrsqaq8ngnmf259fagz6dyp-python3.12-pandocfilters-1.5.1/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.5.1)
Requirement already satisfied: fastjsonschema>=2.15 in /nix/store/yh2gsm8j4cnx422kxm69bx0k7c54n6b4-python3.12-fastjsonschema-2.21.1/lib/python3.12/site-packages (from nbformat>=5.3.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (2.21.1)
Requirement already satisfied: webencodings in /nix/store/n8jzk1lyamvlj6rw9pyx88ai0rhcmfgm-python3.12-webencodings-0.5.1/lib/python3.12/site-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (0.5.1)
Requirement already satisfied: tinycss2<1.5,>=1.1.0 in /nix/store/lrxfr5x30dinqpw0vg2zvdvh6jfy4kxn-python3.12-tinycss2-1.4.0/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.4.0)
Requirement already satisfied: fqdn in /nix/store/c676msxyjp0k5r70s33p040rk6fxii8d-python3.12-fqdn-1.5.1/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.5.1)
Requirement already satisfied: isoduration in /nix/store/4mnklym4fix9xi1i4ppknqk5fcpljfga-python3.12-isoduration-20.11.0/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (20.11.0)
Requirement already satisfied: jsonpointer>1.13 in /nix/store/9lhd1pal6j928py2p7x6g5xs2fyqjfzf-python3.12-jsonpointer-3.0.0/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (3.0.0)
Requirement already satisfied: uri-template in /nix/store/g3g6pdfkd8xlnram70kml18wxdl1zyl2-python3.12-uri-template-1.3.0/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.3.0)
Requirement already satisfied: webcolors>=24.6.0 in /nix/store/vffapvc0y8z4y3x1kq1yahyrk203z60v-python3.12-webcolors-24.11.1/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (24.11.1)
Requirement already satisfied: cffi>=1.0.1 in /nix/store/xmrm1mvjf8kp4nl1im58apax0n0pgb81-python3.12-cffi-1.17.1/lib/python3.12/site-packages (from argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.17.1)
Requirement already satisfied: pycparser in /nix/store/zvrx9j7dsh4h5ryn9nn2vs9v7i7lslc0-python3.12-pycparser-2.22/lib/python3.12/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (2.22)
Requirement already satisfied: arrow>=0.15.0 in /nix/store/xkn28vnhxy42lz0039qqpxhf1dplifb6-python3.12-arrow-1.3.0/lib/python3.12/site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (1.3.0)
Requirement already satisfied: types-python-dateutil>=2.8.10 in /nix/store/4rbnpq6m8shi5h2s2l3kjn86f157gh2d-python3.12-types-python-dateutil-2.9.0.20241206/lib/python3.12/site-packages (from arrow>=0.15.0->isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r ./requirements_2025_26_for_colab_small.txt (line 6)) (2.9.0.20241206)
Downloading catboost-1.2.8-cp312-cp312-manylinux2014_x86_64.whl (99.2 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 99.2/99.2 MB 486.6 kB/s eta 0:00:00m eta 0:00:01[36m0:00:06
[?25hDownloading gdown-5.2.0-py3-none-any.whl (18 kB)
Downloading h5py-3.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.9 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.9/4.9 MB 314.9 kB/s eta 0:00:00 kB/s eta 0:00:01:04
[?25hDownloading hyperopt-0.2.7-py2.py3-none-any.whl (1.6 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 544.6 kB/s eta 0:00:00 kB/s eta 0:00:01:02
[?25hDownloading ipympl-0.9.7-py3-none-any.whl (515 kB)
Downloading ipywidgets-7.7.1-py2.py3-none-any.whl (123 kB)
Downloading lightgbm-4.6.0-py3-none-manylinux_2_28_x86_64.whl (3.6 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.6/3.6 MB 636.2 kB/s eta 0:00:00 kB/s eta 0:00:01:04
[?25hDownloading matplotlib-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (8.6 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.6/8.6 MB 202.3 kB/s eta 0:00:00[36m0:00:02m eta 0:00:03
[?25hDownloading numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (19.2 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 19.2/19.2 MB 465.2 kB/s eta 0:00:00m eta 0:00:01[36m0:00:02
[?25hDownloading pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.7 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.7/12.7 MB 314.6 kB/s eta 0:00:00m eta 0:00:01[36m0:00:02
[?25hDownloading pep8-1.7.1-py2.py3-none-any.whl (41 kB)
Downloading plotly-5.24.1-py3-none-any.whl (19.1 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 19.1/19.1 MB 226.8 kB/s eta 0:00:00m eta 0:00:01[36m0:00:04
[?25hDownloading pycodestyle-2.14.0-py2.py3-none-any.whl (31 kB)
Downloading pytest-8.4.1-py3-none-any.whl (365 kB)
Downloading scikit_image-0.25.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (15.0 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 15.0/15.0 MB 450.7 kB/s eta 0:00:00m eta 0:00:010:02:03
[?25hDownloading scikit_learn-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (13.1 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 13.1/13.1 MB 569.2 kB/s eta 0:00:00m eta 0:00:010:01:02
[?25hDownloading scipy-1.16.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (35.2 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 35.2/35.2 MB 943.1 kB/s eta 0:00:00m eta 0:00:01[36m0:00:02
[?25hDownloading seaborn-0.13.2-py3-none-any.whl (294 kB)
Downloading tqdm-4.67.1-py3-none-any.whl (78 kB)
Downloading umap_learn-0.5.9.post2-py3-none-any.whl (90 kB)
Downloading xgboost-3.0.4-py3-none-manylinux_2_28_x86_64.whl (94.9 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 94.9/94.9 MB 650.9 kB/s eta 0:00:00m eta 0:00:01[36m0:00:05
[?25hDownloading contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (362 kB)
Downloading cycler-0.12.1-py3-none-any.whl (8.3 kB)
Downloading fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl (4.9 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.9/4.9 MB 685.6 kB/s eta 0:00:00 kB/s eta 0:00:01:02
[?25hDownloading imageio-2.37.2-py3-none-any.whl (317 kB)
Downloading iniconfig-2.3.0-py3-none-any.whl (7.5 kB)
Downloading ipython_genutils-0.2.0-py2.py3-none-any.whl (26 kB)
Downloading joblib-1.5.2-py3-none-any.whl (308 kB)
Downloading kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.5 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.5/1.5 MB 1.4 MB/s eta 0:00:00[31m1.3 MB/s eta 0:00:01
[?25hDownloading lazy_loader-0.4-py3-none-any.whl (12 kB)
Downloading networkx-3.5-py3-none-any.whl (2.0 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.0/2.0 MB 985.8 kB/s eta 0:00:00B/s eta 0:00:01:01
[?25hDownloading numba-0.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (3.8 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.8/3.8 MB 1.4 MB/s eta 0:00:00[31m1.4 MB/s eta 0:00:01
[?25hDownloading pillow-12.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (7.0 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.0/7.0 MB 1.2 MB/s eta 0:00:00[31m1.2 MB/s eta 0:00:01
[?25hDownloading pluggy-1.6.0-py3-none-any.whl (20 kB)
Downloading pynndescent-0.5.13-py3-none-any.whl (56 kB)
Downloading pyparsing-3.2.5-py3-none-any.whl (113 kB)
Downloading pytz-2025.2-py2.py3-none-any.whl (509 kB)
Downloading tenacity-9.1.2-py3-none-any.whl (28 kB)
Downloading threadpoolctl-3.6.0-py3-none-any.whl (18 kB)
Downloading tifffile-2025.10.16-py3-none-any.whl (231 kB)
Using cached tzdata-2025.2-py2.py3-none-any.whl (347 kB)
Downloading widgetsnbextension-3.6.10-py2.py3-none-any.whl (1.6 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 1.0 MB/s eta 0:00:00[31m980.3 kB/s eta 0:00:01
[?25hDownloading cloudpickle-3.1.2-py3-none-any.whl (22 kB)
Downloading future-1.0.0-py3-none-any.whl (491 kB)
Downloading graphviz-0.21-py3-none-any.whl (47 kB)
Downloading nvidia_nccl_cu12-2.28.7-py3-none-manylinux_2_18_x86_64.whl (296.8 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 296.8/296.8 MB 561.9 kB/s eta 0:00:00m eta 0:00:01[36m0:00:20
[?25hDownloading py4j-0.10.9.9-py2.py3-none-any.whl (203 kB)
Downloading llvmlite-0.45.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (56.3 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 56.3/56.3 MB 551.0 kB/s eta 0:00:00m eta 0:00:01[36m0:00:03
[?25hDownloading PySocks-1.7.1-py3-none-any.whl (16 kB)
Using cached jupyterlab-4.4.10-py3-none-any.whl (12.3 MB)
Installing collected packages: pytz, py4j, pep8, ipython-genutils, tzdata, tqdm, threadpoolctl, tenacity, PySocks, pyparsing, pycodestyle, pluggy, pillow, nvidia-nccl-cu12, numpy, networkx, llvmlite, lazy-loader, kiwisolver, joblib, iniconfig, graphviz, future, fonttools, cycler, cloudpickle, tifffile, scipy, pytest, plotly, pandas, numba, imageio, h5py, contourpy, xgboost, scikit-learn, scikit-image, matplotlib, lightgbm, hyperopt, gdown, seaborn, pynndescent, catboost, umap-learn, jupyterlab, widgetsnbextension, ipywidgets, ipympl
  Attempting uninstall: jupyterlab
    Found existing installation: jupyterlab 4.4.1
    Not uninstalling jupyterlab at /nix/store/jzhscs6dw96a836cvv12s271j59a5lmv-python3.12-jupyterlab-4.4.1/lib/python3.12/site-packages, outside environment /home/krosh/Documents/Github/ML/.venv
    Can't uninstall 'jupyterlab'. No files were found to uninstall.
  Attempting uninstall: widgetsnbextension
    Found existing installation: widgetsnbextension 4.0.15
    Uninstalling widgetsnbextension-4.0.15:
      Successfully uninstalled widgetsnbextension-4.0.15
  Attempting uninstall: ipywidgets
    Found existing installation: ipywidgets 8.1.8
    Uninstalling ipywidgets-8.1.8:
      Successfully uninstalled ipywidgets-8.1.8
Successfully installed PySocks-1.7.1 catboost-1.2.8 cloudpickle-3.1.2 contourpy-1.3.3 cycler-0.12.1 fonttools-4.60.1 future-1.0.0 gdown-5.2.0 graphviz-0.21 h5py-3.14.0 hyperopt-0.2.7 imageio-2.37.2 iniconfig-2.3.0 ipympl-0.9.7 ipython-genutils-0.2.0 ipywidgets-7.7.1 joblib-1.5.2 jupyterlab-4.4.10 kiwisolver-1.4.9 lazy-loader-0.4 lightgbm-4.6.0 llvmlite-0.45.1 matplotlib-3.10.0 networkx-3.5 numba-0.62.1 numpy-2.0.2 nvidia-nccl-cu12-2.28.7 pandas-2.2.2 pep8-1.7.1 pillow-12.0.0 plotly-5.24.1 pluggy-1.6.0 py4j-0.10.9.9 pycodestyle-2.14.0 pynndescent-0.5.13 pyparsing-3.2.5 pytest-8.4.1 pytz-2025.2 scikit-image-0.25.2 scikit-learn-1.6.1 scipy-1.16.1 seaborn-0.13.2 tenacity-9.1.2 threadpoolctl-3.6.0 tifffile-2025.10.16 tqdm-4.67.1 tzdata-2025.2 umap-learn-0.5.9.post2 widgetsnbextension-3.6.10 xgboost-3.0.4

Проверим версию библиотеки:

In [2]:
import catboost
assert(catboost.__version__ == '1.2.8')

Теперь можно приступать к выполнению задания! :)


Часть 0. Знакомство с библиотекой scikit-learn

Scikit-learn - это библиотека машинного обучения с открытым исходным кодом, которая предоставляет различные инструменты для предобработки данных и обучения моделей.

Подробную документацию с обширным количеством теоретических и практических примеров можно найти на сайте библиотеки

Импорт библиотеки

Можно импортировать библиотеку целиком:

In [5]:
import sklearn

Однако, так как библиотека очень обширная и содержит большое количество модулей, то импортируют либо модуль, либо классы/методы точечно и целенаправленно:

In [8]:
from sklearn.neighbors import KNeighborsClassifier # класс, с помощью которого мы в дальнейшем будем обучать kNN

Подсказка обычно по названию модуля интуитивно понятно, какие методы и функции в нем содержатся. С увеличением практики использования библиотеки вы сможете лучше и быстрее навигироваться в ней. Например, модуль neighbors содержит различные методы поиска ближайших соседей. Помните, что есть как версии для классификации, так и для задач регрессии? Вот версию для классификации мы выше как раз и импортировали. Однако если провалиться в описание модуля можно увидеть еще много разных классов и функций, которые так или иначе связаны с поиском соседей.

Общее устройство моделей

Одним из несравненных плюсов библиотеки является то, что она предоставляет максимально общий и максимально понятный интерфейс взаимодействия с различными алгоритмами машинного обучения.

Обычно, чтобы решить задачу машинного обучения, нам нужно (как минимум):

  • Знать, какой моделью (алгоритмом) хотим воспользоваться
  • Обучить ее на некоторое обучающей выборке
  • Уметь узнавать предсказания модели на новой выборке

Вам не нужно запоминать для каждой конкретной модели, а как она вообще обучается и как это написать: библиотека все делает за вас.

Каждая модель машинного обучения имеет два метода: fit - метод ответственный за обучения модели и predict - метод ответственный за предсказание целевой переменной.

  • Как правило, метод fit принимает на вход два аргумента: X_{train} - обучающая выборка, y_{train} - значения целевых переменных на объектах обучающей выборки.
  • Метод predict принимает на вход набор данных X_{test} и выдает предсказанные значения целевых переменных y_{test} на этом наборе данных.
  • В моделях классификации бывает метод predict_proba, который принимает на вход набор данных и выдает вероятности принадлежности классам.
  • Если нами решается задача классификации, то вектор целевых переменных y содержит целые числа (или другое множество дискретных величин).
  • При решении задачи регрессии вектор y содержит вещественные числа.

Выборка (данные) X представляется в виде матрицы размера (n_samples, n_features), то есть каждому объекту соответствует отдельная строка, а каждому признаку - отдельный столбец.

Целевая переменная обычно представляется одномерным вектором размера (n_samples) - предсказаниями для каждого объекта, в случае предсказания вероятностей классов - матрицей размера (n_samples, n_classes) - значения вероктностей принадлежности объекта к тому или иному классу

Приведем пример стандартной работы с библиотекой scikit-learn

Подсказка Это совсем-совсем базовый способ обучения моделей, на практике используют много дополнительных приемов, постепенно которые мы будем с вами изучать

In [9]:
#Создаем обучающую выборку
X_train = [[0], [1], [2], [3]] # матрица размера 4 x 1, 4 - объекта, 1 признак
y_train = [0, 0, 1, 1] # обучающий вектор целевых переменных

#Создаем тестовую выборку
X_test = [[1.1], [2.8]] # матрица размера 2x1, 2 - объекта, 1 признак

#Создаем объект класса 3-NN классификатора
neigh = KNeighborsClassifier(n_neighbors=3)

#Обучаем классифкатора на созданной ранее выборке
neigh.fit(X_train, y_train)

#Предсказываем метку класса нового объекта с помощью метода predict
y_test = neigh.predict(X_test)
print(y_test) # y_test - вектор размера 2 (в тестовой выборке 2 объекта)
[0 1]

Общее устройство предобработки данных

На практике почти никогда вы не встретите идеальных данных :) Вам всегда понадобится на них посмотреть, проанализировать, где-то почистить, где-то преобразовать и пр.

Упрощая, все работу с данными можно проделать с помощью 2 библиотек:

  • pandas - с помощью этой библиотеки проанализировать данные, посмотреть на то, что в них хранится, принять решение о удалении мусора, замены каких-то значений и прочего. Данные техники вы совсем немного затронули в предыдущем домашнем задании, но подробнее мы к ним вернемся в следующем домашнем задании

  • skelarn - технические способы обработки данных, особенности которых связаны непосредственно с моделью или способом обучения

Пример Данная библиотека поможет решить вопрос: а как нам признаки с типом строка (например, название видео) "запихнуть" в kNN? Он же только чиселки умеет понимать?

Пример Или на следующий вопрос: с лекции немного припоминаю, что для более хорошей работы метрических методов хорошо бы данные привести в один масштаб. Как это можно быстро и безболезненно сделать?

Например, есть 2 признака:

  • вероятность покупки p - лежит на отрезке [0, 1]
  • стоимость покупки s - лежит на отрезке [0, 100000500000]

Хотелось бы чтобы оба признака были на отрезке [0, 1], потому что покупка, кажется, может вносить гораздо больший вклад по расстоянию в обучении модели..

В sklearn способы обработки данных также предоставляются через различные классы, которые имеют одинаковый интерфейс:

Каждый модуль предобработки данных имеет два метода: fit и transform.

  • Как правило, метод fit принимает на вход обучающую выборку X_train и считает по ней необходимые для заданного типа преобразования статистики.
  • Метод transform преобразует входные данные, используя статистики, посчитанные при вызове метода fit и возвращает преобразованные данные.

Пояснение: Когда не хватает pandas или skelarn, можно обратиться к другим библиотекам, например, numpy :) Sklearn обычно одинаково хорошо работает с данными, представленным как и pd.DataFrame, так и numpy-array или обычными вложенными питоновскими списками


In [6]:
import numpy as np
X_train = np.array([[0, 0], [0.5, 100], [1, 1000005000]]) # numpy используем для удобства отображения
# выборка из 3 примеров, 1й признак - вероятность покупки p
# 2й признак - стоимость покупки s

print(X_train)
[[0.000000e+00 0.000000e+00]
 [5.000000e-01 1.000000e+02]
 [1.000000e+00 1.000005e+09]]
In [10]:
from sklearn.preprocessing import MinMaxScaler # штука, которая приводит все значения признаков к отрезку [0, 1]
# В части 1 подробнее разберем

scaler = MinMaxScaler() # создаем экземпляр класса

scaler.fit(X_train) # "обучаем" преобразователь, на самом деле под капотом считаются статистики
# X_train тут не меняется!
Out [10]:
MinMaxScaler()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
MinMaxScaler()
In [11]:
# Теперь метод для каждого признака посчитал его минимальные и максимальные значения
# Но это под капотом, сюда можно вообще не лезть
scaler.data_min_, scaler.data_max_
Out [11]:
(array([0.]), array([3.]))
In [12]:
X_new = scaler.transform(X_train)
X_new
# Значения в 1й признаке не поменялись, так как они уже удовлетворяли условию
# А во втором - стали на отрезке [0, 1]
Out [12]:
array([[0.        ],
       [0.33333333],
       [0.66666667],
       [1.        ]])

Часть 1. Нормализация признакового пространства

В задачах машинного обучения важную роль играет нормализация данных. Ее мы затронули как раз выше. Для числовых признаков, как правило, используют два типа нормализации:

  • Нормализация к распределению с нулевым матожиданием и единичной дисперсией, x := \frac{x - E(x)}{\sigma (x)}, где матожидание E(x) и стандартное отклонение \sigma (x) считаются по каждому признаку (столбцу) отдельно
  • Нормализация в отрезок [0, 1], x := \frac{x - \min(x)}{\max(x) - \min(x)}, где минимум и максимум берется по каждому признаку (столбцу) отдельно (как в примере выше)

Пример

Ниже приведены: таблица до нормализации признаков, таблица после нормализации к нулевому матожиданию и единичной дисперсии, таблица после нормализации в отрезок [0, 1]

До нормализации

Признак 1 Признак 2
1 2
2 -1
3 0

Нормализация к нулевому матожиданию и единичной дисперсии

Признак 1 Признак 2
-1.225 1.336
0 -1.069
1.225 -0.267

Нормализация в отрезок [0, 1]

Признак 1 Признак 2
0 1
0.5 0
1 0.333

Задание 1.1 (юнит-тесты, 4 баллa)

В модуле scalers.py реализуйте два вида нормализации признакового пространства. StandardScaler - нормализация к распределению с нулевым матожиданием и единичной дисперсией, MinMaxScaler - нормализация в отрезок [0, 1].

Нормализаторы имеют два метода - метод fit и метод transform, что максимально повторяет концепцию sklearn. Метод fit получает на вход обучающую выборку и считает по ней все необходимые для заданного преобразования статистики, которые сохраняет во внутренние поля класса. Метод transform преобразует данные, используя статистистики, посчитанные при вызове метода fit.

Примеры запусков функций можно увидеть в открытых тестах.

Внимание! В текущую директорию необходимо загрузить файл scalers.py с реализованными классами. В Google Colab это можно сделать, нажав на значок "папки" слева, дальше на "загрузить" (значок листа со стрелкой вверх). Загружать нужно в папку "sample_data" (она у вас откроется по умолчанию)


Внимание! Перед тем, как выполнять задание дальше, убедитесь, что ваша реализация проходит тесты с системе проверке заданий, и вы загрузили сюда вашу реализацию

Теперь посмотрим работу "скейлеров" на примере данных:

In [13]:
from scalers import StandardScaler, MinMaxScaler
In [14]:
import numpy as np
import seaborn as sns
import pickle

from matplotlib import pyplot as plt


plt.rcParams["figure.figsize"] = (5,5)

Загрузим файл с данными data.pkl:

In [ ]:
import gdown

gdown.download(id='1cGV6SvpJuP_pa1mLCnI_SvTafEtW2sSO')

Загрузим данные в память. В переменной X будут храниться признаковые описания объектов, в переменной y~- метки классов

In [ ]:
with open('/content/data.pkl', 'rb') as file:
    X, y = pickle.load(file)
In [17]:
def plot_data_points(X, labels, xlim, ylim):
    g = sns.scatterplot(x=X[:, 0], y=X[:, 1], hue=labels)
    g.set(xlim=xlim, ylim=ylim)
    plt.xlabel('x_1')
    plt.ylabel('x_2')
    plt.grid()

Визуализируем наши данные

In [18]:
plot_data_points(X, y, xlim=(-15, 15), ylim=(-15, 15))

Как видно, наши данные идеально разделяются прямой x=0

Функция plot\_knn\_bound принимает на вход объекты X, метки классов y, метод нормализации признаков scaler, число соседей n\_neighbors и границы рисунка xlim, ylim. Функция обучает KNN классификатор с числом соседей n\_neighbors и визуализирует разделяющую поверхность для классов, полученную с помощью обученного KNN классификатора.

  • Если вы не можете различить выбранные нами цвета, то измените список цветов в переменных cmap_light и cmap_bold. Актуальный список возможных цветов находится здесь
In [19]:
from matplotlib.colors import ListedColormap
from sklearn import neighbors, datasets

def plot_knn_bound(X, y, scaler=None, n_neighbors=10, xlim=(-15, 15), ylim=(-20, 20)):
    # step size in the mesh
    h = 0.05

    # Create color maps
    cmap_light = ListedColormap(['plum', 'blue', 'plum', 'green'][:np.unique(y).shape[0]])
    cmap_bold = ['plum', 'blue', 'plum', 'darkgreen'][:np.unique(y).shape[0]]

    x_min, x_max = xlim
    y_min, y_max = ylim
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    grid = np.c_[xx.ravel(), yy.ravel()]

    X_scaled = X # if scaler is None
    if scaler is not None:
        grid = scaler.transform(grid)
        X_scaled = scaler.transform(X)

    # we create an instance of Neighbours Classifier and fit the data.
    clf = neighbors.KNeighborsClassifier(n_neighbors, algorithm='brute')
    clf.fit(X_scaled, y)

    Z = clf.predict(grid)

    # Put the result into a color plot
    Z = Z.reshape(xx.shape)
    plt.contourf(xx, yy, Z, cmap=cmap_light)

    # Plot also the training points
    sns.scatterplot(x=X[:, 0], y=X[:, 1], hue=y,
                    palette=cmap_bold, alpha=1.0, edgecolor="black")
    plt.xlabel('x_1')
    plt.ylabel('x_2')
    plt.title('Разделющие поверхности алгоритма {}-NN'.format(n_neighbors))
    plt.grid()
    plt.show()

Нарисуем разделющие поверхности $1$-NN и $10$-NN

In [20]:
plot_knn_bound(X, y, n_neighbors=1)
plot_knn_bound(X, y, n_neighbors=10)

Задание 1.2 (кросс-проверка, 2 балла)

Чем отличаются поверхности, полученные при числе соседей 1 и 10? Объясните, чем вызваны данные отличия

Ваши выводы тут:

При 1 соседе поверхность имеет выраженные границы между классами. Наблюдается высокая вариативность предсказаний даже при небольших изменениях входных данных.

При 10 соседях поверхность имеет более гладкие границы, но смещение может увеличивается


Задание 1.3 (кросс-проверка, 1 балл)

Данную проблему может решить нормализация признакового пространства.

Начертите разделяющие поверхности для KNN, обученного на нормализованных признаках с помощью реализованных вами нормализаторов. Используйте функцию plot\_knn\_bound. Менять функцию plot\_knn\_bound нельзя.

In [21]:
from scalers import StandardScaler, MinMaxScaler

scaler_std = StandardScaler()
scaler_std.fit(X)
plot_knn_bound(X, y, scaler=scaler_std, n_neighbors=1, xlim=(-4, 4))
plot_knn_bound(X, y, scaler=scaler_std, n_neighbors=10, xlim=(-4, 4))

scaler_mm = MinMaxScaler()
scaler_mm.fit(X)
plot_knn_bound(X, y, scaler=scaler_mm, n_neighbors=1, xlim=(-4, 4))
plot_knn_bound(X, y, scaler=scaler_mm, n_neighbors=10, xlim=(-4, 4))

Часть 2. Кросс-валидация на задаче регрессии

Часто модели в машинном обучении имеют вид не просто какой-то функции, а какой-то функции с некоторыми, так называемыми гиперпараметрами - это такие переменные величины, которые могут существенно повлиять на качество и вид модели, но напрямую обучить их нельзя (то есть в методе fit они вообще не обучаются). Одним из примеров таких гиперпараметров является:

n_neighbors - кол-во соседей в методах kNN. Если вернуться в начало ноутбука, то можно увидеть, что имено это значение мы явно задавали, когда создавали модель с помощью класса KNeighborsClassifier.

В этот момент возникает закономерный вопрос: а как нам найти то значение гиперпараметров, при которых наша модель будет показывать более высокие результаты решения задачи?


Продолжаем проваливаться в "кроличью нору" дальше. Для того, чтобы ответить на предыдущий вопрос, нужно сначала понять следующее: а как оценивать-то собственно качество моделей? Пусть даже мы зафиксировали какой-то гиперпараметр, как нам оценивать, насколько наша модель хороша?

Чтобы уметь оценивать качество моделей ("насколько вообще хорошо мы решили задачу") хочется иметь некий "стандарт качества" - данные, которые вообще не участвовали в обучении ("модель их не видела") и верные ответы на этих данных (которые модель также не видела)

При решении прикладных задач, как правило, доступна лишь обучающая выборка, а "стандарт качества" зачастую отсутствует. Решить данную проблему нам поможет техника, называемая кросс-валиация. Данная техника позволяет создавать "стандарты качества" (тестовые наборы, выборки) используя только обучающую выборку, но не позволяя модели "подглядывать" в создаваемые тестовые наборы.

Алгоритм применения кросс-валидации

Пусть зафиксирован некоторый набор значений гиперпараметров модели. В KNN под гиперпараметрами могут пониматься число соседей n_neighbors, метрика близости \rho, стратегия выбора весов w_i.

  • При кросс-валидации обучающая выборка делится на n равных частей (folds, фолды).
  • Затем обучаются n моделей с заданными гиперпараметрами (у всех моделей гиперпараметры одинаковые и фиксированы) - $i$-ая модель обучается на всей обучающей выборке, кроме объектов, которые попали в $i$-ый фолд (out-of-fold).
  • $i$-й фолд объявляется "стандартом качества" (тестовым). Затем измеряется качество $i$-ой модели на $i$-ом фолде. Так как он не участвовал в обучении этой модели, то полученная оценка качества модели будет являться корректной.
  • Финальным значением метрики качества для модели с заданными гиперпараметрами является среднее полученных нами значений на n фолдах.

Идея: Подумайте, как в описанную выше схему корректно добавить обучение скейлеров. Корректно ли будет масштабировать сначала все данные и потом делать кросс-валидацию или все-таки нужно как-то действовать хитрее?

Собственно, теперь мы можем выбрать наилучшие гиперпараметры по следующему алгоритму:

  • Фиксируем, какие значения гиперпараметров хотим перебрать
  • Для каждого набора значений проводим кросс-валидацию
  • Для каждого набора значений сохраняем качество на кросс-валидации
  • Выбираем тот набор значений гиперпараметров, где качество оказыается наилучшим!

Принцип работы кросс-валидации схематично изображен на рисунке.

cross-val-2.png

Небольшое видео объяснение о том, как работает кросс-валидация, можно посмотреть по ссылке


Теперь применем все полученные знания на практике на примере тренировочного датасета!

Далее будем решать задачу предсказания цены дома в Калифорнии с помощью $KNN$-регрессии. Цена дома - вещественное число, поэтому наша задача - задача регрессии. В качестве метрики качества будем использовать $R^2-$score.

R^2(y\_true, y\_predict) = 1 - \frac{\sum_{i=1}^{n} (y\_true_i - y\_predict_i)^2}{\sum_{i=1}^{n} (y\_true_i - E(y\_true_i))^2}

Примечание вы же помните, что предсказания и верные ответы можно оценивать по-разному и это называется метриками качества? Если данная теория подзабылась, то освежите, пожалуйста, знания лекционным материалом

In [22]:
from sklearn.datasets import fetch_california_housing # Да, из sklearn даже можно импортировать данные
from sklearn.model_selection import train_test_split # Вспомогательная функцию которая разобьет нам датасет на 2 части
In [23]:
X, y = fetch_california_housing(return_X_y=True)

Мы разобьем выборку на 2 части: обучающую (75%) и тестовую (25%) с помощью функции train\_test\_split. По умолчанию данная функцию перемешивает данные, что часто оказывается полезно в задачах подобного рода.

Зачем мы разбиваем? Мы пытаемся "эмулировать" жизеннную ситуацию. ML-разработчику приносят данные, говорят "обучи как можно лучше", потом мы протестируем твою модель на новых данных. Вот та тестовая выборка, которую мы выделили (25%) - это те данные, в которые ни в коем случае во время обучения подглядывать нельзя, нас потом на них будут проверять!

In [24]:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)

Pipeline и перебор гиперпараметров

Кросс-валидация в skelarn, как нетрудно догадаться, уже реализована, остается научиться ее запускать :)

Но перед этим изучим еще парочку джедайских техник работы с sklearn, которые облегчат жизнь при написании моделей

In [25]:
from sklearn.neighbors import KNeighborsRegressor # kNN - регрессия
from sklearn.pipeline import Pipeline # разберем ниже
from sklearn.model_selection import GridSearchCV # класс, выполняющий кросс-валидацию
from sklearn.preprocessing import MinMaxScaler, StandardScaler # будем здесь использовать уже реализованные скейлеры

Что нам собственно нужно при решении задачи с учетом кросс-валидации?

  • Понять, предобрабатываем ли мы как-то данные или нет
  • Зафиксировать модель
  • Зафиксировать метрику качества
  • Понять, какие гиперпараметры мы хотим перебрать
  • Собственно выбрать лучший набор с помощью кросс-валидации
  • И оценить, а что на тестовой выборке-то получилось!

Шаг 1 и шаг 2 - объединяются логически - часто бывает так, что нам сначала нужно применить логику предобработки данных, а затем уже применить и обучить модель.

Логическая цепочка в таком случае будет выглдять так:

X -> предобрабатываем X -> X уходит в fit некоторой модели

sklearn Предоставляет удобное решение для составление таких цепочек-шагов обработки результатов, полученных на предыдущем шаге. Инструмент назвается Pipeline (пайплайны):

In [26]:
pipeline = Pipeline([
    ('normalizer', MinMaxScaler()),
    ('classifier', KNeighborsRegressor())
])

В данном примере вы говорим, что хотим, чтобы сначала данные отскелились, а потом, что получилось, подалось бы модели. Причем шаги этой цепочки обозначены строковыми и понятными обозначениям, которые нам скоро понадобятся

Pipeline наследует абсолютно то же интерфейс, что и остальные модули обучения в sklearn - имеет методы fit и predict! То есть получили некоторый "сборный конструктор" из различных частей.

In [27]:
pipeline.fit(X_train, y_train)
pipeline.predict(X_test)
Out [27]:
array([0.5482  , 0.7506  , 4.628604, ..., 1.328   , 2.4206  , 4.089404],
      shape=(5160,))

Далее встает вопрос: а как этот процесс обучения можно варьировать? В самом KNeighborsRegressor много гиперпараметров (число соседей, метрика расстояния и пр.), которые задаются при создании класса, а мы в Pipeline создали дефолтный экземпляр класса.. И вообще, можно же еще и перебирать, хотим ли мы использовать скейлер или нет, вдруг будет лучше без него? (а такое тоже бывает!)

И здесь sklearn нас снова выручает и дает возможность варьировать создание моделей, которые мы используем в Pipeline:

In [28]:
parameters = {
    'classifier__n_neighbors': [1, 5, 10],
    'classifier__metric': ['euclidean', 'cosine'],
    'classifier__weights': ['uniform', 'distance'],
    'normalizer': ['passthrough', MinMaxScaler(), StandardScaler()]
}

Мы можем задать такой словарик типа str -> list, который будет описывать все наши изменения, которые должны будут примениться в Pipeline (применяться они будут через класс кросс-валидации)

Если в качестве ключа написать ровно то название, которым мы обозначили шаг в Pipeline, то потом появляется возможность программно сопоставить эти два шага и заменить значения в Pipeline:

'normalizer': ['passthrough', MinMaxScaler(), StandardScaler()]

В данном случае у нас в Pipeline значения в названии шага normalizer будут меняться в соответствии с предложенными вариантам в списке

Пояснение: passthrough - ключевое слово, которые говорит sklearn "пропусти этот шаг"

А здесь уже логика чуть посложнее: у класса KNeighborsRegressor, который лежит в шаге classifier, при создании можно указать различный набор гиперпараметров, например, тот же n_negihbors. Обращаясь через двойное нижнее подчеркивание появляется возможность на лету изменять значения этих гиперпараметров в классе:

'classifier__n_neighbors': [1, 5, 10]

Здесь мы говорим "посмотри, что за модель лежит на шаге classifier, и замени у нее гиперпараметр n_neighbors в соответствии с сеткой перебора"

Задание 2.1 (кросс, 2 балла)

Запустите кросс-валидацию на 3 фолдах с помощью класса GridSearchCV и метода fit этого модуля. В качестве метрики используйте $R^2$-score (строкое представление в sklearn "r2"). Параметры для перебора описаны ниже

In [29]:
# задаем нужный пайплайн
pipeline = Pipeline([
    ('normalizer', 'passthrough'),
    ('classifier', KNeighborsRegressor())
])

# и сетку перебора параметров
parameters = {
    'classifier__n_neighbors': [1, 5, 10],
    'classifier__metric': ['euclidean', 'cosine'],
    'classifier__weights': ['uniform', 'distance'],
    'normalizer': ['passthrough', MinMaxScaler(), StandardScaler()]
}

grid_search = GridSearchCV(estimator=pipeline, param_grid=parameters, cv=3, scoring='r2', n_jobs=-1, verbose=10)
grid_search.fit(X_train, y_train)
Out [29]:
Fitting 3 folds for each of 36 candidates, totalling 108 fits
[CV 1/3; 2/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 2/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 1/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough
[CV 2/3; 1/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough
[CV 3/3; 1/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough;, score=-0.275 total time=   0.0s
[CV 1/3; 3/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler()
[CV 1/3; 2/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.509 total time=   0.0s
[CV 2/3; 1/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough;, score=-0.250 total time=   0.0s
[CV 3/3; 2/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.545 total time=   0.0s
[CV 2/3; 2/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 3/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler()
[CV 1/3; 4/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough
[CV 2/3; 3/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler()
[CV 1/3; 4/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough;, score=-0.285 total time=   0.0s
[CV 2/3; 4/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough
[CV 3/3; 4/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough
[CV 1/3; 1/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough
[CV 2/3; 4/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough;, score=-0.250 total time=   0.0s
[CV 1/3; 5/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 2/3; 2/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.544 total time=   0.0s
[CV 2/3; 5/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 3/3; 4/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough;, score=-0.275 total time=   0.0s
[CV 3/3; 5/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 1/3; 1/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough;, score=-0.285 total time=   0.0s
[CV 1/3; 6/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler()
[CV 1/3; 3/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler();, score=0.516 total time=   0.1s
[CV 2/3; 6/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler()
[CV 1/3; 5/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.509 total time=   0.0s
[CV 3/3; 5/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.545 total time=   0.0s
[CV 3/3; 6/36] START classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler()
[CV 1/3; 7/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough
[CV 2/3; 5/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.544 total time=   0.0s
[CV 2/3; 7/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough
[CV 1/3; 7/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough;, score=0.100 total time=   0.0s
[CV 3/3; 7/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough
[CV 2/3; 7/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough;, score=0.096 total time=   0.0s
[CV 3/3; 3/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler();, score=0.490 total time=   0.1s
[CV 1/3; 8/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 7/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough;, score=0.098 total time=   0.0s
[CV 2/3; 8/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 8/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 1/3; 9/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler()
[CV 2/3; 3/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler();, score=0.536 total time=   0.1s
[CV 2/3; 6/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler();, score=0.536 total time=   0.1s
[CV 2/3; 9/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler()
[CV 3/3; 8/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.691 total time=   0.0s
[CV 2/3; 8/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.692 total time=   0.0s
[CV 1/3; 8/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.691 total time=   0.0s
[CV 3/3; 9/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler()
[CV 1/3; 10/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough
[CV 2/3; 10/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough
[CV 3/3; 6/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler();, score=0.490 total time=   0.1s
[CV 1/3; 6/36] END classifier__metric=euclidean, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler();, score=0.516 total time=   0.1s
[CV 3/3; 10/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough
[CV 1/3; 11/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 1/3; 10/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough;, score=0.120 total time=   0.0s
[CV 2/3; 11/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 3/3; 11/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 2/3; 10/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough;, score=0.120 total time=   0.0s
[CV 1/3; 12/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler()
[CV 3/3; 10/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough;, score=0.119 total time=   0.0s
[CV 2/3; 12/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler()
[CV 1/3; 11/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.695 total time=   0.0s
[CV 3/3; 12/36] START classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler()
[CV 3/3; 11/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.697 total time=   0.1s
[CV 1/3; 13/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough
[CV 2/3; 11/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.698 total time=   0.1s
[CV 2/3; 13/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough
[CV 1/3; 13/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough;, score=0.116 total time=   0.0s
[CV 3/3; 13/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough
[CV 2/3; 13/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough;, score=0.114 total time=   0.0s
[CV 1/3; 14/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 13/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough;, score=0.118 total time=   0.0s
[CV 2/3; 14/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 1/3; 9/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler();, score=0.668 total time=   0.2s
[CV 3/3; 14/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 2/3; 9/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler();, score=0.701 total time=   0.1s
[CV 1/3; 15/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler()
[CV 3/3; 9/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler();, score=0.669 total time=   0.2s
[CV 2/3; 15/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler()
[CV 2/3; 12/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler();, score=0.705 total time=   0.1s
[CV 1/3; 14/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.694 total time=   0.1s
[CV 3/3; 15/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler()
[CV 1/3; 16/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough
[CV 2/3; 14/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.698 total time=   0.1s
[CV 2/3; 16/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough
[CV 1/3; 12/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler();, score=0.673 total time=   0.1s
[CV 3/3; 16/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough
[CV 1/3; 16/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough;, score=0.141 total time=   0.0s
[CV 1/3; 17/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 3/3; 14/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.695 total time=   0.1s
[CV 3/3; 17/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 2/3; 16/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough;, score=0.143 total time=   0.0s
[CV 3/3; 16/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough;, score=0.145 total time=   0.0s
[CV 2/3; 18/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler()
[CV 3/3; 12/36] END classifier__metric=euclidean, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler();, score=0.672 total time=   0.1s
[CV 1/3; 19/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough[CV 3/3; 19/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough

[CV 1/3; 17/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.702 total time=   0.1s
[CV 2/3; 17/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 3/3; 17/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.703 total time=   0.1s
[CV 1/3; 18/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler()
[CV 2/3; 17/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.706 total time=   0.1s
[CV 1/3; 15/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler();, score=0.677 total time=   0.2s
[CV 2/3; 15/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler();, score=0.708 total time=   0.2s
[CV 2/3; 20/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 15/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler();, score=0.673 total time=   0.2s
[CV 1/3; 21/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler()
[CV 3/3; 21/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler()
[CV 2/3; 22/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough
[CV 2/3; 18/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler();, score=0.713 total time=   0.2s
[CV 3/3; 18/36] START classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler()
[CV 1/3; 18/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler();, score=0.683 total time=   0.2s
[CV 1/3; 23/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 3/3; 18/36] END classifier__metric=euclidean, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler();, score=0.679 total time=   0.2s
[CV 3/3; 23/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 1/3; 23/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.450 total time=   1.7s
[CV 2/3; 23/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 3/3; 21/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler();, score=0.458 total time=   1.9s
[CV 1/3; 22/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough
[CV 2/3; 20/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.458 total time=   1.9s
[CV 3/3; 20/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 1/3; 21/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler();, score=0.472 total time=   1.9s
[CV 2/3; 21/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler()
[CV 2/3; 22/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough;, score=0.102 total time=   1.9s
[CV 3/3; 22/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough
[CV 1/3; 19/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough;, score=0.078 total time=   2.2s
[CV 2/3; 19/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough
[CV 3/3; 19/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough;, score=0.135 total time=   2.2s
[CV 1/3; 20/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 23/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.470 total time=   1.8s
[CV 1/3; 24/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler()
[CV 2/3; 23/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.458 total time=   0.8s
[CV 2/3; 24/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler()
[CV 1/3; 22/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough;, score=0.078 total time=   0.8s
[CV 1/3; 25/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough
[CV 3/3; 20/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.470 total time=   0.8s
[CV 3/3; 25/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough
[CV 3/3; 22/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=passthrough;, score=0.135 total time=   0.8s
[CV 2/3; 21/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=StandardScaler();, score=0.509 total time=   0.8s
[CV 2/3; 26/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 1/3; 27/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler()
[CV 2/3; 19/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=passthrough;, score=0.102 total time=   0.8s
[CV 3/3; 27/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler()
[CV 1/3; 20/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.450 total time=   0.9s
[CV 2/3; 28/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough
[CV 1/3; 24/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler();, score=0.472 total time=   0.9s
[CV 1/3; 29/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 2/3; 24/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler();, score=0.509 total time=   0.5s
[CV 3/3; 24/36] START classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler()
[CV 3/3; 24/36] END classifier__metric=cosine, classifier__n_neighbors=1, classifier__weights=distance, normalizer=StandardScaler();, score=0.458 total time=   0.6s
[CV 3/3; 29/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 1/3; 27/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler();, score=0.657 total time=   1.1s
[CV 2/3; 27/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler()
[CV 1/3; 25/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough;, score=0.382 total time=   1.2s
[CV 2/3; 25/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough
[CV 2/3; 26/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.639 total time=   1.2s
[CV 3/3; 26/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 25/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough;, score=0.385 total time=   1.2s
[CV 1/3; 26/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 3/3; 27/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler();, score=0.648 total time=   1.2s
[CV 1/3; 28/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough
[CV 2/3; 28/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough;, score=0.390 total time=   1.3s
[CV 3/3; 28/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough
[CV 1/3; 29/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.641 total time=   1.2s
[CV 2/3; 29/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 3/3; 29/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.649 total time=   1.1s
[CV 1/3; 30/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler()
[CV 2/3; 27/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=StandardScaler();, score=0.687 total time=   1.3s
[CV 2/3; 30/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler()
[CV 3/3; 26/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.647 total time=   1.2s
[CV 1/3; 31/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough
[CV 2/3; 25/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=passthrough;, score=0.367 total time=   1.4s
[CV 3/3; 31/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough
[CV 1/3; 26/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.643 total time=   1.4s
[CV 2/3; 32/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 1/3; 28/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough;, score=0.393 total time=   1.4s
[CV 1/3; 33/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler()
[CV 2/3; 29/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.642 total time=   1.3s
[CV 2/3; 33/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler()
[CV 3/3; 28/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=passthrough;, score=0.404 total time=   1.4s
[CV 3/3; 33/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler()
[CV 1/3; 30/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler();, score=0.660 total time=   1.4s
[CV 1/3; 34/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough
[CV 2/3; 30/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler();, score=0.688 total time=   1.7s
[CV 3/3; 30/36] START classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler()
[CV 1/3; 31/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough;, score=0.378 total time=   1.7s
[CV 2/3; 31/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough
[CV 3/3; 31/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough;, score=0.388 total time=   1.7s
[CV 1/3; 32/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 2/3; 32/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.658 total time=   1.7s
[CV 3/3; 32/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler()
[CV 1/3; 33/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler();, score=0.665 total time=   2.0s
[CV 2/3; 34/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough
[CV 3/3; 33/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler();, score=0.664 total time=   1.9s
[CV 3/3; 34/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough
[CV 2/3; 33/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=StandardScaler();, score=0.700 total time=   2.1s
[CV 1/3; 35/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 1/3; 34/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough;, score=0.405 total time=   1.4s
[CV 2/3; 35/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 3/3; 30/36] END classifier__metric=cosine, classifier__n_neighbors=5, classifier__weights=distance, normalizer=StandardScaler();, score=0.650 total time=   1.7s
[CV 3/3; 35/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler()
[CV 1/3; 32/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.660 total time=   1.6s
[CV 3/3; 32/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=MinMaxScaler();, score=0.661 total time=   1.6s
[CV 1/3; 36/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler()
[CV 2/3; 36/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler()
[CV 2/3; 31/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=uniform, normalizer=passthrough;, score=0.366 total time=   1.8s
[CV 3/3; 36/36] START classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler()
[CV 2/3; 34/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough;, score=0.403 total time=   1.6s
[CV 3/3; 34/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=passthrough;, score=0.419 total time=   1.7s
[CV 1/3; 35/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.664 total time=   1.7s
[CV 2/3; 35/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.665 total time=   1.7s
[CV 3/3; 35/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=MinMaxScaler();, score=0.667 total time=   0.9s
[CV 1/3; 36/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler();, score=0.673 total time=   0.9s
[CV 3/3; 36/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler();, score=0.669 total time=   0.9s
[CV 2/3; 36/36] END classifier__metric=cosine, classifier__n_neighbors=10, classifier__weights=distance, normalizer=StandardScaler();, score=0.706 total time=   1.0s
GridSearchCV(cv=3,
             estimator=Pipeline(steps=[('normalizer', 'passthrough'),
                                       ('classifier', KNeighborsRegressor())]),
             n_jobs=-1,
             param_grid={'classifier__metric': ['euclidean', 'cosine'],
                         'classifier__n_neighbors': [1, 5, 10],
                         'classifier__weights': ['uniform', 'distance'],
                         'normalizer': ['passthrough', MinMaxScaler(),
                                        StandardScaler()]},
             scoring='r2', verbose=10)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GridSearchCV(cv=3,
             estimator=Pipeline(steps=[('normalizer', 'passthrough'),
                                       ('classifier', KNeighborsRegressor())]),
             n_jobs=-1,
             param_grid={'classifier__metric': ['euclidean', 'cosine'],
                         'classifier__n_neighbors': [1, 5, 10],
                         'classifier__weights': ['uniform', 'distance'],
                         'normalizer': ['passthrough', MinMaxScaler(),
                                        StandardScaler()]},
             scoring='r2', verbose=10)
Pipeline(steps=[('normalizer', MinMaxScaler()),
                ('classifier',
                 KNeighborsRegressor(metric='euclidean', n_neighbors=10,
                                     weights='distance'))])
MinMaxScaler()
KNeighborsRegressor(metric='euclidean', n_neighbors=10, weights='distance')

Посмотрим на результаты кросс-валидации. Посмотреть результаты можно удобно через аттрибут cv_results_:

In [30]:
for elem in zip (grid_search.cv_results_['params'], grid_search.cv_results_['mean_test_score']):
  print(elem)
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 1, 'classifier__weights': 'uniform', 'normalizer': 'passthrough'}, np.float64(-0.2698362539419594))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 1, 'classifier__weights': 'uniform', 'normalizer': MinMaxScaler()}, np.float64(0.5329368736058075))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 1, 'classifier__weights': 'uniform', 'normalizer': StandardScaler()}, np.float64(0.5139255367340351))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 1, 'classifier__weights': 'distance', 'normalizer': 'passthrough'}, np.float64(-0.2698362539419594))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 1, 'classifier__weights': 'distance', 'normalizer': MinMaxScaler()}, np.float64(0.5329368736058075))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 1, 'classifier__weights': 'distance', 'normalizer': StandardScaler()}, np.float64(0.5139255367340351))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 5, 'classifier__weights': 'uniform', 'normalizer': 'passthrough'}, np.float64(0.0977684191856583))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 5, 'classifier__weights': 'uniform', 'normalizer': MinMaxScaler()}, np.float64(0.6915621333110309))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 5, 'classifier__weights': 'uniform', 'normalizer': StandardScaler()}, np.float64(0.6793573692425973))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 5, 'classifier__weights': 'distance', 'normalizer': 'passthrough'}, np.float64(0.1199731657678866))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 5, 'classifier__weights': 'distance', 'normalizer': MinMaxScaler()}, np.float64(0.6964752425342952))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 5, 'classifier__weights': 'distance', 'normalizer': StandardScaler()}, np.float64(0.6834229913464561))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 10, 'classifier__weights': 'uniform', 'normalizer': 'passthrough'}, np.float64(0.1157913069850766))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 10, 'classifier__weights': 'uniform', 'normalizer': MinMaxScaler()}, np.float64(0.6955574490923349))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 10, 'classifier__weights': 'uniform', 'normalizer': StandardScaler()}, np.float64(0.6860471330995802))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 10, 'classifier__weights': 'distance', 'normalizer': 'passthrough'}, np.float64(0.14310059566240177))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 10, 'classifier__weights': 'distance', 'normalizer': MinMaxScaler()}, np.float64(0.7035316821435433))
({'classifier__metric': 'euclidean', 'classifier__n_neighbors': 10, 'classifier__weights': 'distance', 'normalizer': StandardScaler()}, np.float64(0.691615057187545))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 1, 'classifier__weights': 'uniform', 'normalizer': 'passthrough'}, np.float64(0.10527040776150857))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 1, 'classifier__weights': 'uniform', 'normalizer': MinMaxScaler()}, np.float64(0.4590323476108448))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 1, 'classifier__weights': 'uniform', 'normalizer': StandardScaler()}, np.float64(0.47958515234726945))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 1, 'classifier__weights': 'distance', 'normalizer': 'passthrough'}, np.float64(0.1052704077615086))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 1, 'classifier__weights': 'distance', 'normalizer': MinMaxScaler()}, np.float64(0.4590323476108448))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 1, 'classifier__weights': 'distance', 'normalizer': StandardScaler()}, np.float64(0.47958515234726945))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 5, 'classifier__weights': 'uniform', 'normalizer': 'passthrough'}, np.float64(0.37805502479959713))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 5, 'classifier__weights': 'uniform', 'normalizer': MinMaxScaler()}, np.float64(0.6429483717302537))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 5, 'classifier__weights': 'uniform', 'normalizer': StandardScaler()}, np.float64(0.6639133943561187))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 5, 'classifier__weights': 'distance', 'normalizer': 'passthrough'}, np.float64(0.3955985736693544))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 5, 'classifier__weights': 'distance', 'normalizer': MinMaxScaler()}, np.float64(0.6439729194747269))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 5, 'classifier__weights': 'distance', 'normalizer': StandardScaler()}, np.float64(0.666103286084983))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 10, 'classifier__weights': 'uniform', 'normalizer': 'passthrough'}, np.float64(0.3775295488771868))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 10, 'classifier__weights': 'uniform', 'normalizer': MinMaxScaler()}, np.float64(0.6595874224717159))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 10, 'classifier__weights': 'uniform', 'normalizer': StandardScaler()}, np.float64(0.6765890035252449))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 10, 'classifier__weights': 'distance', 'normalizer': 'passthrough'}, np.float64(0.4089433531052468))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 10, 'classifier__weights': 'distance', 'normalizer': MinMaxScaler()}, np.float64(0.6650747099452051))
({'classifier__metric': 'cosine', 'classifier__n_neighbors': 10, 'classifier__weights': 'distance', 'normalizer': StandardScaler()}, np.float64(0.6829471618912982))

Задание 2.2 (кросс, 1 балл)

Какой наибольший r2\_score удалось достичь на кросс-валидации? Какие закономерности вы видите?

  • Обучите модель с наилучшими параметрами на всей обучающей выборке
  • измерьте r2\_score на тестовой выборке.
In [31]:
from sklearn.metrics import r2_score # изучите самостоятельно, как с помощью этой функции измерять качество

print("Максимальный r2_score ", grid_search.best_score_)
print("Лучшие параметры ", grid_search.best_params_)

best_model = grid_search.best_estimator_
best_model.fit(X_train, y_train)
y_pred = best_model.predict(X_test)

test_r2 = r2_score(y_test, y_pred)

print("r2_score на тестовой выборке ", test_r2)
Максимальный r2_score  0.7035316821435433
Лучшие параметры  {'classifier__metric': 'euclidean', 'classifier__n_neighbors': 10, 'classifier__weights': 'distance', 'normalizer': MinMaxScaler()}
r2_score на тестовой выборке  0.7117082182374788

Ваши выводы тут:

Лучшие параметры модели:

n_neighbors=10

weights=distance

metric=euclidean

Нормализация с использованием MinMaxScaler

Модель показала хорошее качество: R^2 около 0.7 говорит, что 0.7 дисперсии целевой переменной объясняется моделью.

Таким образом:

Увеличение числа соседей до 10 дало лучший баланс.

Использование весов 'distance' улучшает качество по сравнению с равными весами.

Евклидова метрика оказалась эффективнее других

Нормализация данных (MinMaxScaler) важна для метрических методов.

Поздравляем с первой обученной моделью машинного обучения!