ORTHOGONAL POLYNOMIAL DENSITY ESTIMATION

Preliminaries

Imports


In [1]:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sbn
import pandas as pd
from uuid import uuid4

from lpde.geometry import WidthOf, Window, PointAt, BoundingBox, Mapper
from lpde.estimate import DensityEstimate
from lpde.estimate.helpers import Event, Degree, Action, Scalings

Notebook settings


In [2]:
%matplotlib notebook

Density Estimation

Initialize


In [3]:
legendre_width = WidthOf(1.8)

center = PointAt(0, 0)
window = Window(1.8, 1.8)
bounds = BoundingBox(center, window)

mapper = Mapper(bounds, legendre_width)

degree = Degree(20, 20)
density = DensityEstimate(degree, mapper)

action = Action.ADD
point = PointAt(0.5, 0.5)
event = Event(uuid4(), action, point)

Create mock data streams


In [4]:
def gaussian():
    x, y = np.random.multivariate_normal((0,0), ((0.1,0), (0,0.1)))
    if (-0.9 <= x <= 0.9) and (-0.9 <= y <= 0.9):
        return x, y
    else:
        return gaussian()

def uniform():
    return np.random.uniform(low=-0.9, high=0.9, size=2)

def new_event(dist):
    location = dist()
    point = PointAt(*location)
    return Event(uuid4(), Action(1), point)

def random_event(dist):
    event_type = np.random.randint(low=-1, high=2)
    if event_type == 1:
        location = dist()
        point = PointAt(*location)
        return Event(uuid4(), Action(1), point)
    elif event_type == 0:
        location = dist()
        point = PointAt(*location)
        column = density._phi.sample(1, axis=1).columns.values[0]
        return Event(column, Action(0), point)
    column = density._phi.sample(1, axis=1).columns.values[0]
    return Event(column, Action(-1))

Timings of density estimation


In [5]:
%%time
for i in range(1000):
    density.update_with(new_event(uniform))


/home/georg/Documents/Python/LPDE/lpde/estimate/estimator.py:88: RuntimeWarning: overflow encountered in double_scalars
  return self.__neg_log_l(c[1:]) + c[0]*self.__norm(c[1:])
/home/georg/Documents/Python/LPDE/lpde/estimate/estimator.py:96: RuntimeWarning: overflow encountered in square
  return -log(square(c.dot(self.__phi_ijn.values))).sum()
/home/georg/Documents/Python/LPDE/lpde/estimate/estimator.py:92: RuntimeWarning: overflow encountered in multiply
  self.__grad_c[1:] = self.__grad_neg_log_l(c[1:]) + 2.0*c[0]*c[1:]
CPU times: user 4min 31s, sys: 5.48 s, total: 4min 37s
Wall time: 34.7 s

In [ ]:
%%time
for i in range(1000):
    density.update_with(random_event(uniform))

In [ ]:
%%time
for i in range(1000):
    density.at(new_event(uniform).location)

Timings

33 ms per additive update with uniform distribution

31 ms per random update with uniform distribution

0.6 ms per evaluation at point

Plot final density


In [ ]:
x_grid = np.linspace(-0.9, 0.90, 100)
y_grid = np.linspace(-0.9, 0.90, 100)
x_grid, y_grid = np.meshgrid(x_grid, y_grid)

p_hat = density._on(x_grid, y_grid)

fig, ax = plt.subplots()
ax.set(xlabel=r'$x$', ylabel=r'$y$')
contour = ax.contourf(x_grid, y_grid, p_hat, 9, cmap='inferno')
cbar = plt.colorbar(contour, ax=ax, label=r'$p(x)$')
fig.tight_layout()

Further timings


In [ ]:
%prun -s cumulative density.update_with(new_event(gaussian))

In [ ]:
%timeit -n 10 -r 100 susi = -2*(density._phi.values / density._c.dot(density._phi.values)).sum(axis=1)

In [ ]:
%timeit -n 10 -r 100 susi = -2*(test / density._c.dot(density._phi.values)).sum(axis=1)

In [ ]:
%timeit -n 10 -r 100 susi = -2*(test / denom).sum(axis=1)

In [ ]:
%timeit -n 1000 -r 100 density._c.dot(density._phi.values)

In [ ]:
%timeit -n 1000 -r 100 density._phi.values.T.dot(density._c)

In [ ]:
denom = np.ones((441, 1)) * density._c.dot(density._phi.values)

In [ ]:
test = density._phi.values.copy()

In [ ]:
tmp = np.zeros_like(density._phi.values)

In [ ]: