Корреляционная матрица: что такое, как строится и для чего используется

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

Где мы остановились? Корреляция

Структура данных, о которой я говорю, — это мощная корреляционная матрица. Как и многие другие концепции науки о данных, это алгебраическая концепция, которую легко понять и еще проще использовать. Давайте кратко повторим корреляцию: это индекс, который показывает линейную зависимость между двумя случайными величинами X и Y. Это всегда число от -1 до 1, где:

  • -1 означает, что две переменные имеют обратную линейную зависимость: когда X увеличивается, Y уменьшается
  • 0 означает отсутствие линейной корреляции между X и Y
  • 1 означает, что две переменные имеют линейную зависимость: когда X увеличивается, Y также увеличивается.

Остерегаться! Корреляция не подразумевает причинно-следственную связь. Когда корреляция между X и Y близка к 1, мы не можем сказать, что изменение X подразумевает последующее изменение Y. Например, рассмотрим две переменные: «Количество мороженого, проданное ежедневно в течение одного года». » и «Количество солнечных ожогов в течение одного года». Эти две переменные, вероятно, будут иметь высокую корреляцию, но изменение одной из двух переменных не отразится на другой. Высокая корреляция, низкая причинность. Теперь: вернемся к корреляционной матрице.

Корреляционная матрица

Корреляционная матрица представляет собой квадрат (количество строк равно количеству столбцов), симметричную (матрица равна своей транспонированной), все элементы главной диагонали равны 1 и полуопределенной положительной (все ее собственные значения неотрицательны) матрицы. В то время как первые 3 свойства просты для понимания и визуализации, стоит сказать пару слов о последнем условии, потому что не все квадратные, симметричные с главной диагональю, равной 1, являются полуопределенными положительными, и, таким образом, не все матрицы, удовлетворяющие первым трем требованиям, являются корреляционными матрицами. Например, следующая матрица:

m = [
    [1, 0.6, 0.9],
    [0.6, 1, 0.9],
    [0.9, 0.9, 1]
]

имеет одно отрицательное собственное значение. Вы могли бы найти это с ручкой и бумагой, но зачем беспокоиться, если мы можем заставить кого-то другого заниматься математикой? Мы можем использовать Python и numpy, чтобы получить все собственные значения m:

m = [
    [1, 0.6, 0.9],
    [0.6, 1, 0.9],
    [0.9, 0.9, 1]
]
eigenvalues = np.linalg.eig(m)
print(eigenvalues[0])
Out: [ 2.60766968  0.4        -0.00766968]

функция np.linalg.eig принимает на вход матрицу (которая во всех языках программирования может быть представлена ​​в виде списка списков, массива массивов или вектора векторов) и возвращает кортеж с двумя элементами:

  • Первый — это список собственных значений матрицы.
  • Второй — это список, содержащий нормализованные собственные векторы матрицы

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

Построение корреляционной матрицы

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

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

Когда я начал читать эту книгу для изучения машинного обучения, первый полный пример прогностических моделей (простая линейная регрессия, глава 2) обучался на наборе данных, составленном из данных о домах округов Калифорнии. Скачать его можно здесь. Когда я впервые прочитал, что такое линейная регрессия, и когда я изучил часть исследовательского анализа (где появились корреляция и корреляционные матрицы), мои двери восприятия быстро открылись, как кто-то сказал. Да, без мескалина. Нам, информатикам, так мало нужно, чтобы споткнуться. Между прочим: каждая строка набора данных представляет отдельный район Калифорнии; Кроме того, каждая строка имеет следующие функции (feature — отличное название для случайной переменной или даже лучше: переменная, по которой можно вычислить некоторые статистические индексы):

  • долгота
  • широта
  • средний возраст дома
  • общее количество комнат
  • общее количество спален
  • численность населения
  • домохозяйства
  • средний доход
  • средняя стоимость дома
  • близость океана

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

Можно сказать, что наш набор данных имеет размерность n x 10, где n — количество строк, то есть количество округов Калифорнии.

Давайте построим матрицу корреляции для этого набора данных. Переменные, по которым мы собираемся вычислять корреляции, — это 10 признаков набора данных. О, ну, в этом наборе данных есть один признак, для которого корреляция просто не имеет смысла: мы говорим о признаке ocean_proximity, категориальной переменной. «Категорический» означает, что домен переменной представляет собой дискретный набор значений, а не непрерывный набор чисел. В частности, для этих функций допускаются только следующие значения:

{“1H OCEAN”, “INLAND”, “NEAR OCEAN”, “NEAR BAY”, “ISLAND” }

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

Давайте теперь заполним нашу матрицу фактическими корреляциями. Напомню, что каждый элемент матрицы имеет один индекс строки и один индекс столбца, которые описывают его положение в матрице. Мы начинаем считать строки и столбцы с 0: это означает, что (например) самое нижнее левое значение имеет позицию 8, 0 (строка 8, столбец 0). Крайний правый элемент четвертой строки имеет позицию 3, 8 (строка 3, столбец 8). Симметрия матрицы говорит нам еще об одной интересной вещи: элемент с позицией i, j равен элементу с позицией j, i (элемент в позиции 3, 8 равен элементу в позиции 8, 3): чтобы удовлетворить этому свойству, мы должны построить матрицу так, чтобы переменная то, что находится в определенном, тоже находится в той же колонке. Например, давайте начнем с признака longitude и скажем, что мы хотим использовать его в строке 0. Условие симметрии накладывает, что мы должны использовать признак longitude для столбца 0. Затем давайте проделаем то же самое с latitude: строка 1, столбец 1. housing_median_age? Строка 3, столбец 3 и так далее, пока мы не используем все функции набора данных и не получим вот такую ​​пустую матрицу:

Попробуем прочитать эту матрицу: элемент с позицией 0, 5(строка 0, столбец 5) представляет корреляцию между долготой и населением; для свойства симметрии он равен элементу с позицией 5, 0, который представляет корреляцию между населением и долготой. Корреляция между двумя переменными X и Y равна корреляции между Y и X. То же самое для элемента с позицией 6, 7, элемента, содержащего корреляцию между «домохозяйствами» и «медианным_доходом» и равного элементу с индексом 7, 6, корреляция между median_income и households.

Теперь рассмотрим элемент с главной диагонали матрицы, например, элемент с позицией 4, 4: он будет представлять корреляцию `total_bedrooms` сама с собой. По определению корреляция переменной с самой собой всегда равна 1. Конечно, все главные диагональные элементы обладают этим свойством: все главные диагональные элементы корреляционной матрицы равны 1.

Матрица корреляции в Python, pandas и seaborn

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

import pandas as pd
housing = pd.read_csv('datasets/housing.csv')
rounded_corr_matrix = housing.corr().round(2)
print(rounded_corr_matrix[‘median_income’])

После именованной (это часть as pd) инструкции импорта давайте прочитаем CSV-файл, который мы скачали ранее, с помощью метода pandas read_csv, который принимает путь к файлу в качестве входных данных и позволяет сохранить результаты чтения в переменной с именем housing. Тип данных, возвращаемый read_csv, — это DataFrame, самый важный тип данных, определенный в pandas, который представляет собой набор данных (кто-то сказал «набор данных»?). Мы можем использовать множество методов и функций в DataFrame, и среди них у нас есть метод corr(); как следует из названия, мы можем использовать его для получения корреляционной матрицы из набора данных! Мы округляем значения корреляции до второго десятичного знака с помощью метода round(2) только потому, что хотим работать с более читаемой матрицей. В следующей инструкции мы печатаем значения корреляции между median_income и всеми остальными функциями в виде панд Series. Это структура данных, напоминающая обычный массив (т. е. мы можем получить доступ к его значениям с помощью числового индекса), но обладающая сверхспособностями. Кроме того, мы можем получить доступ к одному конкретному значению, указав второй индекс. Например:

rounded_corr_matrix['median_income']['housing_median_age']

будет поддерживать корреляцию между median_income и housing_median_age. Удобно, правда? Мы также можем вывести все значения корреляции для признака median_income, упорядоченные по убыванию, с помощью инструкции

rounded_corr_matrix["median_income"].sort_values(ascending=False)

Результат будет:

median_income         1.00
median_house_value    0.69
total_rooms           0.20
households            0.01
population            0.00
total_bedrooms       -0.01
longitude            -0.02
latitude             -0.08
housing_median_age   -0.12
Name: median_income, dtype: float64

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

import seaborn as sns
heatmap = sns.heatmap(rounded_corr_matrix, annot=True)
heatmap.set_title('Correlation Heatmap', fontdict={'fontsize':12}, pad=12)

