import numpy as np
from numba_stats import bernstein, norm, expon
import matplotlib.pyplot as plt
from scipy.integrate import quad
from typing import Callable
This is a demo of how to use custom orthogonal weight functions (COWs) to generate weights which extract one component of a mixture. Find out more in our paper.
= np.random.default_rng(1)
rng
= rng.normal(1, 0.1, size=10000)
s_x = rng.exponential(1, size=100000)
b_x = rng.exponential(1, size=len(s_x))
s_y = rng.normal(0, 1, size=len(b_x))
b_y
= np.append(s_x, b_x)
x = np.append(s_y, b_y)
y id = np.append(np.ones_like(s_x, dtype=bool), np.zeros_like(b_x, dtype=bool))
xrange = 0, 2
= 0, 4
yrange = (x > xrange[0]) & (x < xrange[1]) & (y > yrange[0]) & (y < yrange[1])
m = x[m]
x = y[m]
y id = id[m]
= x[id]
s_x = y[id]
s_y = x[~id]
b_x = y[~id]
b_y
plt.figure()=100, range=xrange)
plt.hist(x, bins=100, range=xrange)
plt.hist(s_x, bins
plt.figure()=100, range=yrange)
plt.hist(y, bins=100, range=yrange); plt.hist(s_y, bins
def gs(m):
return norm.pdf(m, 1, 0.1)
def gb(m):
return expon.pdf(m, 0, 1)
def g(m):
return gs(m) + 10 * gb(m) / 11.
def Gs(m):
return norm.pdf(m, 1.1, 0.2)
def flat(m):
return np.ones_like(m)
def _A(I, S, B, xrange=(-np.inf, np.inf)):
= len(B)
nB = np.empty((1 + nB, 1 + nB))
W = [S] + B
F for i in range(1 + nB):
for j in range(i + 1):
= quad(lambda m: F[i](m) * F[j](m) / I(m), *xrange)[0]
W[i, j] if i != j:
= W[i, j]
W[j, i] return np.linalg.inv(W)
def cow(m, I, S, B, xrange=(-np.inf, np.inf)):
if isinstance(B, Callable):
= [B]
B = _A(I, S, B, xrange=xrange)
a = [S(m)] + [Bi(m) for Bi in B]
F return (a[0] @ F) / I(m)
= cow(x, g, gs, gb, xrange=xrange)
w0 ".", ms=1, mew=0); plt.plot(x, w0,
=w0, density=True, label="estimate")
plt.hist(y, weights=True, edgecolor="r", facecolor="None", label="truth")
plt.hist(s_y, density=f"var(w0) = {np.var(w0):.2f}"); plt.legend(title
= cow(x, g, Gs, gb, xrange=xrange)
w0 ".", ms=1, mew=0); plt.plot(x, w0,
=w0, density=True, label="estimate")
plt.hist(y, weights=True, edgecolor="r", facecolor="None", label="truth")
plt.hist(s_y, density=f"var(w0) = {np.var(w0):.2f}"); plt.legend(title
= cow(x, flat, Gs, gb, xrange=xrange)
w0 ".", ms=1, mew=0); plt.plot(x, w0,
=w0, density=True, label="estimate")
plt.hist(y, weights=True, edgecolor="r", facecolor="None", label="truth")
plt.hist(s_y, density=f"var(w0) = {np.var(w0):.2f}"); plt.legend(title
import numba as nb
class Base:
def __init__(self, n, i, xrange):
self.beta = np.zeros(n)
self.beta[i] = 1
self.xrange = xrange
def __call__(self, m):
return bernstein.density(m, self.beta, *self.xrange)
def make_basis(n, xrange):
return [Base(n, i, xrange) for i in range(n)]
= 7
N = make_basis(N, xrange)
B for Bi in B:
".", ms=1, mew=0)
plt.plot(x, Bi(x),
= cow(x, flat, gs, B, xrange)
w0
plt.figure()".", ms=1, mew=0); plt.plot(x, w0,
=w0, density=True, label="estimate")
plt.hist(y, weights=True, edgecolor="r", facecolor="None", label="truth")
plt.hist(s_y, density=f"var(w0) = {np.var(w0):.2f}"); plt.legend(title