【问题标题】:Using Math.NET Numerics is it possible to generate a normally distributed sample with upper and lower bounds?使用 Math.NET Numerics 是否可以生成具有上限和下限的正态分布样本?
【发布时间】:2022-08-10 13:04:43
【问题描述】:

生成具有所需均值和标准分布的正态分布数据非常容易:

IEnumerable<double> sample = MathNet.Numerics.Distributions.Normal.Samples(mean, sd).Take(n);

但是,如果n 的值足够大,您将获得远离平均值的值。为了把它放到上下文中,我有一个带有mean = 15.93sd = 6.84 的真实世界数据集。对于这个数据集,不可能有超过 30 或低于 0 的值,但我看不到为生成的数据添加上限和下限的方法。

我可以删除超出此范围的数据,如下所示,但这会导致生成的样本的平均值和 SD 与我请求的值有显着差异(在我看来,可能不是统计数据)。

Normal.Samples(mean, sd).Where(x => x is >= 0 and <= 30).Take(n);

有什么方法可以确保生成的值在指定范围内而不影响生成数据的均值和标准差?

  • 对不起,但我不认为这就是正态分布的工作原理。
  • 您在寻找Truncated Normal Distribution 吗?
  • @Emond 在现实世界中,您绝对可以拥有具有有限上限/下限的正态分布数据。例如,考试结果将有一个最小值(0 正确)和一个最大值(全部正确)。
  • @KlausGutter 是的,我想我是在截断正态分布之后,谢谢你教我一个新术语!知道您是否可以使用 Math.NET 生成这样的发行版?
  • 我知道这是一个旧线程,但是,如果您有兴趣,我有一些类似的代码可以简化为一个示例来发布。虽然它不是一个截断的正态分布。这就是我所说的离散正态分布.不仅范围设置为指定点,而且整个分布在 x 轴上具有指定数量的离散点,以这些范围限制开始和结束,而不是连续可变的。它非常适合音乐,这是我的应用程序。

标签: c# normal-distribution math.net


【解决方案1】:

免责声明:我不是统计专家,我没有根据截断正态分布的数学定义(例如维基百科中的定义)检查以下建议的解决方案。第一个代码块是截断正态分布类,它封装了 Math.Net 的普通的班级。制作截断正态分布的主要技术是在构造函数中。请注意在样本方法:

using MathNet.Numerics.Distributions;

public class TruncatedNormalDistribution {
    public TruncatedNormalDistribution(double xMin, double xMax) {
      XMin = xMin;
      XMax = xMax;
      double mean = XMin + (XMax - XMin) / 2; // Halfway between minimum and maximum.
      // If the standard deviation is a third of the difference between the mean and
      // the required minimum or maximum of a normal distribution, 99.7% of samples should
      // be in the required range.
      double standardDeviation = (mean - XMin) / 3;
      Distribution = new Normal(mean, standardDeviation);
    }

    private Normal Distribution { get; }
    private double XMin { get; }
    private double XMax { get; }

    public double CumulativeDistribution(double x) {
        return Distribution.CumulativeDistribution(x);
    }

    public double Density(double x) {
        return Distribution.Density(x);
    }

    public double Sample() {
        return Math.Clamp(Distribution.Sample(), XMin, XMax);
    }
}

这是一个使用示例。要直观地表示结果,请在电子表格(如 Excel)中打开两个输出 CSV 文件,并将其数据映射到折线图:

// Put the path of the folder where the CSVs will be saved here
const string chartFolderPath =
   @"C:\Insert\chart\folder\path\here";
const double xMin = 0;
const double xMax = 100;
var distribution = new TruncatedNormalDistribution(xMin, xMax);
// Densities
var dictionary = new Dictionary<double, double>();
for (double x = xMin; x <= xMax; x += 1) {
    dictionary.Add(x, distribution.Density(x));
}
string csvPath = Path.Combine(
    chartFolderPath, 
    $"Truncated Normal Densities, Range {xMin} to {xMax}.csv");
using var writer = new StreamWriter(csvPath);
foreach ((double key, double value) in dictionary) {
    writer.WriteLine($"{key},{value}");
}
// Cumulative Distributions
dictionary.Clear();
for (double x = xMin; x <= xMax; x += 1) {
    dictionary.Add(x, distribution.CumulativeDistribution(x));
}
csvPath = Path.Combine(
    chartFolderPath, 
    $"Truncated Normal Cumulative Distributions, Range {xMin} to {xMax}.csv");
using var writer2 = new StreamWriter(csvPath);
foreach ((double key, double value) in dictionary) {
    writer2.WriteLine($"{key},{value}");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多