Spec-Zone.ru › scikit-learn

3.1. Перекрестная проверка: оценка производительности оценщика

Обучение параметров функции прогнозирования и тестирование её на тех же данных – методологическая ошибка: модель, которая просто повторяет метки увиденных образцов, будет иметь идеальный результат, но не сможет предсказать ничего полезного на ещё невиденных данных. Эта ситуация называется переобучением. Чтобы избежать этого, при проведении эксперимента с машинным обучением (с учителем) принято оставлять часть доступных данных в качестве тестовой выборки X_test, y_test. Обратите внимание, что слово «эксперимент» не предназначено для обозначения только академического использования, поскольку даже в коммерческих условиях машинное обучение обычно начинается с экспериментального этапа. Вот блок-схема типичного рабочего процесса перекрестной проверки при обучении моделей. Лучшие параметры можно определить с помощью техник поиска по сетке.

<img alt="Поток работы поиска по сетке" class="align-center" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB+8AAAVSCAMAAADw+UkEAAAAb1BMVEVHcEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACHisMAAABUVnpjZY8HCAtISmgbGycRERhzdaYoKTshIjBsb52Dhr4tLkE2N05cXoU+QFp+gbZ4e65oapbe35nyAAAAEXRSTlMAVQxmH8p355WF4z612qMq8GTz8g0AACAASURBVHja7N1bk6pWAoDReUilpqYyNdXNXUBu/v/fON0KtsBG6fQ5HU+yvrckBrXLvRdsEP/1Ku3u939Jy/5tYGh3/zFg/sJ8/sR78V68573Ee/FevOe9eC/eS7znvXgv3ku85714L96L9+K9eC/ei/fivXgv3ov32u99Gktb5bzXQ+9LA0Wbdbx/Iu/jF2mrjPd66P3RQNFmEe95L96L9+K9eC/ei/fivXgv3ov34r14L96L9+K9eC/ei/fiPe8l3ov34j3vxXvxnvfiPe/Fe/Fe4j3vxXvxXrwX78V78V68F+/Fe/FevBfvxXvxXrwX78V78V68573Ee/FevOe9eC/xXrznvXgv3ku85714L96L9+K9eC/ei/fivXgv3ov34r14L96L9+K9eC/ei/e8l3gv3ov3vBfvJd6L97wX78V7ife8F+/Fe/FevBfvxXvxXrwX78V78V68F+/Fe/FevBfvxXvxnvcS78V78Z734r3Ee/Ge9+K9eC/xnvfivXgv3ov34r14L96L9+K9eC/ei/fivXgv3ov34r14L97zXuK9eC/e8168l3gv3vNevBfvJd7zXrwX78V78V68F+/Fe/FevBfvxXvxXrwX78V78V68F+/Fe95LvBfvxXvei/cS78V73ov34r3Ee96L9+K9eC/ei/fivXgv3ov34r14L96L9+K9eC/ei/fivXjPe4n34r14z3vxXuK9eM978V68l3jPe/FevBfvxXvxXrwX78V78V68F+/Fe/FevBfvxXvxnvcS78V78Z734r3Ee/Ge9+K9eC/xnvfivXgv3ov34r14L96L9+K9eC/ei/fivXgv3ov34r14L97zXuK9eC/e8168l3gv3vNevBfvJd7zXrwX78V78V68F+/Fe/FevBfvxXvxXrwX73kv8V68F+95L95LvBfveS/ei/cS73kv3ov34r14L96L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

В scikit-learn случайное разделение на обучающую и тестовую выборки можно быстро вычислить с помощью вспомогательной функции train_test_split. Давайте загрузим набор данных iris, чтобы подогнать к нему линейную машину опорных векторов:

>>> import numpy as np
>>> from sklearn.model_selection import train_test_split
>>> from sklearn import datasets
>>> from sklearn import svm

>>> X, y = datasets.load_iris(return_X_y=True)
>>> X.shape, y.shape
((150, 4), (150,))

Теперь мы можем быстро получить обучающую выборку, оставив 40% данных для тестирования (оценки) нашего классификатора:

>>> X_train, X_test, y_train, y_test = train_test_split(
...     X, y, test_size=0.4, random_state=0)

>>> X_train.shape, y_train.shape
((90, 4), (90,))
>>> X_test.shape, y_test.shape
((60, 4), (60,))

>>> clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train)
>>> clf.score(X_test, y_test)
0.96...

При оценке различных настроек («гиперпараметров») для оценок, таких как настройка C, которая должна быть установлена вручную для SVM, всё ещё существует риск переобучения на тестовой выборке, потому что параметры могут быть настроены до достижения оптимальной работы оценщика. Таким образом, знания о тестовой выборке могут «просочиться» в модель, и показатели оценки больше не отражают обобщающую производительность. Чтобы решить эту проблему, можно выделить ещё одну часть набора данных в качестве так называемой «валидационной выборки»: обучение происходит на обучающей выборке, после чего оценка производится на валидационной выборке, и когда эксперимент, похоже, удался, окончательная оценка может быть произведена на тестовой выборке.

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

Решение этой проблемы — процедура, называемая кросс-валидацией (КВ). Тестовую выборку по-прежнему следует оставить для окончательной оценки, но валидационная выборка больше не нужна при выполнении КВ. В базовом подходе, называемом k-кратной КВ, обучающая выборка разделяется на k меньших наборов (другие подходы описаны ниже, но, как правило, следуют тем же принципам). Следующая процедура выполняется для каждого из k «слоёв»:

  • Модель обучается с использованием \(k-1\) слоёв в качестве обучающих данных;
  • полученная модель оценивается на оставшейся части данных (то есть используется в качестве тестовой выборки для вычисления показателя производительности, такого как точность).

Показатель производительности, сообщаемый k-кратной кросс-валидацией, затем является средним значением вычисленных в цикле значений. Этот подход может быть вычислительно дорогостоящим, но не тратит слишком много данных (как это происходит при фиксировании произвольной валидационной выборки), что является значительным преимуществом в таких задачах, как обратный вывод, где количество образцов очень мало.

<img alt="Изображение 5-кратной перекрестной проверки на обучающей выборке, при этом тестовая выборка оставлена в стороне." class="align-center" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA3UAAAJlCAMAAABKcSs9AAACWFBMVEVHcEw3aKY4aqU7caUzZaU1ZaU8aqc1YqU8c6ctaaU8b6djrLZLh6w9c6cAAAAAAAAAAAAAAAA7bqw5bac3Z6Q0ZaQ2baQ9cKg3ZKQ7b6cAAAAAAAA8cKk/d6g8cag3aKU7cKcAAAAAAAA5bKoAAAAAAAAAAAAAAAAAAAA5bKoAAAAAAAAAAAAAAAAAAAAAAABYk81GfLgAAAAAAAAIDRUAAAAAAAA/bak8cK9JdKw9bqoAAAAAAAAAAAAAAAAAAAARHS9Aa6RLcKNEcas6bqY2aKU0ZaWZypnu7u6Z/8yDyv//zJkAAAA0ZaSS9soKDgxMf2ZxwbwBAgKE4MQEBgVPg2mB16yY/sx5eXkSGhiJ5sUrRzkICwwtSzx+xPkTIBsyU0J4zL+C3cNyxL191cFIeGAbLCcXJyBztu2V+cdkotyX/MoQFRUOEhDT2N+U9sWJ5bc3W0kWIidEPzp3uu/m5+hkp4YhNEKR88LJycmCyf88ZE8nQTSN67wiOS5NTU1srONuqtdBZX9WkHNDaIMnPExCb1msvtQhHx4rQlRdXV0pKCZut5JVhKeG7I4My7s7OxdkLU/alRrs490wZvK0Nl8z6ZcU0ofNCo1Umhal3gwSl1JRkM0WEY4Xkt0tOMwUEBFc1xnrImenp55yqGpqal9wfRTim9hooLeu5uIiIi4k267ydqByPxqpNBqamo+YHlenH1xcXFPeZl6YUmVlZU6WnHnuYrAwMDh4eHUqn/4xpW1tbVio4JimsCmhWORdFdCZYB/1KlKcpFHbotFaoYzVURHcExYkusNAAAAyHRSTlMA+vald0T3IvIR2vzx83wYxYDz4yr+Dckcqe+xufLX9/RK5dmKcabb9qRXCvvSvCf88ZQ+A51h4/Hx9B8xhWsPBuPxufdnOv//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AF5MbIQAACAASURBVHja7NzvTxv3HcBx+mRTn0yrWpZ03Q9tedCt+/Fkldqu1VRpTzD6REbWl+JbHNwn2EH4CDEQIEBYQmGU3ySh4JiEJhSoovEjIKwgkUpplv9rd98z9h0Y/GOxYc379QCTT447FXjrvnfnpqrq5TtzHsCRqssQXdUHrTUAjvIR1QFUB1Ad1QFUB1Ad1QFUB1AdAKoDqA6gOqoDqA6gOqoDqA6gOlRaUILpD6A6lNH0iJiduavrEZsy2oO5fiRLS3zzqA4lWZYR2TmqOjUwMLAwFhCV4/w3MsA3j+pQkgXZk6mjqvPr192gko2DX9cqVEd1KMlsYKqmXZ4cW11NzZ6SPeulMzgWUsborPXpgL34NDwjUB0KsmUtL5dkNE91NRuyYF0CtsvYxsaUxKyf0PKojD3a8YxAdShEpxnatT6o3TzVPRE1bV0CjnXq09yGvh4c0B9dI1AdCrCjT3Mb8ihPddMirTWzy/Yy0zo1LmSq84xAdSjAlL5e65GR6eOrqwlJj3NnpbV1Sdoz1XlGoDrktydj6fiWj6+uU8RahC63h/QjPFd17hGoDvnNyb6BY6ub3pPYtLUcVaM7y8tBV3WeEagOebUqNeoIBWaPPdfN2dd/I7LkXMRlq/OMQHXIKyhz6c9GZeu46pZE9dh3VKadbTPVeUegOuQzbeh7KbYnEus89r0p9k3OmH6avmToi0HnHS2eEagO+Sy5Wpmyloq534c5MKVE6ScLW2IEgwvmEyVbe9bqVOZGdz0jUB3yaXce02k71qkr9/9zIObUlvMj6QyOKGOup+aR6be+8FFMjex6R6A6gOqoDqA6gOqoDqA6gOoAqqM6gOoAqqM6gOoAqqM6gOoAqgNAdcAPqroz5wEcqboKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApxr/4jqO/MfGz6Z/Sc7xL66/XG/+wwfk9Mu39n9JOmpfWR9SHaiO6kB1VEd1oDqqA9VRHdWB6qgOVEd1ANVRHaiO6kB1VEd1oDqqA9VRHdWB6qgOVEd1r4w6qc87OUZAqO4EBYTqTmFSLndybjIYHsw7Ka66q1eprkg33T+n747aamKikOpybEV1FfX0oqVPlP1y8ftyHCFHddGvqa5IE0OWLlH2y9CNo7YKDxVSXY6tqK7yvpdY+XZ+uLp+obqSrIt57N93SCHV5dqK6k6wunp5/DSs2ny+y3WRkDLuT2au4qy/mbwXU+H6lpwTX1tvTEUHG8LSnNlr231rVN/iVOfa4T17kWR4j0F1xVU30WV96xKL+vOZLjNgdm1fq/3S/sbG9jdeTJoq/sWaU93Ks7hSseQ/rU/3t3KNqO5Eq1uV4dDXvf2+lgsSHX5wXcy2/cZWpSl2ffie0vdRDk+6ozJfN2w+8EvD/k67wzLfNBy9ouzq3DscvyWRwcfeY1BdUdUlxJ+6OSR+e6k5If7kzZQhidqZhMSfb6e3XTEkspmKJ5Vd3VqXxFOpiJhWp+mt3COqO9HqBsX/rf16W6KXrZfP5cF+Y4OiVu37IBLOOamXPuuUN2m4lpPOqPm6yMEdjusVpmdEdcVUNyNxe//PJWJ9jMu6HVnc32HNs2vHF9K1Vlvb2CXifEGjPs2l9B+GDo6o7mSrC+vXydvf6HuNciHbWNQ+izUHpCXXZF7G7S+4K9nq5uW2TycmB3foVOcZUV0x1Q2Jvgt5LS7Wyc4QfXOlMdOTIyIzTqB2dYsz+rbnRLq3oYMjqjvZ6u5nht39bQ+lL1ud8zd+6c41UdKva3VVp6TNuXUiB3c4nrmbkhlRXTHV+cVZFibt+lJiPE+vEt3VKWebDtm/m7Jy6dKEdHm2yoyo7mSrSy/3xvtC+smQq7qmQ9VlJ5fFuZ5ryVZnjewFpK/BGbl3mK7OPaK6Iqpbyz65e2H9KaVEjMS6t7oVkUZ9PnSqm+lSentXde4R1Z1sdU5Jj0Xdenp7fLXQ6rrT1TUEDlXnhOjZoVOdZ0R1xVWX2nToVWLHdtIU2cxZ3ZqubltUYmJm5j+u6jwjqjsN1YXlof3ysNDqGtIrzLbDK0xn5NmhU51nRHXFrDBNOficfGGL+u5VpiLujrDuRB0rzA9I6o7BdVZ5yf9EK630Op8UefdZO67KRHnbspVe+Tdoa7OO6K64u6mOM8H9EEWnYu6lDVzVxd37qZM2NVZJ7w154FDpjrviOpOw7kuJl/ZwRgSKbC6B/K5fV4Lu54cNOknB90RHaJnh3fk+sER1RX35MCwU1uMGY21NySy4jyRm6n9zpXQpn5ysBLX5zpTP12YiEncenG28oyo7jRU1yRG3eoF8yslTXcKqq7NlL6mW2a9ylbXb/V0677Ra8rBHbYF5Epvv2dEdcU+JU88S4b0KS8hscRmKm5HdikgyUT6yB1WT4lkLOkXnaDx7MWQf12JdSXobOUZUd1pqK65PqqMK5/5Bk3/3YKq83120R+af+pzVeebvGeqaF2LfpOYZ4e+uzEV7veOqK7Id4T5A+aQzuXadpcZCEVe2DdPtmPK2D/y4pd+FX62Zth3VRq/iKtY8kbtc39oO72Vd0R1/8daJPRK//fzf7VSXQX1j+s3mnzzQ7pIozqqO90eSsRaZzZfSK86qY7qqK78S8s+CQ8PRyTaTXVUR3UVcnk14lfRB/0+qqM6qgPVUR2ojuqoDlRHdaA6qqMUB3VgeqoDqA6qgPVUR2ojur+B2fOA7lVn03/kpx7lb8JVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8Pn29/H52Qkd7n6O9pKPh5Tr32o/K7s3M0c5U4Gi/zhztFxU42muZX823K3G01/eP9vsKHK36x/RRHh+01pRbZ7aDX82W/Wg11dnG/13+o2Wr+/u/yn+0v57NVFeBo330Fn1QHdVlq3ub6qiO6qgOVEd1VEd1VEd1oDqqK7S637z75zc+oRWqo7oKVveeWP70HrVQHdVVtjqRdz6mF6qjukpd1336yU/etbL77V8IhuqornJ3U97/289F/sgqk+qorpL3MD/+KdmdTHVBCWb/EJAyV1fK0UqvrqSjlV5dKYcrvbpSjnbwycEf3hH5HYvMMlXXIxn/Ze9uf5rK8jiAd7PJbvaNYiab3WlnswsrhVXQBMQ3IvqyJb9Nm5uL9MYq7ANtCAUZsDwo0J1hxpQWaQUUEVEcKJomiGKYQMJsMjuz83ftfeoDCs6559zb7Ivv94VAAb+59Hzac8+5hTT7nTeeoSUedVxtueGArCT2rKvjaYvnMzG17YBDHd+P0ufLDlPCujqOtuK3JBj2666q7NxYUnFKnfzUTIp1qGTzssyrznpbiuThpTRJOQ51ltv2MxRLJNJE6zzqrB+c/tMkPnWW2w5ISejJs+ySn1UnmVUXoMYZdQHLE5UEpXZ51VluWydlXB2aO5TkUGe5bZuexvVPK1kOdQGeOd+enOFTZ7ktRynmGaZ2bucmqoWaSqjLZ9Tp3NJe6c4bSMXkZChbPlSG11ULtqhjaFsi/ZE5LtOAqDqGtlBi3GzbF1bH8qNUq9KxnB3qGNp2aduKOm3rrh5zTOfVZROUTIUSspwr3Hn7ScrsbKeX5PJzH5896hjb4vqbgKg6tjYjAxTzCapjrdum3J64Oqa2fPlzIIM6l3pq5wUbx9XtUnrfmNVlzTsvRMPqu/EMHR6ZtqhjbtPPSTKCM0zmtux+LintiqpjrNNmfTaoY2rboZ2UIseOXJg6Ut2lepLOw43T6obNVYQ0HZh3XoZyxuBwQB1zm/bILR0IqmNtyxNJqT2fqDq2uoFYct8OdUxt26QtFSVJXmdU5zqNJzundw7USX+YHprrhnnzzjNOp7L7dqnjavONp2lXaOfAQlvuaSYsJwaEdg6Y655qDyZ7gjsHjG3ZfCKkztazIQrvM6o7WU8NOLNzZOdg2EzeFyeKF+Yixp1XuCVrlzqutlz/UQ/PLDsHPG3qUYQoGefZObBaZ5xpcarjPDjtaXCXUZ2riegy4Dg7w6yAOo62bF5K7vm41HEdm/4cdNSGnZUZJlPduJzJ8qvjPrht7YvY1J2XqAZ7dg6f1wWOmaj4Bpw4r2Ns26HMgE9YHVNbPLdeGJghwfM6lrpQaZaYFDuvY77jjC8KsapzVRHhujDHV1N23zspTxsn5evOrKawtIWMjWthdSxt2QCNm1+cF15N+fm63LaeFCW3Q6KrKQwHl0jrAyBrfopJXS1RE+Q4q27dWIDepXRhAXpHX4DeTzuhjqntgNJxnx3qmNpSxvPqLskPBdUx/yjtmGGytSUooa2mbJMSZ1Z3iagOchy+NmVJe9hNSIG9wmbrgELpVEpJ9ZfuvL1EIpGhpPpvTvDaFJa2DKWNiwePuiLZ0rUpLG0DaQoPa9dh5kV3DpjqbFPHdnBJ7ULMJAUOfMzqXHVEWMV0WF12NxOWk6mHpQuLHib6tQuLkhQvbewWkhdUx9KWLLbtCqpjafPth9QvinG+5sB6nW3q2A5uJy3Lye2HPgvqWojwOju71dkcvKrVtjjwqtasz9oVYVouYu8A6qDOmRyrrpXIAzpQB3WVVHeFqBF0oA7qKqnO5SY36EAd1FVUXR0Rrk6BOqirqLpGoiuwA3VQV0l1VUQnYQfqoA7qoA7qo6BOqiDOqiDOqiDOqiDOqirTP78V+fzSclBBdpKxj+rQFtJ3V8q0Pbb31S07ddQhyD/L4E6BIE6BIE6BEGgDkGgDkEQqEMQqEMQBOoQBOoQBOoQBIE6BIE6BEGgDkGgDkEQqEMQqEMQqEMQBOoQBOoQBIE6BIE6BEGgDkGgDkGgDj8FBIE6BIE65Lj8rqK/cb0SvwP9V8W2Tyvx+92vFtoq8TvQ/1jR37j+i99DnTP55Ha707lZ9tdF/u53Op1lf13kn463+Ut/5+Czvznf9qeig1/+w/m2P+Cvi0Ad1JWp+xTqoA7qoA6BOqiDOqiDOqhDoA7qoA7qoA7qoA7qoA7qoA7qoA7qoA7qEKiDOqirZE7QKZfrFJ1wVt1X9GXpA4kcVtdBwdIHEjmsjqdNQB1PHb86njaoM3PpdFVNQ32dt/podbU1beq7Z86Uf+J8FXmtqfuCihliV/fFKK3wqLtWaosyD5WFiYCsrG5YV8fTdmt6ql9WflrkUMd1cNpRTFC3dXUcbcVv6Ya641JdT3XeJm8j0ekj1Rmp85RuvlBb32BdnfS1mWVWdVs/yjKvOumGmXnWgXmX5OurEZIWONRZbhubov41tY1GeNRZPzgtL4lPneW2RVK69byEumNy1k1thr4Gaj1W3UkqU+ehlovW1YUtzzC/ppV3vOoCVqdFI6TMqb6C1MWhznLbPbpxS4egdHKoC/DM+R7Jj/nUWW5boLuYYX48rVRXMNbS7HJdpout59z1jRcPndd5tflCTeFbzp1xnRFUt/VuNCzHVl6X1D1f6ZeHvtoqVzd6v/2+Ler6nkxpk8dHpaEy+CwmRzv6yobKKj3R3vRKNCmojqUt2H3NbBsTVcdSp01pI/2zNqhjaXtFL6Du4zlP7rNlH56iJrfntLdeX0Ipqqtuosa2i8WnR5eoujszpCx/PyPLDwrqNhWKvPl2aEUuU7fZbo+6zm/qmg+uyvJsYaiMddHjnnvRz+Wygdnbq78JiKpjazMySDG/oDrWunlaeCSujqltmjqg7uO50EhVzeWTSknT1Uz1V8rXMKvLZ5guYXX3aWhTfxPbMtX9l0bVd2+O0uE1TFvUvaKI9ozyDSl95lDpoAn13d4p+sDBIj0WnGEyt3VOLkSl70TVMdbNqrM+G9QxtQWpZ16RY90bUHf8EqZ6uDWe2uYLpro682dwxkF1o3RffztE/zbVRUh72mt/4IS6CXPNIkKL5lB5TAvGUHxf3WRUWhRUx9o2TSTd3fCLqmOrm4x1jdmhjqltnijWvdpF0gjUfWQVs6VGPW1zN13S1bXot7Vo1mxVV8xye3uYnuu3LtOPpjrZuOW2XeqKmff7wzRnrlK+NIeKTIP6WHxf3VyE3grtHFhoW7gxFZbXBoV2Dpjrbkiq70eCOwesbdNrQXW23hekwCTUfSwnq5tqyH1eg3ZZv+G0to9gqzpp1My79ptEN/Vb39AbQ92mecsdu9RJ18088d8iuqXf2kM9xlAp3NL5nrrZfnnEz6OOq83vvxWkaC/PzoHVuif6ugenOs6D054G30Ldz+SqV5NVUnfKuRmmqm7zaHVbDswwe48dKn2Hh8pLqWvDz6WOp814Djpqw87KDJOp7po81cevjvvgXmhfBHVH5sqF4mpmjQatyZxhtjl4XleaYf5weIb53InzukBxWjR9eFo0eGio9NDEpF9YHVNb7+xIYd8uKHhex1LXUZoldomd1zH+KAvnd0GoOzrnpMK1Xs2Gukb9g0aqruhqypCxmnLfCXXX6ZX+NlpcAogYSwAj5UMlSDd6/TaoY2nrC9B/zNWJJ4LqWOpmX+h5RtEXL8XUMR3cWkR/9OozPwV1H6aW3NX6s11rnXEqp3FTBWq7eCV1zVTlyM7B0B1T3Rt952BzyAl13xjL3d9RtNMcKj36cvdYhMovY4r0+u1Qx9T2jKYm9YV4eVBQHVOdeXWK+BomU1s3dauzzr4XpPRC3TFp0TYOvJ5GIo8Ozev2nmiq1y8TK6k72SB5W66YV7N4PJ4q9Xs8nmrua1NWSPn2yxkp/LqwS347RkPLK7GVQEnd65mZmQgp6r8PBK9N+Zy67gXXpMBGYWt3UqHI/DPlbn9pqExRxLh4sHtR8NoUlrbJCAUmflKH6rTozgFTnW3q2A6uixRt5yCwgZ2DY9Pc0lgvFV5zcIJOtHo+uCLM5Wqraagz1VUXTxLauNXdeRcJy8ryv4pXhN15PhOQu77fUszVTWPvzswPguo6306p//ndudJlTHOr/XI02NdFxUfjrmLbW0F1LG3+sY7HYSm2xveaA+t1tqljapvsicpydH4Ou+SMKXuZAXfwqlax4FWtUAd1UAd1UPc/9u7tt4krjwP4FK3a5aFxstVu23GlZQbH4zpjRxpfHtZO4od9SfQTzo4mRN6GxLurOI2SiGAhEgUSsU2LFCkgERAiREBACHgBpULqW5HY7fbv2plz5mZim7kaF/++D3VynM7hePzxnMvMGNWhOlSH6lAdqkN1qA7V9VpQHapDdagO1aE6VIfqUB2qQ3WoDtWhOlSH6jCoDtWhOlSH6lAdxsrpv/wh9HxsOTj1+9DzkVnbV38Nv7Y/muq+7ERtJ43avu5qAbR99gurCyclPwo/5VmH+9MHV9sV7qq3U0dpQHQbzvoPqMBhUh8GgOgwGg+owGFSHwWBQHQaD6jAYDKrDYFAdBoPqMBgMqsNgUB0Gg0F1GAyq64V09kqfkx/wtTcfcm2oLticPvVp2Dl1wqzt8w5cQ2u/qjX0tn1qv6q1A7XZrmoNvza8qjWsfPb30G8EcMa6g8Ppb0O/X8QG3sEB7+CA6lAdqsOgOlSH6lAdqkN1qA7VoTpUh+pQHapDdagO1aEdVIfqUB2qQ3WoDoPqUB2qCzzkS8oHoA/VoTpUF2wKsX5eTAhxrrm6QX5U/TGZtJVzaVbk48WA1E3BpPWLDCGr+x6+s36RIWR1XtrmQ52X6ryr81IbqtMJJUCIS/EUQKypOhohahXnQEyrfy9yLtSdBTMLznfe2S244EXdv63a6o7V3VybUZZ3XrpX56Vt57e3VpTKr7c9qPP2Uo6PT1+Bqnt1Hmoz/5cqqmuRIRZGqT4Rii/VRcBSlwS+oD6MgOBKnXxOz57Tt8rStqJ4VSf/oGffqbp9UNYO6iDf9KDOddvWt2Dl8H4N4JIXde5fSi3PwJs617XdhkqV5Bmqa5Giiacvl9Es5YtpNpHKN4zr4tonF6//XZwyLYmtXqXm6squOyqH8OCeV3UzbnuY12H5qurrCCoe1Llu2zU4d55AqEx7UFf20ue7o9z1ps51bbfgMvYw22cY2CHbrwMgsdFYPEGmUEx1nASp0bzxN6USeWB9qFu6t1VWKvfvWDtv9cGysjC1ZH+rXHk8fikQdS9eaZ3Hg5eWuocHK0r9+xc2dQfwinwJrAzf+lTnpG2T1bPaw6IM637VOXop1S5tbWU3AHVOansOj1Bd+2RT0J+xdyplTVcGEmP2OUzO1sPUk4F+xqu66SrM7U3eV5RdY+etz8Hd+WsLFxT72Gc8GHUbO1DZf7OjKDcNdU8rUDv6qX6g2HqYs7PkYQYu+lPnrG00q7A87lOd0+r24NYd/+oc1bYNU6juXVOYanP56GAmq6sT9Ncg2V7dmCBmPKt7DjXtM/4xVJb0nTcFV9QfF7eg8Z0ZhLqN61B/SvuQL3R1/4M19cfZNTg2h/kaaj57mI7bNr15a0H+2a86h9Xtqr2+ANQ5qm0S3c/cKynL1CaprN4uZ49VhGysViLqcPk/Z11ZdISXnGc/qruizCDW4re+8u3CLvjmCVzexBtfJYx1e6+pqQOZMbh5Td7Euv/apzmnbtgHky0/G/apzVt3m8tx6EOoc1bYHsFy9PwfyJTfq0gCFHlsPj3ASD+ywBm2EFMS0dYTW6jg2kWTcqTOzNz4+AzdI6WV4pu88BVbJuyModWb2tU7jQ32W8hddnUJLLr6t7mqdju48rxy4aNutc1szyuGqr5UDx9Wdk1Xfd3yuHDitbftwclEdAU5CedOFuihAsfdORCnFNVmWuoE26gZFvsi4VCd/o+fe+HmA86R0HubpzjNKpoNSJ6/peTUxC0CHbEdwRNU91Us23lJ3s6xcn/CizlPb1IHrJCwselk5cFvdPTLv4VGdx8Zph8EfXajLAXC9o20sa85m8ho0SX8NRlurG4H+CONWna2jsthy5y2F0MNU1T1tru5Fo7pf5MrLCU/qPLWNHIOaLdi56WE6qu6ssrXkXZ3nxj3S/sixugGAfM+gS8tJc1KSqEuRX1LaB08LdQMQLTF+1I2XzY7KdmNHZTWMcZ3Vw/xvYw/zYYO6I1i7OOFbnaO2Le5eMtbtJn2O65xUN2X1Euf8jesc7zg6vpt0oS4PejerFzIILEeOdkWBDuXIcT5DVvEsdfZlgoycaovOgbpv4Dl5XDAH5TU6KL/UmdmUOp1NuW5X9wZ+mJ0IQJ2Tti2V4T/67MQ9n+qcVLf7iOQBLDx65k+do8Yd1sh4bkl/yqG6IkC6d3qYOW3hIB5NAUQJtDgb75MS5PwTS11ElOO5MWOKNxWlyXhV95hOQP8MC9P6zpsnE9DrtTDUmSsH9Q1d3RFZOXhat6l7DfXZiSDUOWrbA9jaJBPxyqpPdY5fyiB6mM5qq0JV7XUuPYLKogt1Q6J59lMvJJNLJWTjmoM+6CtGj50RxjCjvCjo6nizu5L3fG7KBZi7Nnkol58Yi62bFajtPahcXrF23p1qtboFc+p/d32em3IAlZ++25FnXhqr5BeXob5/sHxQttTVoL5D89rnuSlO2rZZg/KVX9W36rbflQNH1QWmzlnj5qCirRyUn7hZOVAHNTDM9GZslxl4jgN10z9ulZW5yzesE4tu3F9RFiaX5mDRWtg1su1T3car2oxS2b9qOyNsR63+zYsKmMe3ilnbK5/qnLRtfH3q7oy8fOjtmgP31QWmzlFtm/MLirKwd8PVKjkzAjCI6gJVF3DwqtbA0i1XtTIZaHmOIapDdaguFHVZHuQCqkN1qK6D6hgJXN8sBNWhOlTnS10RgM8yGFSH6jqnTrvsIIl8UB2q66S6JICABztUh+o6qS6b6qVzMVEdqusGddrBjsVb0aI6VNdJddqlrXEEhOpQXSfVDSewj4nqUF1n1TGDAImM7da668DEIHx8m0Bv2F1/zwTdjZt6q7Ohh6bun+E3rYzNnX/Cr82m7q/hV/bu9RpN3Lg250EPWxdKygYXwfQUl3rp49vUeTTQS1bJN/H+sfnJ8LPabO2r/4cfj4za/uyA237uGTU9nUnajupV1b6XQdqO/HFO948Y6n27IZB1K8zi0rttkPUOYq+xbQAEA1m3UKIYocX4zDdsVRW4AFYro0R1tFm3KjTt5hhgxlTRgDVYX5jKagHHTkXcaRugN5AMl+I86LQRz42Ijk+of5ojeuOP50aZXgoHd9iH7mafagvlRD5XIGW5JO8WDhWWEyzbHqY4foTfJz+S5NpNsGTm1uaX09gFVnbIV+H1Y87GdNtifSrb9uExA05VDcII3y/FBfJ1MmYAP0jkhC31L39dGpAYmMsNNliUrtpUDYNQizWDyy9PWwsEVU/ARoKByHGRqUUCBwbl3h63wkJWGkgSm5uaXw9ga3I3E4e2NyAJOA+xnRdSiMimeBgcw7ViYPEjECPV+oxraTCbfN0gZebqevTuoYcCENkVidGgLGk0/lWoZhUq+CBLWr3NtFuWa0+rx3yRskVgvTWXg1FxnZS5J6fQ7iLMV0YjrJrcg/2purIfe1KImS1M6g5ygSaPp2iT49CE3VFVjv5usBl6HEvTbTQ49JbhWSDObqg3w8ZjSOdthS0m1BQdQ1FxnaEnr1JBabrp3UGEsRcoumxzoxksqJ/x4J6EElQqWN2dcefLjSoE+NqtPt1GfUNRSIGMOtUGVthjnYqyWJgVFNnfL9VTpuPoeoaioztSMCPFnAHY7pwXJcm4rix5uM6Ma1n1GQVM1kNAdD+m2xT1/A0dd3QwySRWX29jktT8xSY/gXGTQolOuMZVY+eWeujwLh5bGORsZ2spG5GkHAfY7osrucwm6nLQgt1MmOhbLZFJg+ilOS5wQZ1zQob1cVGaDKWOluRqZeJ5OM84E7GdBk6N+t1x1gx+jcIR5qrU58eO97DbFDH0/FYskFds0KbOnXbtvGa0