Тепловая карта — это инструмент визуализации данных, в котором конкретное явление отображается в цветовой шкале. В нашем случае более темные цвета используются для сопоставления более низких значений (с черным сопоставлением значения корреляции -1), в то время как более высокие значения сопоставляются с более светлыми цветами (с белым сопоставлением значения корреляции +1). У Seaborn есть метод heatmap, который принимает в качестве первого параметра двумерную структуру данных, из которой мы собираемся создать тепловую карту: в нашем случае корреляционную матрицу. Мы передаем в функцию heatmap еще один параметр с именем annot: полезно записывать в ячейки тепловой карты фактические значения корреляции, чтобы получить более точное представление о том, что происходит.

​​

Полезность тепловой карты, как мы видим, зависит от оперативности интерпретации визуализированных данных. Например, после беглого взгляда видно, что существует высокая корреляция между `total_bedrooms` и total_rooms (0,93, очень близко к 1), total_roomns и population, total_bedrooms и households. Это имеет смысл, не так ли? Напротив, у нас будет низкое значение корреляции для latitude и longitude (подождите немного и попытайтесь визуализировать форму штата Калифорния…). Мы ничего не можем сказать о значениях около 0 (например, median_income и population).

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

features = ["median_house_value", "median_income", "total_rooms",
                  "housing_median_age"]
subset = rounded_corr_matrix[features].loc[features]
heatmap = sns.heatmap(subset, annot=True)

Мы замечаем, что если мы попытаемся просто получить доступ к rounded_corr_matrix[features], мы получим матрицу 9x4, содержащую корреляцию 4 выбранных функций с всеми другими функциями набора данных. Мы используем атрибут loc pandas, который позволяет нам получить доступ к подмножеству функций структуры данных 9x4, используя их имена, а не числовые индексы. Эти имена, конечно, features имен. Мы получаем структуру 4x4, на которой мы можем использовать нашу тепловую карту. Вот результат:

Матрица рассеяния — Основы

В конце мы используем функцию pandas scatter_matrix, которая обеспечивает гораздо более интуитивную визуализацию корреляционной матрицы. Как следует из названия, эта матрица состоит не из чисел, а из точечных диаграмм (двумерных диаграмм, в которых каждая ось является функцией набора данных).

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

from pandas.plotting import scatter_matrix
features = ["total_rooms", "population", "households", "median_house_value"]
scatter_matrix(housing[features], figsize=(12, 8))

Результат:

Обратите внимание на одну любопытную вещь: у нас есть гистограммы на главной диагонали. Теоретически мы должны найти в этих положениях корреляции между переменными и сами, но если бы мы их нарисовали, то получили бы просто линии с уравнением y=x (у нас были бы одинаковые значения на обоих ось х и ось у — прямая линия). Вместо того, чтобы визуализировать линию под углом 45 градусов, `scatter_matrix` показывает нам гистограммы этих переменных, просто чтобы иметь представление о распределении функций. Глядя на другие графики, можно увидеть, что для определенных пар переменных (например, население/общее количество комнат или домохозяйства/население) наблюдается четкая положительная корреляция, в некоторых случаях очень близкая к 1. Напротив, все присутствующие переменные значение корреляции с `median_house_value` (наиболее интересная функция, если мы разработаем прогностическую модель машинного обучения) близко к 0, а графики очень «разреженные».

Использование корреляционных матриц

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

features = ["median_house_value", "total_rooms", "median_income"]
scatter_matrix(housing[features], figsize=(12, 8))

Мы бы обнаружили довольно четкую корреляцию между median_income и median_house_value (чем выше средний доход, тем выше медианная стоимость дома… как всегда, это имеет смысл). Затем мы могли бы попытаться построить, обучить и оптимизировать простую модель линейной регрессии. Мы не получим очень точную модель, но это все же отправная точка, не так ли?

Бонус-трек — Калифорния, мы идем!

Ранее в статье мы спрашивали, что может означать очень низкое значение корреляции между latitude и longitude. Ради науки давайте нарисуем точечную диаграмму этих двух переменных:

Эй, разве это не похоже на настоящую Калифорнию? Да, конечно! Низкое значение корреляции между широтой и долготой связано с географической формой Калифорнии, которая напоминает линию с отрицательным угловым коэффициентом. Разве это не смешно?

Вот код для создания этой точечной диаграммы с пандами:

housing[['longitude', 'latitude']].plot.scatter(x="longitude", y="latitude")

Удачного обучения и кодирования!