[БЕЗ_ЗВУКА] На предыдущих уроках мы научились генерировать модельные данные, а также строить разбиения набора данных с помощью кросс-валидации. Теперь мы можем смело перейти к построению моделей, и в этом уроке мы научимся строить линейные модели с помощью модуля sklearn.linear.model. Модуль предоставляет нам целый ряд линейных моделей: это линейная классификация и регрессия, логистическая регрессия, модель на основе стохастического градиентного спуска и другое. По ссылкам ниже доступна документация и примеры построения линейных моделей. Мы с вами начнем с того, что импортируем необходимые нам модули. С модулями cross-validation и datasets вы знакомы с предыдущих уроков, модуль linear_model нужен нам для того, чтобы использовать линейные модели, и модуль metrics пригодиться для того, чтобы оценивать качество полученных моделей. Итак, начнем с генерации данных. В данном случае в качестве модельных данных я выбрала dataset, состоящий из 2-х признаков, его также удобно визуализировать, который представляется в виде 2-х капель, или 2-х облаков точек. Построить такой dataset можно с помощью функции make_blobs. Укажем ей параметры, говорящие о том, сколько у нас будет классов, сколько будет центров и какой будет разброс. Вот теперь давайте посмотрим на то, как же выглядит наш dataset. Но ответим, что действительно получили два облака точек, которые немножечко накладываются друг на друга. Итак, теперь с помощью уже знакомой нам функции train_test_split разобьем данные на обучение и тест. Будем это делать в соотношении: 30 % — тест и 70 % — обучение. Теперь давайте строить наш классификатор. Мы будем строить линейный классификатор под названием ridge_classifier, для начала не будем указывать никаких параметров, воспользуемся моделью по умолчанию. Единственное, что мы укажем — это random_state. Он нужен для того, чтобы наши эксперименты были воспроизводимы. Итак, мы сделали объект. Теперь давайте его обучим. Для того чтобы обучить модель, нужно вызвать метод fit и передать ему в качестве аргументов данные, на которых нужно обучаться, и метки классов. В нашем случае это train_data и train_labels, которые мы сгенерировали ранее. Итак, получили обученную модель. Теперь мы можем строить наши предсказания. Для этого вызываем метод predict и передаем ему на вход тестовую выборку. Это те данные, которые в обучении не участвовали, и мы можем с помощью них проверить, насколько хорошо наша модель работает на внешних данных. Итак, получили наши предсказания, теперь давайте выведем на экран правильные метки и предсказанные метки, чтобы их сравнить и посмотреть, насколько же хорошо мы отработали. Итак, тестовые метки перед вами, метки на тестовой выборке. Теперь выводим предсказания и видим, что в целом кажется, что неплохо. Они похожи, но есть отличия. Для того чтобы формально оценить качество нашей модели, нужно воспользоваться некоторой метрикой качества. Ну давайте воспользуемся довольно простой метрикой под названием accuracy — это доля правильных ответов на тестовой выборке. Ну в данном случае мы передаем в качестве аргументов метки на тестовой выборке и наши предсказания. Итак, получаем 0,87. Получается, что в 87 % случаев мы правильно предсказали метку нашего класса. Это хорошо. А помимо качества классификации, мы можем смотреть также и на веса перед нашими признаками, которые мы получили в процессе обучения. Ну давайте их выведем. Перед нами вес перед первым и перед вторым признаком. Ну и помимо весов перед признаками мы можем вывести коэффициент перед свободным членом — свободный коэффициент. Он также перед вами. Следующая модель, которую мы обучим — логистическая регрессия. Для этого нужно воспользоваться классом LogisticRegression. Давайте создадим соответствующий объект, снова будем использовать параметры по умолчанию, и также обучим модель и построим предсказания на той же самой тестовой выборке. Обучаем модель с помощью метода fit, снова передаем ей для обучения данные и метки классов, строим предсказания, а теперь заметим, что в случае, когда мы используем логистическую регрессию, мы работаем с вероятностной моделью. Помимо меток классов, эта модель может выдать нам вероятности, с которыми каждый объект принадлежит первому и нулевому классу. Вот давайте эти вероятности тоже построим. Для этого нужно воспользоваться методом predict_proba (или predict probability). Снова в качестве аргумента передаем тестовую выборку и получаем наши вероятности принадлежности к классам. Давайте посмотрим, как это выглядит. Тестовые метки у нас не изменились. Обычные предсказания выглядят в виде меток классов. И теперь вероятностное предсказание. Видим, что для каждого объекта нам доступны 2 значения: первое — это вероятность принадлежности к классу с меткой 0, второе значение — вероятность принадлежности к классу с меткой 1. Ну и логично, что если каждую пару мы сложим, мы должны получить 1. Итак, теперь давайте оценим качество нашей модели. Снова сделаем это с помощью метода accuracy_score, посмотрим на аккуратность нашей классификации, или на долю правильных ответов. Видим, что она составляет 0,8, и напомню, что когда мы обучали ridge-классификатор, у нас доля правильных ответов была 87 %. Итак, мы с вами уже умеем обучать модели, оценивать их качество по holdout dataset-у и смотреть на полученные веса. Теперь давайте ответим на вопрос: является ли полученная оценка устойчивой? Достаточно ли такой оценки для того, чтобы сделать вывод о том, что один алгоритм работает лучше, чем другой? Давайте обучим сразу несколько моделей. Сделать это можно с помощью кросс-валидации. Проанализируем полученные результаты и попытаемся сравнить с нашей моделью. Для того чтобы обучить несколько моделей и посмотреть на полученные оценки, мы можем действовать разными способами. Например, мы можем взять функцию train_test_split, которую мы изучили ранее, построить несколько разбиений, обучить на них модели и оценить качество. Таким образом мы получим целый набор оценок, который в дальнейшем можно будет усреднить, посчитать отклонения и получить некоторую интервальную оценку на качество наших моделей. Понятно, что это не очень удобно. Нам хотелось бы иметь некоторый автоматизированный способ, для того чтобы это делать. Для этого cross-validation предоставляет нам функцию cross-val-score. Давайте посмотрим, как она выглядит. Эта функция принимает несколько аргументов. Во-первых, она принимает модель, которую мы хотим оценивать. Далее ей нужно передать данные и метки классов, а также указать, какая метрика нас интересует и каким образом мы хотим делать кросс-валидацию. Для начала давайте попробуем довольно простой запуск. Передадим классификаторы, которые мы ранее создали. Воспользуемся данными, которые нам также доступны, и укажем, что в качестве метрики мы будем использовать accuracy — долю правильных ответов, в качестве кросс-валидации будем использовать k-fold на 10 fold-ов. Если мы указываем параметр cv = 10, в данном случае мы никак не специфицируем вид кросс-валидации, работает кросс-валидация по умолчанию: это либо k-fold, либо stratified k-fold. Когда мы работаем над задачей бинарной классификации, по умолчанию работает stratified k-fold. В данном случае нас это вполне устраивает. Итак, давайте применим функцию. Сначала получили оценку для классификатора ridge-classifier, теперь давайте сделаем то же самое для логистической регрессии. И теперь по полученному скорингу, давайте также выведем его на экран, чтобы посмотреть, как это выглядит. На самом деле, это просто список оценок метрики accuracy, то же самое в случае линейной регрессии. Теперь давайте посмотрим на статистики. Ну вот выведем среднее, максимальное и минимальное значение и посчитаем разброс. Сначала для ridge-классификатора, теперь для log-регрессии. Вот на основании полученного результата мы видим, что на самом деле модель работает приблизительно одинаково. Теперь давайте немножечко усложним. Предположим, что мы хотим считать какую-то нестандартную метрику качества и хотим специфицировать нужную нам стратегию кросс-валидации. Для того чтобы передать свою метрику качества в эту функцию, нам нужно создать так называемый объект scorer. Он должен удовлетворять нужному интерфейсу. Он должен принимать 3 параметра. Первый — это модель, которую мы оцениваем. Далее — набор меток классов и набор наших предсказаний. Если мы посмотрим на синтаксис функции accuracy_score, то мы поймем, что он не такой. Эта метрика... эта функция не принимает на вход классификатор, она принимает только метки классов и наши предсказания. Для того чтобы создать правильный объект, который можно передать внутрь функции cross_val_score, нам с вами нужно его создать. Это можно делать с помощью функции make_scorer. Передаем ей в качестве аргумента нашу метрику и создаем scorer. Ну в данном случае мы передали ту же самую метрику, потому что она нам просто подходит. Теперь давайте специфицируем стратегию кросс-валидации. Ну для примера давайте будем использовать StratifiedShuffleSplit. Будем делать целых 20 итераций, и пусть доля тестовой выборки будет 30 %. Итак, scorer и стратегию мы создали, теперь давайте предадим их внутрь функции cross_val_score и снова оценим наши модели. Итак, сначала scoring для ridge-классификатора, теперь scoring для линейной, для логистической регрессии. Итак, выводим оценки и видим, что снова мы получили очень похожий результат. Понятно, что наша модель работает приблизительно одинаково. На этом мы заканчиваем. Мы научились строить линейные модели ridge_classifier и log_regression, а также научились оценивать их качество в отдельной точке и с помощью кросс-валидации. Для этого мы использовали функцию cross_val_score. На следующем уроке мы продолжим работать с модулем linear_model и научимся строить еще несколько моделей.