3.1.1. Вычисление метрик перекрёстной проверки

Самый простой способ использования перекрёстной проверки — вызвать функцию-помощник cross_val_score для оценщика и набора данных.

Следующий пример демонстрирует, как оценить точность линейного ядра поддержки векторных машин на наборе данных iris, разделив данные, обучив модель и вычислив результат 5 раз подряд (с разными разбиениями каждый раз):

>>> from sklearn.model_selection import cross_val_score
>>> clf = svm.SVC(kernel='linear', C=1, random_state=42)
>>> scores = cross_val_score(clf, X, y, cv=5)
>>> scores
array([0.96..., 1. , 0.96..., 0.96..., 1. ])

Среднее значение и стандартное отклонение даются следующим образом:

>>> print("%0.2f accuracy with a standard deviation of %0.2f" % (scores.mean(), scores.std()))
0.98 accuracy with a standard deviation of 0.02

По умолчанию, вычисляемая на каждой итерации перекрёстной проверки метрика — это метод score оценщика. Можно изменить это, используя параметр scoring:

>>> from sklearn import metrics
>>> scores = cross_val_score(
...     clf, X, y, cv=5, scoring='f1_macro')
>>> scores
array([0.96..., 1.  ..., 0.96..., 0.96..., 1.        ])

Подробности см. в разделе Параметр scoring: определение правил оценки моделей. В случае набора данных Iris, выборки сбалансированы по классам целевой переменной, поэтому точность и F1-мера почти равны.

Когда аргумент cv является целым числом, cross_val_score использует стратегии KFold или StratifiedKFold по умолчанию, а последняя используется, если оценщик унаследован от ClassifierMixin.

Также возможно использование других стратегий перекрёстной проверки путём передачи итератора перекрёстной проверки, например:

>>> from sklearn.model_selection import ShuffleSplit
>>> n_samples = X.shape[0]
>>> cv = ShuffleSplit(n_splits=5, test_size=0.3, random_state=0)
>>> cross_val_score(clf, X, y, cv=cv)
array([0.977..., 0.977..., 1.  ..., 0.955..., 1.        ])

Другой вариант — использовать итерируемый объект, возвращающий (обучающие, тестовые) разбиения в виде массивов индексов, например:

>>> def custom_cv_2folds(X):
...     n = X.shape[0]
...     i = 1
...     while i <= 2:
...         idx = np.arange(n * (i - 1) / 2, n * i / 2, dtype=int)
...         yield idx, idx
...         i += 1
...
>>> custom_cv = custom_cv_2folds(X)
>>> cross_val_score(clf, X, y, cv=custom_cv)
array([1.        , 0.973...])
Преобразование данных с помощью отложенных данных

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

>>> from sklearn import preprocessing
>>> X_train, X_test, y_train, y_test = train_test_split(
...     X, y, test_size=0.4, random_state=0)
>>> scaler = preprocessing.StandardScaler().fit(X_train)
>>> X_train_transformed = scaler.transform(X_train)
>>> clf = svm.SVC(C=1).fit(X_train_transformed, y_train)
>>> X_test_transformed = scaler.transform(X_test)
>>> clf.score(X_test_transformed, y_test)
0.9333...

