# Wrapper for pomegranate.GeneralMixtureModel
import sys
import numpy as np
from pomegranate import GeneralMixtureModel as GMM
import chippr
from chippr import defaults as d
from chippr import utils as u
[docs]class gmix(object):
def __init__(self, amps, funcs, limits=(d.min_x, d.max_x)):
"""
Object to define a mixture probability distribution
Parameters
----------
amps: ndarray, float
array with one relative amplitude per component
funcs: list, chippr.gauss or chippr.discrete objects
list of components
limits: tuple or list or numpy.ndarray, float, optional
minimum and maximum sample values to return
"""
self.amps = amps/np.sum(amps)
self.cumamps = np.cumsum(self.amps)
self.n_comps = len(self.amps)
self.funcs = funcs#[chippr.gauss(self.means[c], self.sigmas[c]**2) for c in range(self.n_comps)]
# print('gmix before:')
# for c in range(self.n_comps):
# print('gmix '+str((c, type(self.funcs[c]))))
self.funcs = [func.dist for func in self.funcs]
# print('gmix after:')
# for c in range(self.n_comps):
# print('gmix '+str((c, type(self.funcs[c]))))
self.dims = np.shape(np.array(limits).T)[0]
self.min_x = limits[0]
self.max_x = limits[1]
# print("amps="+str(self.amps))
self.dist = GMM(self.funcs, weights=self.amps)
[docs] def pdf(self, xs):
return self.evaluate(xs)
[docs] def evaluate_one(self, x):
"""
Function to evaluate Gaussian mixture
once
Parameters
----------
x: float
value at which to evaluate Gaussian mixture
Returns
-------
p: float
probability associated with x
"""
# p = 0.
# for c in range(self.n_comps):
# p += self.amps[c] * self.funcs[c].evaluate_one(x)
p = self.dist.probability(x)
return p
[docs] def evaluate(self, xs):
"""
Function to evaluate the Gaussian mixture probability distribution at many points
Parameters
----------
xs: ndarray, float
values at which to evaluate Gaussian mixture probability distribution
Returns
-------
ps: ndarray, float
values of Gaussian mixture probability distribution at xs
"""
# ps = np.zeros(len(xs))
# for c in range(self.n_comps):
# ps += self.amps[c] * self.funcs[c].evaluate(xs)
ps = self.dist.probability(xs)
return ps
[docs] def sample_one(self):
"""
Function to sample a single value from Gaussian mixture probability distribution
Returns
-------
x: float
a single point sampled from the Gaussian mixture probability distribution
"""
# x = -1. * np.ones(self.dims)
# #don't do this every time!
# min_x = self.min_x * np.ones(self.dims)
# max_x = self.max_x * np.ones(self.dims)
#
# while np.any(np.less(x, min_x)) or np.any(np.greater(x, max_x)):
# r = np.random.uniform(0., self.cumamps[-1])
# c = 0
# for k in range(1, self.n_comps):
# if r > self.cumamps[k-1]:
# c = k
# x = self.funcs[c].sample_one()
x = self.dist.sample(1)
return x
[docs] def sample(self, n_samps):
"""
Function to take samples from Gaussian mixture probability distribution
Parameters
----------
n_samps: int
number of samples to take
Returns
-------
xs: ndarray, float
array of points sampled from the Gaussian mixture probability distribution
"""
# print('gmix trying to sample '+str(n_samps)+' from '+str(self.dist))
# xs = np.array([self.sample_one() for n in range(n_samps)])
# print(self.dist.to_json)
xs = np.array(self.dist.sample(n_samps))
# print('gmix sampled '+str(n_samps)+' from '+str(self.dist))
return xs