-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP Mixture Models #1437
WIP Mixture Models #1437
Conversation
Nice, this is a really clear implementation.
I assume you mean for discrete mixtures? If you look at the code, it's mostly about default dtypes: class Discrete(Distribution):
"""Base class for discrete distributions"""
def __init__(self, shape=(), dtype='int64', defaults=['mode'], *args, **kwargs):
super(Discrete, self).__init__(
shape, dtype, defaults=defaults, *args, **kwargs)
class Continuous(Distribution):
"""Base class for continuous distributions"""
def __init__(self, shape=(), dtype='float64', defaults=['median', 'mean', 'mode'], *args, **kwargs):
super(Continuous, self).__init__(
shape, dtype, defaults=defaults, *args, **kwargs) As such, maybe we could inherit from
Can you specify an example case?
Yes, that's the most common reason. If you post an example it would help with testing. |
@twiecki thanks for the feedback. The For broadcasting, the notebook I posted shows two different cases. As the code is now, when the component distributions all have the same type (as in the normal mixture case |
I added a NUTS example to the linked notebook; 6 samples/sec seems quite low from my experience. |
I think this looks good. The NUTS issue I bet is initialization, can you try with ADVI init (https://gist.github.com/jonsedar/cd4985bbfafdba61b3c8d077dd91f237)? In any case, I wouldn't block on the NUTS issue, we can resolve it later. Instead, I would focus on:
|
@twiecki yup, those are my priorities. I would also add random value generation to support posterior predictive sampling to the list of necessary additions. One more question: do we want to replace the current |
Yes, that's probably cleaner. |
I also need to better understand/resolve the issues in #1449 before I can make this code work with dependent weights. |
comp_dists = self.comp_dists | ||
|
||
try: | ||
value_ = value if value.ndim > 1 else value[:, np.newaxis] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should perhaps use tt.shapepadright
instead of np.newaxis
I am not going to port the ZeroInflated* models to be subclasses in this pull request. Due to #1452, we no longer broadcast a certain way in |
That sounds right. Let me know when you want us to take another look. |
@twiecki I think I have gotten this into a pretty good state and would love your feedback on it again. Happy to make any changes you think are necessary to merge. |
_, sd = get_tau_sd(tau=kwargs.pop('tau', None), | ||
sd=kwargs.pop('sd', None)) | ||
|
||
super(NormalMixture, self).__init__(w, Normal.dist(mu, sd=sd), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The simplicity to create a Normal Mixture here is really validating, nicely done.
This is a really high-quality PR, thanks! |
* First pass at mixture modelling * No longer necessary to reference self.comp_dists directly in logp * Add dimension internally (when necessary) * Import get_tau_sd * Misc bugfixes * Add sampling to Mixtures * Differentiate between Discrete and Continuous mixtures when possible * Add support for 2D weights * Gracefully try to calculate mean and mode defaults * Add docstrings for Mixture classes * Export mixture models * Reference self.comp_dists * Remove unnecessary pm. * Add Mixture tests * Add missing imports * Add marginalized Gaussian mixture model example * Calculate the mode of the mixture distribution correctly
Re: #1401
This is my first pass at a flexible mixture model class, and definitely needs a lot of work. As this notebook shows, this code can support two use cases:
comp_dists
is a PyMC3 distribution; that is, each of the mixture components are from the same distributional family, differing only in their parameters (e.g. a mixture of normals)comp_dists
is an iterable of PyMC3 distributions (e.g. a zero inflated Poisson)There are a few issues to address here, that I'd love to get some feedback on:
Discrete
orContinuous
as appropriate, based on the component distributions (it seems like there is some Python metaprogramming magic that should work here, but I am not very well versed in that sort of thing)@twiecki @springcoil @fonnesbeck any feedback/guidance you could give would be much appreciated :)