Класс Pipeline упрощает составление оценщиков, обеспечивая это поведение при перекрёстной проверке:

>>> from sklearn.pipeline import make_pipeline
>>> clf = make_pipeline(preprocessing.StandardScaler(), svm.SVC(C=1))
>>> cross_val_score(clf, X, y, cv=cv)
array([0.977..., 0.933..., 0.955..., 0.933..., 0.977...])

См. Конвейеры и составные оценщики.

3.1.1.1. Функция cross_validate и оценка нескольких метрик

Функция cross_validate отличается от cross_val_score двумя способами:

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

Для оценки по одной метрике, где параметр scoring — строка, вызываемый объект или None, ключи будут — ['test_score', 'fit_time', 'score_time']

А для оценки по нескольким метрикам возвращаемое значение — словарь со следующими ключами — ['test_<scorer1_name>', 'test_<scorer2_name>', 'test_<scorer...>', 'fit_time', 'score_time']

return_train_score устанавливается в False по умолчанию, чтобы сэкономить время вычислений. Чтобы оценить метрики и на обучающей выборке, необходимо установить его в True. Вы также можете сохранить оценщик, обученный на каждой обучающей выборке, установив return_estimator=True. Аналогично, вы можете установить return_indices=True для сохранения индексов обучающей и тестовой выборок, используемых для разбиения набора данных на обучающую и тестовую выборки для каждого разбиения cv.

Несколько метрик могут быть заданы в виде списка, кортежа или множества предварительно определённых имён метрик:

>>> from sklearn.model_selection import cross_validate
>>> from sklearn.metrics import recall_score
>>> scoring = ['precision_macro', 'recall_macro']
>>> clf = svm.SVC(kernel='linear', C=1, random_state=0)
>>> scores = cross_validate(clf, X, y, scoring=scoring)
>>> sorted(scores.keys())
['fit_time', 'score_time', 'test_precision_macro', 'test_recall_macro']
>>> scores['test_recall_macro']
array([0.96..., 1.  ..., 0.96..., 0.96..., 1.        ])

Или в виде словаря, сопоставляющего имя метрики с предварительно определённой или пользовательской функцией оценки:

>>> from sklearn.metrics import make_scorer
>>> scoring = {'prec_macro': 'precision_macro',
...            'rec_macro': make_scorer(recall_score, average='macro')}
>>> scores = cross_validate(clf, X, y, scoring=scoring,
...                         cv=5, return_train_score=True)
>>> sorted(scores.keys())
['fit_time', 'score_time', 'test_prec_macro', 'test_rec_macro',
 'train_prec_macro', 'train_rec_macro']
>>> scores['train_rec_macro']
array([0.97..., 0.97..., 0.99..., 0.98..., 0.98...])

Вот пример cross_validate с использованием одной метрики:

>>> scores = cross_validate(clf, X, y,
...                         scoring='precision_macro', cv=5,
...                         return_estimator=True)
>>> sorted(scores.keys())
['estimator', 'fit_time', 'score_time', 'test_score']

3.1.1.2. Получение прогнозов с помощью перекрёстной проверки

Функция cross_val_predict имеет похожий интерфейс с cross_val_score, но возвращает для каждого элемента входных данных прогноз, полученный для этого элемента, когда он был в тестовой выборке. Можно использовать только стратегии перекрёстной проверки, которые точно один раз присваивают все элементы тестовой выборке (в противном случае генерируется исключение).

Предупреждение

Замечание по ненадлежащему использованию cross_val_predict

Результат cross_val_predict может отличаться от результатов, полученных с помощью cross_val_score, так как элементы группируются по-разному. Функция cross_val_score вычисляет среднее значение по разбиениям перекрёстной проверки, тогда как cross_val_predict просто возвращает метки (или вероятности) из нескольких различных моделей без различения. Таким образом, cross_val_predict не является надлежащей мерой обобщающей ошибки.

Функция cross_val_predict подходит для:
  • Визуализации прогнозов, полученных от различных моделей.
  • Слияния моделей: Когда прогнозы одного контролируемого оценщика используются для обучения другого оценщика в методах ансамбля.

Доступные итераторы перекрёстной проверки представлены в следующем разделе.

