Как distplot вычисляет кривую kde? - PullRequest
0 голосов
/ 15 апреля 2020

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

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

x = np.random.normal(size=100)
sns.distplot(x)
plt.show()

Результат этого кода:

plot result

Мои вопросы:

1 - Как distplot удается построить это?

2- Почему начинается график с -3 и заканчивается на 4?

3- Существует ли какая-либо параметрическая c функция или какая-либо конкретная c математическая функция, которую использует distplot для построения таких данных?

Я использую distplot и kde для построения своих данных, но Я хотел бы знать, что за математика стоит за этими функциями.

1 Ответ

0 голосов
/ 15 апреля 2020

Вот некоторый код, пытающийся проиллюстрировать, как рисуется кривая kde.

Код начинается со случайной выборки 100 xs.

Эти xs показаны в гистограмме . При density=True гистограмма нормализуется таким образом, чтобы ее полная площадь была равна 1. (Стандартно, столбцы гистограммы растут с количеством точек. Внутренне полная область вычисляется, а высота каждого столбца делится на эту область.)

Чтобы нарисовать kde , вокруг каждого из N образцов рисуется гауссов «колокольчик». Эти кривые суммируются и нормализуются путем деления на N. sigma этих кривых является свободным параметром. По умолчанию рассчитывается по правилу Скотта (N ** (-1/5) или 0.4 для 100 точек, зеленая кривая на примере графика).

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

import matplotlib.pyplot as plt
import numpy as np

def gauss(x, mu, sigma):
    return np.exp(-((x - mu) / sigma) ** 2 / 2) / (sigma * np.sqrt(2 * np.pi))

N = 100
xs = np.random.normal(0, 1, N)

plt.hist(xs, density=True, label='Histogram', alpha=.4, ec='w')
x = np.linspace(xs.min() - 1, xs.max() + 1, 100)
for sigma in np.arange(.2, 1.2, .2):
    plt.plot(x, sum(gauss(x, xi, sigma) for xi in xs) / N, label=f'$\\sigma = {sigma:.1f}$')
plt.xlim(x[0], x[-1])
plt.legend()
plt.show()

resulting plot

PS: вместо гистограммы или kde другие способы визуализации 100 случайных чисел представляют собой набор коротких линий:

plt.plot(np.repeat(xs, 3), np.tile((0, -0.05, np.nan), N), lw=1, c='k', alpha=0.5)
plt.ylim(ymin=-0.05)

или точек (с дрожанием, чтобы они не перекрывались):

plt.scatter(xs, -np.random.rand(N)/10, s=1, color='crimson')
plt.ylim(ymin=-0.099)
...