How is the mode point estimate calculated by the `plot_posterior` method?

When plotting the posterior from the trace, you can choose the point_estimate='mode'. I also need the value of a mode as a separate statistic, which is unfortunately not incorporated into default statistics of stats.summary() method. So, I pass in the stats_funcs parameter a wrapper for scipy.stats.mode (because by default scipy.stats.mode returns additionally number of bins, which has to be disposed). Now, if I compare what value plot_posterior(point_estimate='mode') is showing and the value scipy.stats.mode is returning, these are two super different in my case. E.g. I get 7.339 for plot_posterior() and scipy.stats.mode() method returns 29.097, which is more plausible value.
Now, question is: how is mode calculated by the plot_posterior method, where this discrepancy from scipy implementation can come from and what I should rely on?

To add, I now have checked, scipy.stats.mode is making its calculations based on only 30 bins binning, which is super law value for a range of values my posterior is spanning over. Still it would be interesting to know how mode is calculated inside the PyMC3, how reliable it is and how to calculate it with the tools of PyMC3, rather than third-party libs, which results in such discrepancies.

PyMC3 use Arviz which for continuous value use a kde function to smooth out the histogram and get the local maximum:

It might not work well if you have multi mode but otherwise we think it is quite good in most case


Thank you, Junpeng, for such a fast response. Now it have become even more weird, bacause calling az.plots.plot_utils.calculate_point_estimate('mode', trace['tau'], bw=4.5) results into array([29.09679086]) – super close to the value returned by the scipy.stats.mode. Yet, plot_posterior shows 7.339. The only parameter which could have effect (bw parameter) does not really have effect. So I am now wondering what could be the reason plot_posterior is showing such a value of mode.

More info: when calculated through passing the stats_funcs parameter of the az.stats.summary(), it results in the same value of 7.339, so something happens to the trace on the way, which is not done when calling az.plots.plot_utils.calculate_point_estimate('mode', trace['tau'], bw=4.5) directly.

hmmm sounds like a bug - could you raise an issue on Arviz?

1 Like

Thank you, I will!

1 Like