Примеры

  • Кривая ROC (Receiver Operating Characteristic) с перекрёстной проверкой,
  • Рекурсивное удаление признаков с перекрёстной проверкой,
  • Настройка стратегии повторного обучения поиска по сетке с перекрёстной проверкой,
  • Пример конвейера для извлечения признаков текста и оценки,
  • Построение прогнозов при перекрёстной проверке,
  • Вложенная и невложенная перекрёстная проверка.

3.1.2. Итераторы для перекрёстной проверки

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

3.1.2.1. Итераторы перекрёстной проверки для данных i.i.d.

Предположение о том, что данные независимы и одинаково распределены (i.i.d.), означает, что все образцы происходят из одного и того же генеративного процесса, и предполагается, что генеративный процесс не запоминает прошлые сгенерированные образцы.

В таких случаях можно использовать следующие перекрёстные валидаторы.

Примечание

Хотя данные i.i.d. являются распространённым предположением в теории машинного обучения, на практике они редко выполняются. Если известно, что образцы были сгенерированы с помощью временного зависимого процесса, безопаснее использовать схему перекрёстной проверки, учитывающую временные ряды.схему перекрёстной проверки, учитывающую временные ряды. Аналогично, если известно, что генеративный процесс имеет структуру группы (образцы, собранные от разных субъектов, экспериментов, измерительных устройств), безопаснее использовать групповую перекрёстную проверку.

3.1.2.1.1. K-кратная перекрёстная проверка

KFold делит все образцы на \(k\) групп образцов, называемых фолдами (если \(k = n\), это эквивалентно стратегии «оставить один извне»), равного размера (если это возможно). Функция предсказания обучается с использованием \(k - 1\) фолдов, а оставшийся фолд используется для тестирования.

Пример 2-кратной перекрёстной проверки на наборе данных с 4 образцами:

%%%CODE_BLOCK_42%%>

Вот визуализация поведения перекрёстной проверки. Обратите внимание, что KFold не зависит от классов или групп.

../_images/sphx_glr_plot_cv_indices_006.png

3.1.2.1.2. Повторная K-кратная перекрёстная проверка

RepeatedKFold повторяет K-кратную перекрёстную проверку n раз. Она может использоваться, когда необходимо выполнить KFold n раз, создавая разные разбиения на каждой итерации.

Пример 2-кратной K-кратной перекрёстной проверки, повторённой 2 раза:

%%%CODE_BLOCK_47%%>

Аналогично, RepeatedStratifiedKFold повторяет стратифицированную K-кратную перекрёстную проверку n раз с разной случайностью на каждой итерации.

3.1.2.1.3. Оставление одного (LOO)

LeaveOneOut (или LOO) — это простой вид перекрестной проверки. Каждый обучающий набор создаётся путём исключения одного образца, а тестовый набор состоит из этого исключённого образца. Таким образом, для \(n\) образцов у нас есть \(n\) различных обучающих наборов и \(n\) различных тестовых наборов. Эта процедура перекрестной проверки не тратит много данных, так как из обучающего набора удаляется только один образец:

>>> from sklearn.model_selection import LeaveOneOut

>>> X = [1, 2, 3, 4]
>>> loo = LeaveOneOut()
>>> for train, test in loo.split(X):
...     print("%s %s" % (train, test))
[1 2 3] [0]
[0 2 3] [1]
[0 1 3] [2]
[0 1 2] [3]

Пользователям, использующим LOO для выбора модели, следует учитывать некоторые известные недостатки. По сравнению с \(k\)-кратной перекрестной проверкой, создаётся \(n\) моделей из \(n\) образцов вместо \(k\) моделей, где \(n > k\). Кроме того, каждая модель обучается на \(n - 1\) образцах вместо \((k-1) n / k\). В обоих случаях, предполагая, что \(k\) не слишком велико и \(k < n\), LOO является более вычислительно затратной, чем \(k\)-кратная перекрестная проверка.

С точки зрения точности, LOO часто приводит к высокой дисперсии в качестве оценки ошибки тестирования. Интуитивно, поскольку \(n - 1\) из \(n\) образцов используются для построения каждой модели, модели, построенные из блоков, практически идентичны друг другу и модели, построенной на основе всего обучающего набора.

Однако, если кривая обучения крутая для рассматриваемого размера обучающего набора, то 5- или 10-кратная перекрестная проверка может переоценить ошибку обобщения.

Как общее правило, большинство авторов и эмпирические данные свидетельствуют о том, что 5- или 10-кратная перекрестная проверка предпочтительнее LOO.

Ссылки
  • http://www.faqs.org/faqs/ai-faq/neural-nets/part3/section-12.html;
  • Т. Хэсти, Р. Тибширани, Дж. Фридман, Элементы статистического обучения, Springer 2009
  • Л. Брейман, П. Спектор Подбор и оценка подмоделей в регрессии: Случай X-случайности, Международный статистический обзор 1992;
  • Р. Кохави, Исследование перекрестной проверки и бутстрапа для оценки точности и выбора модели, Международная совместная конференция по искусственному интеллекту
  • Р. Бхарат Рао, Г. Фунг, Р. Росалес, О опасностях перекрестной проверки. Экспериментальная оценка, SIAM 2008;
  • Г. Джеймс, Д. Уиттен, Т. Хэсти, Р. Тибширани, Введение в статистическое обучение, Springer 2013.

3.1.2.1.4. Оставление P (LPO)

LeavePOut очень похож на LeaveOneOut, поскольку он создаёт все возможные обучающие/тестовые наборы путём удаления \(p\) образцов из полного набора. Для \(n\) образцов это даёт \({n \choose p}\) пар обучение-тест. В отличие от LeaveOneOut и KFold, тестовые наборы будут перекрываться для \(p > 1\).

Пример оставления двух образцов для набора данных с 4 образцами:

>>> from sklearn.model_selection import LeavePOut

>>> X = np.ones(4)
>>> lpo = LeavePOut(p=2)
>>> for train, test in lpo.split(X):
...     print("%s %s" % (train, test))
[2 3] [0 1]
[1 3] [0 2]
[1 2] [0 3]
[0 3] [1 2]
[0 2] [1 3]
[0 1] [2 3]

3.1.2.1.5. Перекрёстная валидация случайными перестановками (иначе Shuffle & Split)

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

Для воспроизводимости результатов можно управлять случайностью, явно задав начальное значение генератора псевдослучайных чисел random_state.

Вот пример использования:

>>> from sklearn.model_selection import ShuffleSplit
>>> X = np.arange(10)
>>> ss = ShuffleSplit(n_splits=5, test_size=0.25, random_state=0)
>>> for train_index, test_index in ss.split(X):
...     print("%s %s" % (train_index, test_index))
[9 1 6 7 3 0 5] [2 8 4]
[2 9 8 0 6 7 4] [3 5 1]
[4 5 1 0 6 9 7] [2 3 8]
[2 7 5 8 0 3 4] [6 1 9]
[4 1 0 6 8 9 3] [5 2 7]

Вот визуализация поведения перекрестной валидации. Обратите внимание, что ShuffleSplit не зависит от классов или групп.

../_images/sphx_glr_plot_cv_indices_008.png

ShuffleSplit — хорошая альтернатива перекрёстной валидации с помощью KFold, позволяющая точнее управлять количеством итераций и пропорцией образцов в обучающей и тестовой выборках.

3.1.2.2. Итераторы кросс-валидации со стратификацией по меткам классов

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

3.1.2.2.1. Стратифицированный k-фолдовый перекрёстный контроль

StratifiedKFold — это вариация k-фолдовой схемы, которая возвращает стратифицированные фолды: каждый набор содержит примерно такой же процент образцов каждого целевого класса, как и весь набор данных.

Вот пример стратифицированной 3-фолдовой кросс-валидации на наборе данных с 50 образцами из двух несбалансированных классов. Мы покажем количество образцов в каждом классе и сравним с KFold.

>>> from sklearn.model_selection import StratifiedKFold, KFold
>>> import numpy as np
>>> X, y = np.ones((50, 1)), np.hstack(([0] * 45, [1] * 5))
>>> skf = StratifiedKFold(n_splits=3)
>>> for train, test in skf.split(X, y):
...     print('train -  {}   |   test -  {}'.format(
...         np.bincount(y[train]), np.bincount(y[test])))
train -  [30  3]   |   test -  [15  2]
train -  [30  3]   |   test -  [15  2]
train -  [30  4]   |   test -  [15  1]
>>> kf = KFold(n_splits=3)
>>> for train, test in kf.split(X, y):
...     print('train -  {}   |   test -  {}'.format(
...         np.bincount(y[train]), np.bincount(y[test])))
train -  [28  5]   |   test -  [17]
train -  [28  5]   |   test -  [17]
train -  [34]   |   test -  [11  5]

