Гауссово суммирование для 2D-диаграмм рассеяния с использованием python

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

Для примера я привожу случайную пару данных (x, y) ниже. Реальные данные будут распределены в разных масштабах, отсюда и разница в расстоянии между точками сетки по осям X и Y.

import numpy as np
from matplotlib import pyplot as plt

def homemadeKDE(x, xgrid, y, ygrid, sigmaX = 1, sigmaY = 1):

    a = np.exp( -((xgrid[:,None]-x)/(2*sigmaX))**2 )
    b = np.exp( -((ygrid[:,None]-y)/(2*sigmaY))**2 ) 

    xweights = np.dot(a, x.T)/np.sum(a)
    yweights = np.dot(b, y.T)/np.sum(b)  

    return xweights, yweights

x = np.random.rand(10000)
x.sort()
y = np.random.rand(10000)

xGrid = np.linspace(0, 500, 501)
yGrid = np.linspace(0, 10, 11)

newX, newY = homemadeKDE(x, xGrid, y, yGrid)

Я застрял в том, как спроецировать эти значения обратно в исходный вектор x и y, чтобы я мог использовать его для построения двумерного графика рассеяния (x, y) со значением z для плотности, окрашенной заданной цветовой картой, например так :

plt.scatter(x, y, c = z, cmap = "jet")

Подход к построению графиков и KDE на самом деле вдохновлен этим замечательным ответом.

РЕДАКТИРОВАТЬ 1 Чтобы сгладить некоторую путаницу, идея состоит в том, чтобы сделать гауссовский KDE, который был бы на гораздо более грубой сетке. SigmaX и sigmaY отражают пропускную способность ядра в направлениях x и y соответственно.


person Fourier    schedule 23.03.2018    source источник
comment
У меня есть некоторые проблемы с пониманием кода. Аргументы в функции обращены к тому, как вызывается функция? Что такое столица X? И последнее, но не менее важное: какова цель этой функции?   -  person ImportanceOfBeingErnest    schedule 23.03.2018
comment
Исправлен синтаксис. Простите за это.   -  person Fourier    schedule 23.03.2018
comment
И все же, что это за весы? почему оба веса рассчитываются как произведение с одним и тем же x?   -  person ImportanceOfBeingErnest    schedule 23.03.2018
comment
Веса — это просто взвешивание точек на основе сетки, следующих следующему определению: /2014/02/26/ядро-регрессия   -  person Fourier    schedule 23.03.2018
comment
Каким будет z в вашем случае? Как вы хотите, чтобы ваши данные x,y были точно окрашены?   -  person Gabriel    schedule 23.03.2018
comment
@Gabriel Это похоже на вектор окраски точек, основанный на биннинге с помощью непрерывных функций Гаусса. Пожалуйста, взгляните на решение на основе scipy.stats, которое я предоставил в ссылке.   -  person Fourier    schedule 23.03.2018
comment
Функция scipy.stats.gaussian_kde() возвращает одно значение (KDE) для каждой пары x,y, а ваша функция homemadeKDE() возвращает два. Тогда мне непонятно, что будет эквивалентно значению KDE в вашем случае (то есть: z на диаграмме рассеяния)   -  person Gabriel    schedule 23.03.2018
comment
Это то, о чем я прошу, способ правильной обратной проекции. Можно было бы просто использовать np.dot() для умножения весов, но тогда вектор все равно меньше исходного, что очевидно из-за того, что моих точек сетки меньше, чем точек данных.   -  person Fourier    schedule 23.03.2018
comment
Откуда исходит предположение, что два отдельных kde в каждом измерении будут иметь какое-то отношение к 2D kde, к которому вы стремитесь? Может, это все-таки математический вопрос?   -  person ImportanceOfBeingErnest    schedule 23.03.2018
comment
У вас есть конкретная причина не использовать функцию scipy.stats.gaussian_kde()?   -  person Gabriel    schedule 23.03.2018
comment
@ImportanceOfBeingErnest Вполне может быть. Я могу сделать неправильную вещь здесь. Может быть, мне придется зацикливаться на каждой паре точек и складывать гауссову сумму. Я стремился к более быстрому подходу, который, вероятно, математически неверен.   -  person Fourier    schedule 23.03.2018
comment
@Габриэль Ничего. И я использовал его работает отлично. Однако я хотел написать свой собственный код, чтобы понять его немного яснее.   -  person Fourier    schedule 23.03.2018
comment
Возможно, это поможет, взгляните на то, как генерируется многовариантный KDE: -multivariate-gaussian-densities" rel="nofollow noreferrer">sebastianraschka.com/Articles/   -  person Gabriel    schedule 23.03.2018


Ответы (1)


На самом деле, немного подумав, я смог решить проблему самостоятельно. Также спасибо за помощь и проницательные комментарии.

import numpy as np
from matplotlib import pyplot as plt

def gaussianSum1D(gridpoints, datapoints, sigma=1):

    a = np.exp( -((gridpoints[:,None]-datapoints)/sigma)**2 )

    return a

#some test data
x = np.random.rand(10000)
y = np.random.rand(10000)

#create grids
gridSize = 100
xedges = np.linspace(np.min(x), np.max(x), gridSize)
yedges = np.linspace(np.min(y), np.max(y), gridSize)

#calculate weights for both dimensions seperately
a = gaussianSum1D(xedges, x, sigma=2)
b = gaussianSum1D(yedges, y, sigma=0.1)

Z = np.dot(a, b.T).T

#plot original data
fig, ax = plt.subplots()
ax.scatter(x, y, s = 1)
#overlay data with contours 
ax.contour(xedges, yedges, Z, cmap = "jet")
person Fourier    schedule 06.04.2018
comment
Спасибо за указание на это. Однако четкий отчет об ошибке помог бы исправить код. - person Fourier; 16.10.2019
comment
TypeError: unsupported operand type(s) for *: 'NoneType' and 'float' было сообщением об ошибке, но теперь оно исправлено. - person Code Pope; 16.10.2019