Почему мой график kde отображается в виде вертикальных линий, а не кривой? - PullRequest
0 голосов
/ 28 апреля 2020

Я пытался составить график KDE для данных, которые у меня есть (частота сайтов запуска хромосом), и хотя я точно следую примерам , когда я использую свои данные или сгенерированные данные, которые выглядят как мои собственный, весь график портится и выдает только вертикальные линии вместо нормальной кривой. Я надеялся, что кто-то, более знакомый с scikit, узнает, что KDE поможет мне понять, что я делаю неправильно.

Вот код с сгенерированными данными из примера, где все работает нормально:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from sklearn.neighbors import KernelDensity

X = np.concatenate((np.random.normal(0, 1, 14), np.random.normal(5, 1, 6)))[:, np.newaxis]
X_plot = np.linspace(-5, 10, 1000)[:, np.newaxis]
kde = KernelDensity(kernel='gaussian', bandwidth=1.0).fit(X) 
log_density = kde.score_samples(X_plot)

fig, ax = plt.subplots()
plt.fill_between(X_plot[:, 0], np.exp(log_density), color="b")
plt.plot(X, np.full_like(X, -0.01), '|k', markeredgewidth=.01)
ax.set_xlim(-5, 10)

Вот код с данными, которые я сгенерировал, чтобы выглядеть как мои данные. У меня есть 1000 начальных сайтов в данных, и их значение варьируется от 10000 до 824989. Я изменил данные, диапазон и шаг linspace и ось x, и теперь я получаю вертикальные линии вместо кривой. Я также изменил пределы y, потому что они оказались действительно странными.

X = np.random.normal(10000, 824989, 1000)[:, np.newaxis]
X_plot = np.linspace(10000, 824989, 100000)[:, np.newaxis]
kde = KernelDensity(kernel='gaussian', bandwidth=1.0).fit(X) 
log_density = kde.score_samples(X_plot)

fig, ax = plt.subplots()
plt.fill_between(X_plot[:, 0], np.exp(log_density), color="b")
plt.plot(X, np.full_like(X, -0.01), '|k', markeredgewidth=.01)
ax.set_xlim(10000, 824989)
ax.set_ylim(-0.0001, 0.00061) 

Я думаю, что это как-то связано с linspace. Я не очень понимаю, почему score_samples() также принимает в качестве параметра linspace.

1 Ответ

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

С вашим кодом есть две проблемы:

  1. Пропускная способность, используемая при оценке плотности ядра, должна быть выше, поскольку ваши данные имеют гораздо большее стандартное отклонение по сравнению с примером (ваши данные имеют стандартное отклонение 824,989, в то время как данные, используемые в примере, имеют стандартное отклонение 2,5). Вам потребуется использовать полосу пропускания приблизительно 200 000 вместо полосы пропускания 1. См., Например, раздел «Оценочное значение полосы пропускания» в статье Википедии об оценке плотности ядра .
  2. Цель использования np.linspace() состоит в том, чтобы сгенерировать набор точек данных, в которых можно оценить оценочную функцию плотности ядра kde. Чтобы иметь возможность визуализировать полное распределение ваших данных, первый аргумент np.linspace() должен быть установлен равным минимуму данных (вместо среднего значения данных), а второй аргумент np.linspace() должен быть установлен равно максимуму данных (вместо стандартного отклонения данных).

Я включил приведенный ниже пример.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KernelDensity

mu = 10000 # mean
sigma = 824989 # standard deviation

# generate the data
X = np.random.normal(mu, sigma, 1000)[:, np.newaxis]

# estimate the optimal bandwidth
h = 1.06 * np.std(X) * (len(X) ** (- 1 / 5))

# estimate the density function
kde = KernelDensity(kernel='gaussian', bandwidth=h).fit(X)

# evaluate the density function
x = np.linspace(np.min(X), np.max(X), 100000)[:, np.newaxis]
log_density = kde.score_samples(x)
density = np.exp(log_density)

# plot the density function
plt.plot(x, density)
...