Мы можем видеть, что StratifiedKFold сохраняет соотношения классов (приблизительно 1/10) как в обучающем, так и в тестовом наборах данных.

Вот визуализация поведения кросс-валидации.

../_images/sphx_glr_plot_cv_indices_009.png

RepeatedStratifiedKFold можно использовать для повторения стратифицированного k-фолдового перекрёстного контроля n раз с различной случайной выборкой на каждом повторении.

3.1.2.2.2. Стратифицированное перемешивание и разбиение

StratifiedShuffleSplit — это разновидность ShuffleSplit, которая возвращает стратифицированные разбиения, т.е. разбиения, созданные с сохранением того же процента для каждого класса целевой переменной, что и в полном наборе данных.

Вот визуализация поведения перекрестной проверки.

../_images/sphx_glr_plot_cv_indices_012.png

3.1.2.3. Заданные наборы сплитов/валидационные наборы

Для некоторых наборов данных уже существует предопределенное разбиение данных на обучающую и валидационную выборки или на несколько наборов для перекрестной проверки. С помощью PredefinedSplit можно использовать эти разбиения, например, при поиске гиперпараметров.

Например, при использовании валидационной выборки установите test_fold в 0 для всех образцов, которые являются частью валидационной выборки, и в -1 для всех остальных образцов.

3.1.2.4. Итераторы перекрёстной проверки для сгруппированных данных

Предположение о независимости и одинаковом распределении (i.i.d.) нарушается, если основной генеративный процесс дает группы зависимых выборок.

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

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

Для этого можно использовать следующие разделители перекрестной проверки. Идентификатор группировки для выборок задается параметром groups.

3.1.2.4.1. Группа k-fold

GroupKFold — это вариант k-fold, который гарантирует, что одна и та же группа не представлена как в тестовом, так и в обучающем наборах. Например, если данные получены от разных субъектов с несколькими выборками на субъект, и если модель достаточно гибкая, чтобы учиться на сильно специфичных для человека признаках, она может не обобщиться на новых субъектов. GroupKFold позволяет обнаружить ситуации такого переобучения.

Представьте, что у вас три субъекта, каждому из которых присвоено число от 1 до 3:

>>> from sklearn.model_selection import GroupKFold

>>> X = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10]
>>> y = ["a", "b", "b", "b", "c", "c", "c", "d", "d", "d"]
>>> groups = [1, 1, 1, 2, 2, 2, 3, 3, 3, 3]

>>> gkf = GroupKFold(n_splits=3)
>>> for train, test in gkf.split(X, y, groups=groups):
...     print("%s %s" % (train, test))
[0 1 2 3 4 5] [6 7 8 9]
[0 1 2 6 7 8 9] [3 4 5]
[3 4 5 6 7 8 9] [0 1 2]

Каждый субъект находится в отдельной проверочной папке, и один и тот же субъект никогда не находится как в проверочной, так и в обучающей выборке. Обратите внимание, что папки не имеют одинакового размера из-за дисбаланса в данных. Если необходимо, чтобы пропорции классов были сбалансированы по всем папкам, StratifiedGroupKFold — лучший вариант.

Вот визуализация поведения перекрестной проверки.

../_images/sphx_glr_plot_cv_indices_007.png

Подобно KFold, тестовые наборы из GroupKFold составят полное разбиение всех данных.

Хотя GroupKFold пытается разместить одинаковое количество выборок в каждой папке, когда shuffle=False, когда shuffle=True он пытается разместить равное количество различных групп в каждой папке (но не учитывает размеры групп).

3.1.2.4.2. StratifiedGroupKFold

StratifiedGroupKFold — это схема перекрестной проверки, которая объединяет как StratifiedKFold, так и GroupKFold. Идея состоит в том, чтобы сохранить распределение классов в каждом разбиении, сохраняя при этом каждую группу в одном разбиении. Это может быть полезно, когда у вас несбалансированный набор данных, так как использование только GroupKFold может привести к искажённым разбиениям.

Пример:

>>> from sklearn.model_selection import StratifiedGroupKFold
>>> X = list(range(18))
>>> y = [1] * 6 + [0] * 12
>>> groups = [1, 2, 3, 3, 4, 4, 1, 1, 2, 2, 3, 4, 5, 5, 5, 6, 6, 6]
>>> sgkf = StratifiedGroupKFold(n_splits=3)
>>> for train, test in sgkf.split(X, y, groups=groups):
...     print("%s %s" % (train, test))
[ 0  2  3  4  5  6  7 10 11 15 16 17] [ 1  8  9 12 13 14]
[ 0  1  4  5  6  7  8  9 11 12 13 14] [ 2  3 10 15 16 17]
[ 1  2  3  8  9 10 12 13 14 15 16 17] [ 0  4  5  6  7 11]
Примечания к реализации
  • В текущей реализации полная перетасовка невозможна в большинстве сценариев. Когда shuffle=True, происходит следующее:

    1. Все группы перемешиваются.
    2. Группы сортируются по стандартному отклонению классов с использованием устойчивой сортировки.
    3. Сортированные группы перебираются и назначаются в слои.

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

  • Алгоритм жадно назначает каждую группу одному из n_splits тестовых наборов, выбирая тестовый набор, который минимизирует дисперсию распределения классов по тестовым наборам. Назначение групп происходит от групп с наибольшей к наименьшей дисперсией частоты классов, то есть большие группы, пиковые по одному или нескольким классам, назначаются в первую очередь.
  • Это разбиение не является оптимальным в том смысле, что оно может привести к несбалансированным разбиениям, даже если идеальная стратификация возможна. Если у вас относительно близкое распределение классов в каждой группе, использование GroupKFold предпочтительнее.

Вот визуализация поведения перекрестной проверки для неравномерных групп:

../_images/sphx_glr_plot_cv_indices_005.png

3.1.2.4.3. Оставление одной группы вне

LeaveOneGroupOut — это схема перекрестной проверки, где каждый разбиение исключает образцы, относящиеся к одной определённой группе. Информация о группах предоставляется через массив, кодирующий группу каждого образца.

Каждый обучающий набор таким образом составляется из всех образцов, кроме тех, которые относятся к определённой группе. Это аналогично LeavePGroupsOut с n_groups=1 и аналогично GroupKFold с n_splits равным числу уникальных меток, переданных в параметр groups.

Например, в случае нескольких экспериментов, LeaveOneGroupOut можно использовать для создания перекрестной проверки, основанной на разных экспериментах: мы создаём обучающий набор, используя образцы всех экспериментов, кроме одного:

>>> from sklearn.model_selection import LeaveOneGroupOut

>>> X = [1, 5, 10, 50, 60, 70, 80]
>>> y = [0, 1, 1, 2, 2, 2, 2]
>>> groups = [1, 1, 2, 2, 3, 3, 3]
>>> logo = LeaveOneGroupOut()
>>> for train, test in logo.split(X, y, groups=groups):
...     print("%s %s" % (train, test))
[2 3 4 5 6] [0 1]
[0 1 4 5 6] [2 3]
[0 1 2 3] [4 5 6]

Другим распространённым применением является использование временной информации: например, группы могут представлять год сбора образцов, и, таким образом, позволяют проводить перекрестную проверку по временным разбиениям.

3.1.2.4.4. Оставление P групп вне

LeavePGroupsOut аналогично LeaveOneGroupOut, но удаляет образцы, относящиеся к \(P\) группам для каждого набора обучение/тестирование. Все возможные комбинации из \(P\) групп исключаются, что означает перекрытие наборов для тестирования при \(P>1\).

Пример оставления 2 групп вне:

>>> from sklearn.model_selection import LeavePGroupsOut

>>> X = np.arange(6)
>>> y = [1, 1, 1, 2, 2, 2]
>>> groups = [1, 1, 2, 2, 3, 3]
>>> lpgo = LeavePGroupsOut(n_groups=2)
>>> for train, test in lpgo.split(X, y, groups=groups):
...     print("%s %s" % (train, test))
[4 5] [0 1 2 3]
[2 3] [0 1 4 5]
[0 1] [2 3 4 5]

