Permalink
Cannot retrieve contributors at this time
Fetching contributors…
| // Accord Statistics Library | |
| // The Accord.NET Framework | |
| // http://accord-framework.net | |
| // | |
| // Copyright © César Souza, 2009-2017 | |
| // cesarsouza at gmail.com | |
| // | |
| // This library is free software; you can redistribute it and/or | |
| // modify it under the terms of the GNU Lesser General Public | |
| // License as published by the Free Software Foundation; either | |
| // version 2.1 of the License, or (at your option) any later version. | |
| // | |
| // This library is distributed in the hope that it will be useful, | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| // Lesser General Public License for more details. | |
| // | |
| // You should have received a copy of the GNU Lesser General Public | |
| // License along with this library; if not, write to the Free Software | |
| // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| // | |
| namespace Accord.Statistics.Distributions.Univariate | |
| { | |
| using System; | |
| using Accord.Statistics.Distributions.Fitting; | |
| using AForge; | |
| using Accord.Math; | |
| /// <summary> | |
| /// Bernoulli probability distribution. | |
| /// </summary> | |
| /// | |
| /// <remarks> | |
| /// <para> | |
| /// The Bernoulli distribution is a distribution for a single | |
| /// binary variable x E {0,1}, representing, for example, the | |
| /// flipping of a coin. It is governed by a single continuous | |
| /// parameter representing the probability of an observation | |
| /// to be equal to 1.</para> | |
| /// | |
| /// <para> | |
| /// References: | |
| /// <list type="bullet"> | |
| /// <item><description><a href="http://en.wikipedia.org/wiki/Bernoulli_distribution"> | |
| /// Wikipedia, The Free Encyclopedia. Bernoulli distribution. Available on: | |
| /// http://en.wikipedia.org/wiki/Bernoulli_distribution </a></description></item> | |
| /// <item><description> | |
| /// C. Bishop. “Pattern Recognition and Machine Learning”. Springer. 2006.</description></item> | |
| /// </list></para> | |
| /// </remarks> | |
| /// | |
| /// <example> | |
| /// <code> | |
| /// // Create a distribution with probability 0.42 | |
| /// var bern = new BernoulliDistribution(mean: 0.42); | |
| /// | |
| /// // Common measures | |
| /// double mean = bern.Mean; // 0.42 | |
| /// double median = bern.Median; // 0.0 | |
| /// double var = bern.Variance; // 0.2436 | |
| /// double mode = bern.Mode; // 0.0 | |
| /// | |
| /// // Probability mass functions | |
| /// double pdf = bern.ProbabilityMassFunction(k: 1); // 0.42 | |
| /// double lpdf = bern.LogProbabilityMassFunction(k: 0); // -0.54472717544167193 | |
| /// | |
| /// // Cumulative distribution functions | |
| /// double cdf = bern.DistributionFunction(k: 0); // 0.58 | |
| /// double ccdf = bern.ComplementaryDistributionFunction(k: 0); // 0.42 | |
| /// | |
| /// // Quantile functions | |
| /// int icdf0 = bern.InverseDistributionFunction(p: 0.57); // 0 | |
| /// int icdf1 = bern.InverseDistributionFunction(p: 0.59); // 1 | |
| /// | |
| /// // Hazard / failure rate functions | |
| /// double hf = bern.HazardFunction(x: 0); // 1.3809523809523814 | |
| /// double chf = bern.CumulativeHazardFunction(x: 0); // 0.86750056770472328 | |
| /// | |
| /// // String representation | |
| /// string str = bern.ToString(CultureInfo.InvariantCulture); // "Bernoulli(x; p = 0.42, q = 0.58)" | |
| /// </code> | |
| /// </example> | |
| /// | |
| /// <seealso cref="BinomialDistribution"/> | |
| /// | |
| [Serializable] | |
| public class BernoulliDistribution : UnivariateDiscreteDistribution, | |
| IFittableDistribution<double, IFittingOptions>, | |
| ISampleableDistribution<int>, IUnivariateDistribution<double>, IUnivariateDistribution | |
| { | |
| // Distribution parameters | |
| private double probability; | |
| // Derived parameter values | |
| private double complement; | |
| // Distribution measures | |
| private double? entropy; | |
| /// <summary> | |
| /// Creates a new <see cref="BernoulliDistribution">Bernoulli</see> distribution. | |
| /// </summary> | |
| /// | |
| public BernoulliDistribution() | |
| : this(0.5) | |
| { | |
| } | |
| /// <summary> | |
| /// Creates a new <see cref="BernoulliDistribution">Bernoulli</see> distribution. | |
| /// </summary> | |
| /// | |
| /// <param name="mean">The probability of an observation being equal to 1. Default is 0.5</param> | |
| /// | |
| public BernoulliDistribution([Unit] double mean) | |
| { | |
| if (mean < 0 || mean > 1) | |
| throw new ArgumentOutOfRangeException("mean", | |
| "Mean should be between zero and one."); | |
| this.initialize(mean); | |
| } | |
| private void initialize(double mean) | |
| { | |
| this.probability = mean; | |
| this.complement = 1.0 - mean; | |
| this.entropy = null; | |
| } | |
| /// <summary> | |
| /// Gets the mean for this distribution. | |
| /// </summary> | |
| /// | |
| public override double Mean | |
| { | |
| get { return probability; } | |
| } | |
| /// <summary> | |
| /// Gets the median for this distribution. | |
| /// </summary> | |
| /// | |
| /// <value> | |
| /// The distribution's median value. | |
| /// </value> | |
| /// | |
| public override double Median | |
| { | |
| get | |
| { | |
| double median; | |
| if (complement > probability) | |
| { | |
| median = 0; | |
| } | |
| else if (complement < probability) | |
| { | |
| median = 1; | |
| } | |
| else | |
| { | |
| median = 0.5; | |
| } | |
| Accord.Diagnostics.Debug.Assert(median == complement || median == base.Median); | |
| return median; | |
| } | |
| } | |
| /// <summary> | |
| /// Gets the mode for this distribution. | |
| /// </summary> | |
| /// | |
| /// <value> | |
| /// The distribution's mode value. | |
| /// </value> | |
| /// | |
| public override double Mode | |
| { | |
| get | |
| { | |
| if (complement > probability) | |
| return 0; | |
| if (complement < probability) | |
| return 1; | |
| return 0; // TODO: should return both 0 and 1 | |
| } | |
| } | |
| /// <summary> | |
| /// Gets the variance for this distribution. | |
| /// </summary> | |
| /// | |
| public override double Variance | |
| { | |
| get { return probability * complement; } | |
| } | |
| /// <summary> | |
| /// Gets the entropy for this distribution. | |
| /// </summary> | |
| /// | |
| public override double Entropy | |
| { | |
| get | |
| { | |
| if (!entropy.HasValue) | |
| { | |
| entropy = -probability * System.Math.Log(probability) - | |
| complement * System.Math.Log(complement); | |
| } | |
| return entropy.Value; | |
| } | |
| } | |
| /// <summary> | |
| /// Gets the support interval for this distribution. | |
| /// </summary> | |
| /// | |
| /// <value> | |
| /// A <see cref="IntRange" /> containing | |
| /// the support interval for this distribution. | |
| /// </value> | |
| /// | |
| public override IntRange Support | |
| { | |
| get { return new IntRange(0, 1); } | |
| } | |
| /// <summary> | |
| /// Gets the cumulative distribution function (cdf) for | |
| /// this distribution evaluated at point <c>k</c>. | |
| /// </summary> | |
| /// | |
| /// <param name="k">A single point in the distribution range.</param> | |
| /// | |
| /// <remarks> | |
| /// The Cumulative Distribution Function (CDF) describes the cumulative | |
| /// probability that a given value or any value smaller than it will occur. | |
| /// </remarks> | |
| /// | |
| protected internal override double InnerDistributionFunction(int k) | |
| { | |
| return complement; | |
| } | |
| /// <summary> | |
| /// Gets the inverse of the cumulative distribution function (icdf) for | |
| /// this distribution evaluated at probability <c>p</c>. This function | |
| /// is also known as the Quantile function. | |
| /// </summary> | |
| /// | |
| /// <param name="p">A probability value between 0 and 1.</param> | |
| /// | |
| /// <returns> | |
| /// A sample which could original the given probability | |
| /// value when applied in the <see cref="UnivariateDiscreteDistribution.DistributionFunction(int)"/>. | |
| /// </returns> | |
| /// | |
| protected override int InnerInverseDistributionFunction(double p) | |
| { | |
| if (p > this.complement) | |
| return 1; | |
| return 0; | |
| } | |
| double IUnivariateDistribution.InverseDistributionFunction(double p) | |
| { | |
| if (p == complement) | |
| return 0.5; | |
| if (p > complement) | |
| return 1.0; | |
| return 0.0; | |
| } | |
| double IUnivariateDistribution<double>.InverseDistributionFunction(double p) | |
| { | |
| if (p == complement) | |
| return 0.5; | |
| if (p > complement) | |
| return 1.0; | |
| return 0.0; | |
| } | |
| /// <summary> | |
| /// Gets P(X > k) the complementary cumulative distribution function | |
| /// (ccdf) for this distribution evaluated at point <c>k</c>. | |
| /// This function is also known as the Survival function. | |
| /// </summary> | |
| /// | |
| /// <param name="k">A single point in the distribution range.</param> | |
| /// | |
| /// <remarks> | |
| /// The Complementary Cumulative Distribution Function (CCDF) is | |
| /// the complement of the Cumulative Distribution Function, or 1 | |
| /// minus the CDF. | |
| /// </remarks> | |
| /// | |
| protected internal override double InnerComplementaryDistributionFunction(int k) | |
| { | |
| return probability; | |
| } | |
| /// <summary> | |
| /// Gets the probability mass function (pmf) for | |
| /// this distribution evaluated at point <c>x</c>. | |
| /// </summary> | |
| /// | |
| /// <param name="k">A single point in the distribution range.</param> | |
| /// | |
| /// <returns> | |
| /// The probability of <c>k</c> occurring | |
| /// in the current distribution. | |
| /// </returns> | |
| /// <remarks> | |
| /// The Probability Mass Function (PMF) describes the | |
| /// probability that a given value <c>k</c> will occur. | |
| /// </remarks> | |
| /// | |
| protected internal override double InnerProbabilityMassFunction(int k) | |
| { | |
| if (k == 1) | |
| return probability; | |
| return complement; | |
| } | |
| /// <summary> | |
| /// Gets the log-probability mass function (pmf) for | |
| /// this distribution evaluated at point <c>x</c>. | |
| /// </summary> | |
| /// | |
| /// <param name="k">A single point in the distribution range.</param> | |
| /// | |
| /// <returns> | |
| /// The logarithm of the probability of <c>k</c> | |
| /// occurring in the current distribution. | |
| /// </returns> | |
| /// | |
| /// <remarks> | |
| /// The Probability Mass Function (PMF) describes the | |
| /// probability that a given value <c>k</c> will occur. | |
| /// </remarks> | |
| /// | |
| protected internal override double InnerLogProbabilityMassFunction(int k) | |
| { | |
| if (k == 1) | |
| return Math.Log(probability); | |
| return Math.Log(complement); | |
| } | |
| /// <summary> | |
| /// Fits the underlying distribution to a given set of observations. | |
| /// </summary> | |
| /// | |
| /// <param name="observations">The array of observations to fit the model against. The array | |
| /// elements can be either of type double (for univariate data) or | |
| /// type double[] (for multivariate data).</param> | |
| /// <param name="weights">The weight vector containing the weight for each of the samples.</param> | |
| /// <param name="options">Optional arguments which may be used during fitting, such | |
| /// as regularization constants and additional parameters.</param> | |
| /// | |
| /// <remarks> | |
| /// Although both double[] and double[][] arrays are supported, | |
| /// providing a double[] for a multivariate distribution or a | |
| /// double[][] for a univariate distribution may have a negative | |
| /// impact in performance. | |
| /// </remarks> | |
| /// | |
| public override void Fit(double[] observations, double[] weights, IFittingOptions options) | |
| { | |
| if (options != null) | |
| throw new ArgumentException("No options may be specified."); | |
| double mean; | |
| if (weights == null) | |
| mean = observations.Mean(); | |
| else | |
| mean = observations.WeightedMean(weights); | |
| initialize(mean); | |
| } | |
| /// <summary> | |
| /// Creates a new object that is a copy of the current instance. | |
| /// </summary> | |
| /// <returns> | |
| /// A new object that is a copy of this instance. | |
| /// </returns> | |
| /// | |
| public override object Clone() | |
| { | |
| return new BernoulliDistribution(probability); | |
| } | |
| #region ISampleableDistribution<int> Members | |
| /// <summary> | |
| /// Generates a random vector of observations from the current distribution. | |
| /// </summary> | |
| /// | |
| /// <param name="samples">The number of samples to generate.</param> | |
| /// <param name="result">The location where to store the samples.</param> | |
| /// <param name="source">The random number generator to use as a source of randomness. | |
| /// Default is to use <see cref="Accord.Math.Random.Generator.Random"/>.</param> | |
| /// | |
| /// <returns>A random vector of observations drawn from this distribution.</returns> | |
| /// | |
| public override int[] Generate(int samples, int[] result, Random source) | |
| { | |
| for (int i = 0; i < samples; i++) | |
| result[i] = source.NextDouble() > this.probability ? 1 : 0; | |
| return result; | |
| } | |
| /// <summary> | |
| /// Generates a random observation from the current distribution. | |
| /// </summary> | |
| /// | |
| /// <param name="source">The random number generator to use as a source of randomness. | |
| /// Default is to use <see cref="Accord.Math.Random.Generator.Random"/>.</param> | |
| /// | |
| /// <returns>A random observations drawn from this distribution.</returns> | |
| /// | |
| public override int Generate(Random source) | |
| { | |
| double u = source.NextDouble(); | |
| return u > this.probability ? 1 : 0; | |
| } | |
| #endregion | |
| /// <summary> | |
| /// Returns a <see cref="System.String"/> that represents this instance. | |
| /// </summary> | |
| /// | |
| /// <returns> | |
| /// A <see cref="System.String"/> that represents this instance. | |
| /// </returns> | |
| /// | |
| public override string ToString(string format, IFormatProvider formatProvider) | |
| { | |
| return String.Format(formatProvider, "Bernoulli(x; p = {0}, q = {1})", | |
| probability.ToString(format, formatProvider), | |
| complement.ToString(format, formatProvider)); | |
| } | |
| } | |
| } |