[БЕЗ_ЗВУКА] Привет! В этом видео мы продолжим говорить про задачи визуализации данных и также на примерах рассмотрим все эти методы, которые вы уже успели изучить. Работать мы будем с dataset digits — это стандартный dataset, который представляет из себя написанные от руки цифры. Вот давайте его загрузим. Делаем это с помощью модуля dataset из библиотеки sklearn. И теперь посмотрим, что же он из себя представляет. Посмотрим на описание. Мы видим, что набор представляет из себя изображение цифр, всего их 5620. Каждая цифра представляется в виде вектора из 64 цифр, каждая из которых характеризует яркость пикселя в данной точке. Соответственно, изображение представляет из себя прямоугольник 8 на 8. Мы видим, что пропущенных значений у нас, конечно же, нет. И также у нас есть ссылка на UCI репозиторий, в котором вы можете ознакомиться с полным описанием dataset и скачать его. Итак, теперь давайте посмотрим, как же выглядят данные и как представлены целевые метки. Вот мы видим, что… Смотрим на первый объект, у него целевая метка 0 — означает, что это рукописная цифра 0, и, собственно, мы видим набор его признаков. Вектор длиной 64, а изменяющийся в диапазоне от 0 до 16. Теперь давайте попробуем его отрисовать, посмотреть, как же эта картинка выглядит. Для того чтобы отрисовывать изображение, Python представляет нам функцию imshow — это функция библиотеки matplotlib. Вот давайте попробуем сделать следующее: передадим этой функции в качестве аргумента описание нашего объекта и попробуем его нарисовать. Вот потренируемся на самом первом объекте. Отметим, что почему-то ничего не получилось. Давайте смотреть почему. Написано, что размерность нашего объекта, размерность данных, не походит для того, чтобы строить рисунок. Давайте посмотрим, какая же у нас размерность. Видим, что размерность 64 и 0. То есть фактически мы передаем в данную функцию не матрицу, а вектор. Поэтому не понятно, как же этот вектор отобразить. Что мы с вами можем сделать? Мы можем вспомнить, что ndarray представляет нам функцию reshape, которая позволяет изменить размерность нашего вектора. Вот давайте вместо того чтобы работать со строчкой длиной 64, будем работать с матрицей длиной 8 на 8. Для этого вызовем метод reshape с параметрами 8 и 8. Вот давайте посмотрим. Видим, что данные не изменились, но теперь это уже не вектор, а матрица, поэтому кажется, что в этом виде можно попробовать нарисовать. На всякий случай вызываем метод shape. Видим, что размерность правильная, и теперь давайте рисовать. Вот видим, что теперь все получилось. Перед нами изображение рукописной цифры, и мы знаем, что это 0. На самом деле, создатели dataset уже позаботились о том, чтобы нам было удобно отображать цифры и не нужно было каждый раз делать reshape. Давайте посмотрим на все эти атрибуты, которые предоставляет наш dataset. Видим, что помимо данных, целевой переменной, имен классов и описаний, у нас есть еще ключ images. Давайте посмотрим, что это такое. Видим, что это фактически то же самое описание объекта, но только уже не в виде вектора, который очень удобен для решения задач классификации или кластеризации, а в виде матрицы, которая прекрасно подходит для того, чтобы объект рисовать. Вот давайте попробуем его отрисовать, используя images вместо data. И видим, что получаем ту же самую картинку, еще и удобнее — не нужно делать reshape. Теперь давайте посмотрим, как мы можем влиять на то, какое изображение получается. Возможно, в таком виде не очень видно, что это 0. Изображение довольно яркое, разноцветное, ну на это можно легко повлиять. Во-первых, мы можем влиять на то, каким и в какой цветовой она карте, в каком colormap отображается наше изображение. Мы можем выбрать любое. Например, выбрать colormap hot или выбрать colormap gray — это черно-белые тона. Также мы можем влиять на так называемую interpolation, или параметр, который отвечает за то, как будут выглядеть границы наших пикселей на изображении. Давайте рассмотрим 4 разных варианта. И видим, что, в общем-то, каждый может выбрать себе то, что вам больше нравится. Вот мне больше всего нравится черно-белое изображение, поэтому давайте в этих же цветах отрисуем и другие цифры. Посмотрим, как они выглядит, и легко ли их узнать глазами. Так, воспользуемся subplot и отрисуем первые 10 объектов из нашего dataset, будем надеяться, что это разные цифры. Так, видим, что мы получили изображение. Вот действительно, перед нами изображение цифр от 0 до 9, и в принципе невооруженным взглядом их узнать можно. Соответственно, это дает нам следующее предположение: если мы с вами цифры можем довольно неплохо узнать, мы видим, что, в общем-то, их начертание отличается, то, наверное, можно решать задачи классификации более-менее успешно. Наверное, она решается неплохо. Из предыдущих лекций вам известно, что такое представление цифр, а именно представление в виде 64 признаков, является несколько избыточным. Для того чтобы успешно отличать эти цифры друг от друга, нам достаточно гораздо меньшей размерности данных. Вот давайте попробуем сделать следующее: сначала уменьшим размерность данных теми методами, которые вы изучали, и посмотрим, как же это сказывается на качестве классификации. Для начала сделаем следующее: давайте отрежем небольшую подвыборку из нашей выборки данных и будем работать с ними. Это нужно только для того, чтобы все наши команды, всё то, что мы запускаем, работало несколько быстрее. Вы, конечно же, можете тренироваться на всем наборе данных. Вот я возьму первую тысячу. И теперь давайте посмотрим, что у меня получилась сбалансированная выборка, то есть, что все объекты встречаются приблизительно в одинаковой пропорции, объекты всех классов. Сделаем это с помощью Counter. Видим, что, ну действительно, каждый объект встречается приблизительно 100 раз, — то, что нужно. И чтобы это было более наглядно, можем нарисовать гистограмму. Это не сложно. И видим, что да, в принципе все объекты встречаются одинаковое количество раз. Теперь давайте построим некоторый классификатор. Ну так как мы хотим смотреть на то, как наши объекты отображаются на плоскости, нам подойдет метрический классификатор. Он работает на основе близости объектов, поэтому это то, что нужно. Выбираем классификатор K ближайших соседей. И давайте сделаем следующее: обучим его на всей выборке, на всех тех 1000 цифрах, которые мы выбрали, и посмотрим, какое получается качество. Фактически это нам скажет о том, насколько наши объекты легко классифицировать по их изображениям. Итак, мы видели довольно подробную информацию о качестве классификации. Сделали это с помощью метода classification_report. Он предоставляет нам подробную сводку о том, какую точность, полноту f1 мы получили для каждого класса (вот можем посмотреть, что классов здесь ровно 10), а также дает нам усредненные оценки. Видим, что в среднем мы правильно классифицируем практически всю выборку. В данном случае мы видим, что классификация производится на основании 5 ближайших соседей, поэтому что мы можем сказать? Мы можем сказать, что большинство объектов находятся в окружении объектов из своего класса. В общем-то, это хорошо. Это говорит о том, что наши изображения действительно похожи друг на друга, что начертания похожи, и на основе изображений мы можем решать эту задачу. Теперь давайте сделаем следующее: если мы перейдем в пространство меньшей размерности, то есть перейдем в пространство 2, нам снова будет интересно, остается ли это условие в силе. То есть в новом пространстве наши цифры так же находятся близко друг к другу или уже нет, или уже в ближайшем окружении начнутся встречаться объекты чужих классов, и тогда наше качество классификации уменьшится. Вот давайте на это посмотрим. Начнем с линейных методов понижения размерности. Первый метод, который мы рассмотрим, — это случайные проекции. Для начала нам нужно построить наши преобразования, делаем это с помощью модуля random_projection. Строим объект SparseRandomProjection и передаем ему следующие аргументы. Первый аргумент — это количество новых компонент, которые нас интересуют. Мы с вами хотим строить изображение наших объектов, поэтому нам удобно работать с двумя компонентами. И зададим random_state. Итак, после того, как мы наш объект построили, нужно это отображение обучить на исходных данных и применить, то есть получить данные в новой размерности. Вот давайте это сделаем с помощью метода fit_predict. Итак, готово наше новое представление о данных, теперь давайте его изобразим на плоскости. В данном случае мы видим набор точек, где разными цветами отображены объекты разных классов, то есть разными цветами у нас отображены разные цифры. Видим, что, в общем-то, они довольно сильно перемешены и так вот на глаз не очевидно, в какой области нужно ожидать встретить какую цифру. Ну на глаз оценивать такие вещи плохо, давайте попробуем обучить классификатор. Снова обучим ту же самую модель knn и сравним, насколько изменилось качество. Посмотрим для скольких объектов в ближайшем окружении вновь находятся объекты того же самого класса. Для этого оцениваем качество на обучающей выборке, и что мы видим? Наше качество в среднем упало до 50 %, то есть мы видим, что для половины объектов ближайшие 5 соседей уже могут быть числами из разных классов. Давайте посмотрим на следующий метод — это метод PCA, или метод главных компонент. Он уже находится в модуле decomposition RandomizedPCA. И давайте снова построим преобразование, в качестве результата получим представление объектов в двумерном пространстве. Снова применяем метод fit_predict, вернее fit_transform, и смотрим на наше изображение Видим, что, ну на глаз изображение кажется более качественным. У нас явно появились области разных цветов, то есть мы видим, что для некоторых классов получается отделить их от других. Получается сделать так, чтобы объекты этих классов были рядом друг с другом. Теперь давайте оценим это с помощью классификатора. Итак, считаем качество. И да, видим, что в среднем качество уже лучше, чем для предыдущего случая. Наша аккуратность 0,7, то есть, в общем-то, 70 % объектов мы все еще можем классифицировать. Представьте себе, как здорово — мы уменьшили размерность в 32 раза, вместо 64 признаков у нас теперь всего 2, и тем не менее, мы получаем довольно высокое качество классификации. Давайте двигаться дальше. Перейдем к нелинейным методам. Следующий метод, который мы рассмотрим, — это multidimensional scaling, или многомерное шкалирование. Он находится в модуле manifold. И давайте построим следующий объект: будем уменьшать размерность до 2 компонент и задачу оптимизации будем решать не более чем за 100 итераций. Строим обновленные данные, делаем это с помощью метода fit_transform, и теперь давайте отобразим изображение. Кажется, что нелинейные методы должны работать даже немножечко лучше. Вот давайте посмотрим. Ну да, видим, что вновь мы можем отличить группы объектов. И давайте получим оценку на основе классификации. Обучаем модель и видим, что качество примерно такое же, но немножечко больше. Тоже метод довольно неплохо работает. Последний метод, который мы рассмотрим, — это метод t-SNE. Его реализация также находится в модуле manifold, поэтому давайте создадим наш объект-преобразователь, основу оставим для компонента, инициализировать преобразование будем с помощью PCA. Другой вариант — делать это с помощью случайной инициализации, или random. И давайте получим преобразование данных с помощью метода fit_transform. Итак, это занимает какое-то время, потому что опять же мы решаем задачу оптимизации. А теперь давайте строить изображение. Видим, что это, наверное, самая лучшая картинка из всех, которую мы получили. Здесь очень легко убедиться в том, что объекты разных цветов или объекты разных классов находятся довольно далеко друг от друга. Кажется, что если мы будем решать задачу классификации в таких признаках, то мы должны получить довольно высокое качество. Может быть, даже сравнимое с изначальным, с данными в изначальном пространстве. Вот давайте это проверим. Снова обучим классификатор ближайших соседей и видим, что да, действительно, наше качество в среднем равняется 0,99 по метрике accuracy, то есть практически нигде мы с вами не ошибаемся. Тоже довольно неплохой метод уменьшения размерности. А на этом мы заканчиваем. На этом уроке мы научились на практике применять такие методы уменьшения размерности, как t-SNE, multidimensional scaling, PCA, а также метод случайных проекций. На этом мы заканчиваем модуль по визуализации данных, а на следующей неделе вы познакомитесь с такими интересными задачами, как topic modeling, или тематическое моделирование.