-
Notifications
You must be signed in to change notification settings - Fork 85
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
[Request] Alternative parameterization for negative binomial distributions? #198
Comments
I expect that you'd want this at initialization, but I don't have the background to know when else a different parametrization would be useful. Can you help me understand such a scenario? |
Thank you for getting back to me! Here's a quick summary of what parameterizations we are discussing: the current parameterization of negative binomial distribution as implemented uses The mean-and-dispersion is more widely used in regression analysis, because the explanatory variables can be linked to the mean, similar to linear regression. This is also, in my opinion, more intuitive when it comes to interpreting the effects of explanatory variables on the negative binomial counts. (Personally, I don't think I have seen negative binomial regression done with the The parameters, or statistics like means and variances, can be derived using the current parameterization. In my own codes, I just wrote a separate |
This "Alternative Parameterization" usually called the "Method of moments estimator". This parameterization exists for many distributions, so in my opinion it is rather a trait. |
Hmm, were it a trait, how would you define that, i.e. what methods and generics would go with it? |
I don't really think such a feature is one of the highest priorities, in any case I think the implementation should look like the following: trait StandardizedMoments {
fn mean(&self) -> Option<f64>;
fn variance(&self) -> Option<f64>;
fn skewness(&self) -> Option<f64>;
fn kurtosis(&self) -> Option<f64>;
}
trait MethodOfMomentsEstimator {
fn from_moments<M: StandardizedMoments>(moments: M) -> Result<Self>;
} Skewness & kurtosis here as negative binomial distribution (not only this distribution) can be fitted not only to fist 2 moments, but to first 4 moments. There are multiple ways how to fit data to distributions. |
I see this as a way to refer to distributions or estimators with constraints by their moments instead of other parameters. I was expecting something narrower, things that would specify distributions given family and number of moments that fully specify the parametrization of the distribution. I see usefulness in thinking about moments by specifying mean [and variance [and skew...]] , (notation is bash-style optionals) but I think these are little far off from where the crate is now
Not opposed to them, but think they would take a significant amount of work. @diaorch how close is this to what you were wanting? |
The discussion brings up several good points. Firstly, I agree that it's likely not of the highest priority for the crate right now. Secondly, I wasn't considering generalizing to the Method of Moments Estimator, but I agree that if we are going with the Method of Moments Estimator in general, a trait would be a better choice than, say, a method specific to a distribution Hope this is still helpful. |
@YeungOnion I don't have ready to implement API design. Maybe instead of trait it could be a builder pattern... this way set of parameters can be effectively constrained if, for instance, set of variance will return an "extended" builder. As an additional example – Gamma distribution can be parametrized by:
|
@diaorch that's alright by me, but I think as a user you have some great input for how you'd like it to work as a library despite implementation. Could you share what the struct you wrapped the negative binomial distribution in? |
@tessob yeah, I think it will take some digging, perhaps as its own feature request. I also think a builder pattern would work well, as it seems like there are a few things that can come out depending on what info is specified, assuming all have specified the family of distribution,
Thoughts? |
@YeungOnion hey sorry for the very late reply and thank you for the appreciation for input from a user like me. Here are the codes I used as a wrapper to use the alternative parameterization for its probability mass function. Some of the ideas are taken from R source codes. Hope they are useful for showing what I was describing as the alternative parameterization and how I was using it.
Let me know if there is anything else I can do to help and I will do my best to be less than months late this time. :) |
One idea on how to implement this pattern would be with generics. struct NegativeBinomial {
r: f64,
p: f64,
} We could move the parametrization out into a wrapper struct: struct NegativeBinomial<P> {
param: P
}
// naming TBD
struct SuccessProbability {
r: f64,
p: f64,
}
struct MeanVariance {
m: f64, // μ
v: f64, // σ²
}
impl NegativeBinomial<SuccessProbability> {
pub fn new_success_probability(r: f64, p: f64) -> Result<Self, Error>;
pub const fn p(&self) -> f64 { self.param.p }
pub const fn r(&self) -> f64 { self.param.r }
// maybe return Result, if conversion can fail
pub fn into_mean_variance(self) -> NegativeBinomial<MeanVariance>;
}
impl NegativeBinomial<MeanVariance> {
pub fn new_mean_variance(m: f64, v: f64) -> Result<Self, Error>;
pub const fn m(&self) -> f64 { self.param.m }
pub const fn v(&self) -> f64 { self.param.v }
pub fn into_success_probability(self) -> NegativeBinomial<SuccessProbability>;
}
impl DiscreteCDF<u64, f64> for NegativeBinomial<SuccessProbability> {
// implement functions for r, p
}
impl DiscreteCDF<u64, f64> for NegativeBinomial<MeanVariance> {
// implement functions for m, v
}
// etc. This would mean that we need to implement traits for both Anyways, from a user's point of view this should mean that when you type The documentation would need to explain this well. And it would add a generic parameter to the type, which makes things more complicated (often you don't need to explicitly type your variables, this is Rust after all, but for beginners it can get confusing).
I think a builder would be great for this. You should even be able to handle different types. pub struct GammaBuilder<P> {
p: P
}
impl<P> GammaBuilder<P> {
pub fn new(mean: f64) -> GammaBuilder<ExpBuilderParams> {
GammaBuilder {
p: ExpBuilderParams { mean }
}
}
}
impl GammaBuilder<ExpBuilderParams> {
pub fn variance(self, variance: f64) -> GammaBuilder<GammaBuilderParams> {
GammaBuilder {
GammaBuilderParams {
mean: self.mean,
variance,
}
}
}
pub fn build(self) -> Exp {
// ...
}
}
impl GammaBuilder<GammaBuilderParams> {
pub fn build(self) -> Gamma {
// ...
}
}
struct ExpBuilderParams {
mean: f64
}
struct GammaBuilderParams {
mean: f64,
variance: f64,
} Needs a bit of polish and I can't sketch an API for the Footnotes
|
I think supporting construction by specifying moments would be useful and as general fitting/optimizing of distribution functions should be a feature of I also think the builder is a good choice. It even extends well for fitting to data. I've got other thoughts, but while writing it I realized we haven't defined if this project aims to be more for those writing single analyses or more as a library for applications / other library-like crates. The notion of a Gamma distribution shouldn't rely on its parametrization, but numerically speaking a caller could opt into tradeoffs by choosing a parametrization that's closer to their use case. C.f. when running your own potentially exploratory analysis, you might just expect numerical stability across parameters, so we would runtime select from suite of methods to account for broad parameter ranges. |
Currently, the
struct NegativeBinomial
uses the parametersr
andp
, as in the interpretation of negative binomial distribution as the distribution of the number of failures in a sequence of Bernoulli trials with probability of successp
that continue untilr
successes occur.Another way to describe a negative binomial distribution is through the mean and the size/dispersion parameters. This is worth implementing especially given that a lot of the statistical questions center around the mean of the distribution.
r
andp
can be calculated from the mean and the dispersion parameter.Perhaps the alternative parameterization of negative binomial distributions can be a useful addition to the crate's functionality?
The text was updated successfully, but these errors were encountered: