В качестве минимального воспроизводимого примера, предположим, что у меня есть следующее многомерное нормальное распределение:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.stats import multivariate_normal, gaussian_kde
# Choose mean vector and variance-covariance matrix
mu = np.array([0, 0])
sigma = np.array([[2, 0], [0, 3]])
# Create surface plot data
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
rv = multivariate_normal(mean=mu, cov=sigma)
Z = np.array([rv.pdf(pair) for pair in zip(X.ravel(), Y.ravel())])
Z = Z.reshape(X.shape)
# Plot it
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
pos = ax.plot_surface(X, Y, Z)
plt.show()
Это дает следующий график поверхности:
Myцель состоит в том, чтобы обойти это и использовать оценку плотности ядра, чтобы получить хороший и плавный 1D гауссов.Я сталкиваюсь с 2 проблемами:
- Не уверен, что моя методика маргинализации имеет смысл.
- После маргинализации у меня остается барплот, но gaussian_kde требует фактических данных (а не их частоты)для того, чтобы соответствовать KDE, поэтому я не могу использовать эту функцию.
Вот как я его изолирую:
# find marginal distribution over y by summing over all x
y_distribution = Z.sum(axis=1) / Z.sum() # Do I need to normalize?
# plot bars
plt.bar(y, y_distribution)
plt.show()
и вот барплот, который я получаю:
Далее я следую этому вопросу StackOverflow, чтобы найти KDE только по данным "гистограммы".Для этого мы повторно сэмплируем гистограмму и подгоняем KDE для повторных сэмплов:
# sample the histogram
resamples = np.random.choice(y, size=1000, p=y_distribution)
kde = gaussian_kde(resamples)
# plot bars
fig, ax = plt.subplots(nrows=1, ncols=2)
ax[0].bar(y, y_distribution)
ax[1].plot(y, kde.pdf(y))
plt.show()
Это дает следующий график:
который выглядит "хорошо", но эти два графика явно не в одном масштабе.
Проблема кодирования
Почему KDE выходит в другом масштабе?Или, скорее, почему барплот в другом масштабе, чем KDE?
Чтобы еще раз подчеркнуть это, я изменил ковариационную матрицу дисперсии, чтобы мы знали, что предельное распределение по y является нормальным распределением с центром в0 с дисперсией 3. На данный момент мы можем сравнить KDE с фактическим нормальным распределением следующим образом:
plt.plot(y, norm.pdf(y, loc=0, scale=np.sqrt(3)), label='norm')
plt.plot(y, kde.pdf(y), label='kde')
plt.legend()
plt.show()
Это дает:
Это означает, что гистограмма имеет неправильный масштаб.Какая проблема кодирования сделала барплот в неправильном масштабе?