Объясните функцию contourf matplotlib - PullRequest
1 голос
/ 03 августа 2020

Я пытаюсь построить область решения (на основе результатов логистической c регрессии) с помощью функции matplotlib contourf. Код, который я использую:

subplot.contourf(x2, y2, P, cmap=cmap_light, alpha = 0.8)

, где x2 и y2 - две 2D-матрицы, созданные с помощью сеток numpy. P вычисляется с использованием

P = clf.predict(numpy.c_[x2.ravel(), y2.ravel()])
P = P.reshape(x2.shape) 

. Каждый элемент P является логическим значением, основанным на выходе логистической c регрессии. Визуализированный график выглядит так введите описание изображения здесь

Мой вопрос: как функция contourf знает, где рисовать контур на основе 2D-матрицы логических значений? (x2, y2 - это просто numpy meshgrids) I просмотрел документы несколько раз, но ничего не понял.

1 Ответ

2 голосов
/ 03 августа 2020

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

Во-первых, регрессия рассчитывается на основе заданных данных (точки с черным контур). Затем для каждой точки сетки, покрывающей данные, вычисляется прогноз (маленькие точки в сетке). Обратите внимание, что заданные и прогнозируемые значения - это просто числа 0, 1 и 2. (В вопросе используются только 0 и 1.)

Последний шаг - использование этих точек сетки в качестве входных данных для поиска контуров регионы с равным прогнозируемым значением. Итак, контурная линия проводится между точками сетки, имеющими значение 0 и теми, которые имеют значение 1. И еще одна между значениями 1 и 2. A contourf заполняет область между линиями однородным цветом. .

Поскольку точки сетки и их прогноз не визуализируются на графике вопроса, внезапные контуры труднее понять.

from matplotlib import pyplot as plt
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression

X, y = load_iris(return_X_y=True)
X = X[:, :2]
clf = LogisticRegression(random_state=0).fit(X, y)

x2, y2 = np.meshgrid(np.linspace(X[:, 0].min()-.5, X[:, 0].max()+.5, 20),
                     np.linspace(X[:, 1].min()-.5, X[:, 1].max()+.5, 20) )
pred = clf.predict(np.c_[x2.ravel(), y2.ravel()])

cmap = plt.get_cmap('Set1', 3)
plt.scatter(x2.ravel(), y2.ravel(), c=pred, s=10, cmap=cmap, label='Prediction on grid')
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=cmap, ec='black', label='Given values')
plt.contourf(x2, y2, pred.reshape(x2.shape), cmap=cmap, alpha=0.4, levels=2, zorder=0)
plt.legend(ncol=2, loc="lower center", bbox_to_anchor=(0.5,1.01))
plt.show()

пример сюжета

PS: Примерно pred.reshape(x2.shape):

  • x2 и y2 - это массивы, задающие координаты x и y каждой точки сетки. x2 и y2 организованы как 2D-массивы, похожие на сетку, которую они представляют (20x020 в примере).
  • Однако функция clf.predict требует, чтобы ее входные массивы были 1d. Для этого используется .ravel(): он просто создает один длинный массив 1d из массива 2d. В этом примере ravel преобразует массивы 20x20 в 1d массивы из 400.
  • Результатом pred = clf.predict является соответствующий 1d массив (400 элементов).
  • pred.reshape(x2.shape) преобразует pred в тот же формат 2d, что и x2 и y2 (снова 20x20).
  • Обратите внимание, что scatter хочет, чтобы его параметры были в формате 1d, он просматривает только каждую точку отдельно. contourf, с другой стороны, хочет, чтобы его параметры были в 2-мерном формате, поскольку ему нужно знать, как устроена сетка.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...