3.1.2.4.5. Разбиение с перемешиванием по группам

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

Вот пример использования:

>>> from sklearn.model_selection import GroupShuffleSplit

>>> X = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 0.001]
>>> y = ["a", "b", "b", "b", "c", "c", "c", "a"]
>>> groups = [1, 1, 2, 2, 3, 3, 4, 4]
>>> gss = GroupShuffleSplit(n_splits=4, test_size=0.5, random_state=0)
>>> for train, test in gss.split(X, y, groups=groups):
...     print("%s %s" % (train, test))
...
[0 1 2 3] [4 5 6 7]
[2 3 6 7] [0 1 4 5]
[2 3 4 5] [0 1 6 7]
[4 5 6 7] [0 1 2 3]

Вот визуализация поведения перекрестной проверки.

../_images/sphx_glr_plot_cv_indices_011.png

Этот класс полезен, когда требуется поведение LeavePGroupsOut, но количество групп достаточно велико, чтобы генерация всех возможных разбиений с исключенными \(P\) группами была бы слишком дорогостоящей. В такой ситуации GroupShuffleSplit предоставляет случайную выборку (с возвращением) разбиений на обучающую и тестовую выборки, сгенерированных методом LeavePGroupsOut.

3.1.2.5. Использование итераторов перекрестной проверки для разделения на обучающую и тестовую выборки

Функции групповой перекрестной проверки также могут быть полезны для разделения набора данных на обучающую и тестовую выборки. Обратите внимание, что функция train_test_split является оболочкой вокруг ShuffleSplit и поэтому позволяет только стратифицированное разделение (с использованием меток классов) и не может учитывать группы.

Для выполнения разделения на обучающую и тестовую выборки используйте индексы для обучающих и тестовых подмножеств, полученных из генератора, выведенного методом split() разделителя перекрестной проверки. Например:

>>> import numpy as np
>>> from sklearn.model_selection import GroupShuffleSplit

>>> X = np.array([0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 0.001])
>>> y = np.array(["a", "b", "b", "b", "c", "c", "c", "a"])
>>> groups = np.array([1, 1, 2, 2, 3, 3, 4, 4])
>>> train_indx, test_indx = next(
...     GroupShuffleSplit(random_state=7).split(X, y, groups)
... )
>>> X_train, X_test, y_train, y_test = \
...     X[train_indx], X[test_indx], y[train_indx], y[test_indx]
>>> X_train.shape, X_test.shape
((6,), (2,))
>>> np.unique(groups[train_indx]), np.unique(groups[test_indx])
(array([1, 2, 4]), array([3]))

3.1.2.6. Перекрёстная проверка временных рядов

Данные временных рядов характеризуются корреляцией между наблюдениями, которые близки во времени (автокорреляция). Однако классические методы перекрёстной проверки, такие как KFold и ShuffleSplit, предполагают, что образцы независимы и одинаково распределены, и в результате приведут к необоснованной корреляции между обучающими и тестовыми экземплярами (что даст плохие оценки обобщающей ошибки) на данных временных рядов. Поэтому очень важно оценить нашу модель для данных временных рядов на будущих наблюдениях, наименее похожих на те, которые используются для обучения модели. Для достижения этой цели одним из решений является TimeSeriesSplit.

3.1.2.6.1. Разбиение по временным рядам

TimeSeriesSplit — это разновидность k-fold, которая возвращает первые \(k\) фолдов в качестве обучающей выборки, а \((k+1)\) -й фолд в качестве тестовой. Обратите внимание, что в отличие от стандартных методов перекрёстной проверки последовательные обучающие выборки являются супермножествами тех, что были до них. Кроме того, он добавляет все избыточные данные в первый обучающий раздел, который всегда используется для обучения модели.

Этот класс может использоваться для перекрёстной проверки выборок временных рядов, которые наблюдаются через фиксированные временные интервалы.

Пример перекрёстной проверки временных рядов с 3 разбиениями на наборе данных с 6 образцами:

>>> from sklearn.model_selection import TimeSeriesSplit

>>> X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]])
>>> y = np.array([1, 2, 3, 4, 5, 6])
>>> tscv = TimeSeriesSplit(n_splits=3)
>>> print(tscv)
TimeSeriesSplit(gap=0, max_train_size=None, n_splits=3, test_size=None)
>>> for train, test in tscv.split(X):
...     print("%s %s" % (train, test))
[0 1 2] [3]
[0 1 2 3] [4]
[0 1 2 3 4] [5]

Вот визуализация поведения перекрёстной проверки.

../_images/sphx_glr_plot_cv_indices_013.png

3.1.3. Примечание о перемешивании

Если порядок данных не произвольный (например, образцы с одинаковым меткой класса сосредоточены), то для получения осмысленного результата перекрёстной проверки их необходимо предварительно перемешать. Однако обратное может быть справедливо, если образцы не являются независимыми и одинаково распределёнными. Например, если образцы соответствуют новостным статьям и упорядочены по времени публикации, то перемешивание данных скорее всего приведёт к модели, которая переобучена и имеет завышенную оценку валидации: она будет тестироваться на образцах, искусственно похожих (близких по времени) на обучающие образцы.

Некоторые итераторы перекрёстной проверки, такие как KFold, имеют встроенную возможность перемешать индексы данных перед их разделением. Обратите внимание, что:

  • Это потребляет меньше памяти, чем непосредственное перемешивание данных.
  • По умолчанию перемешивания не происходит, в том числе и для (стратифицированной) перекрёстной проверки k-fold, выполненной путём задания cv=some_integer для cross_val_score, поиска по сетке и т. д. Имейте в виду, что train_test_split по-прежнему возвращает случайное разбиение.
  • Параметр random_state по умолчанию равен None, что означает, что перемешивание будет разным при каждом KFold(..., shuffle=True). Однако GridSearchCV будет использовать то же перемешивание для каждого набора параметров, проверенных одним вызовом его метода fit.
  • Для получения одинаковых результатов для каждого разбиения установите random_state в целое число.

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

3.1.4. Перекрёстная проверка и выбор модели

Итераторы перекрёстной проверки также могут быть использованы для прямого выбора модели с помощью поиска по сетке для оптимальных гиперпараметров модели. Это тема следующего раздела: Настройка гиперпараметров оценщика.

3.1.5. Тест перестановки (Permutation test)

permutation_test_score предлагает другой способ оценки производительности классификаторов. Он предоставляет значение p, основанное на перестановках, которое представляет вероятность получения наблюдаемой производительности классификатора случайно. Нулевая гипотеза в этом тесте заключается в том, что классификатор не использует никакой статистической зависимости между признаками и метками для правильного прогнозирования на оставленных данных. permutation_test_score генерирует нулевое распределение, вычисляя n_permutations различные перестановки данных. При каждой перестановке метки случайным образом перемешиваются, тем самым удаляя любую зависимость между признаками и метками. Значение p — это доля перестановок, для которых среднее значение оценки перекрёстной проверки, полученное моделью, лучше, чем значение оценки перекрёстной проверки, полученное моделью с использованием исходных данных. Для надёжных результатов n_permutations обычно должно быть больше 100, а cv — между 3 и 10 слоями.

Малое значение p свидетельствует о том, что набор данных содержит реальную зависимость между признаками и метками, и классификатор смог использовать её для получения хороших результатов. Высокое значение p может быть связано с отсутствием зависимости между признаками и метками (нет различий в значениях признаков между классами) или с тем, что классификатор не смог использовать зависимость в данных. В последнем случае использование более подходящего классификатора, способного использовать структуру данных, приведёт к меньшему значению p.

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

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

Наконец, permutation_test_score вычисляется с помощью грубой силы и внутри подгоняет (n_permutations + 1) * n_cv модели. Поэтому он реализуем только с небольшими наборами данных, для которых подгонка отдельной модели очень быстра.

Примеры

  • Тестирование с перестановками значимости оценки классификации
Ссылки
  • Ojala и Garriga. Тесты перестановки для изучения производительности классификатора. J. Mach. Learn. Res. 2010.

© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/modules/cross_validation.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API