java - Java中的本福德定律-如何将数学函数转换为Java

标签 java function math syntax benfords-law

我有一个快速的问题。我正在尝试用Java制作欺诈检测应用程序,该应用程序将主要基于本福德定律。本福德定律 super 酷,基本上可以解释为,在实际的金融交易中,第一位数通常是1、2或3,很少是8、9。我无法获得本福德公式转换为可以在Java中运行的代码。

http://www.mathpages.com/home/kmath302/kmath302.htm此链接提供有关什么是本福德法则以及如何使用本法的更多信息。

我知道我将必须使用java math类才能使用自然的日志函数,但是我不确定如何做到这一点。任何帮助将不胜感激。

非常感谢!!

最佳答案

@Rui提到了如何计算概率分布函数,但这对您没有太大帮助。

您要使用的是Kolmogorov-Smirnov testChi-squared test。两者均用于将数据与已知概率分布进行比较,以确定数据集是否可能/不太可能具有该概率分布。

卡方用于离散分布,而K-S用于连续分布。

为了使用符合本福德定律的卡方,您只需创建直方图H [N],例如具有9个bin的N = 1,2,... 9,遍历数据集以检查第一个数字以对9个非零数字(或具有90个bin的前两个数字)中的每个数字计数样本数。然后运行卡方检验以将直方图与预期计数E [N]进行比较。

例如,假设您有100条数据。 E [N]可以根据本福德定律计算得出:

E[1] = 30.1030 (=100*log(1+1))
E[2] = 17.6091 (=100*log(1+1/2))
E[3] = 12.4939 (=100*log(1+1/3))
E[4] =  9.6910
E[5] =  7.9181
E[6] =  6.6946
E[7] =  5.7992
E[8] =  5.1152
E[9] =  4.5757

然后计算Χ2= sum((H [k] -E [k])^ 2/E [k]),并与测试中指定的阈值进行比较。 (这里我们有一个没有参数的固定分布,因此参数s = 0且p = s + 1 = 1的个数,箱数n为9,因此自由度的个数= np = 8 *。然后转到handy-dandy chi-squared table,看看数字是否正确,对于8个自由度,置信度如下所示:

Χ2> 13.362:数据集仍然符合本福德定律的可能性为10%

Χ2> 15.507:数据集仍然符合本福德定律的可能性为5%

Χ2> 17.535:数据集仍然符合本福德定律的可能性为2.5%

Χ2> 20.090:数据集仍然符合本福德定律的几率为1%

Χ2> 26.125:数据集仍然符合本福德定律的可能性为0.1%

假设您的直方图得出X = 0.5585,则H = [29,17,12,10,8,7,6,5,6]。这非常接近预期的分布。 (甚至太近了!)

现在假设您的直方图对于Χ2= 13.89产生H = [27,16,10,9,5,11,6,5,11]。该直方图来自与本福德定律匹配的分布的可能性不到10%。因此,我称数据集有问题,但不是过分。

请注意,您必须选择显着性水平(例如10%/5%/等)。如果使用10%,则可以预期实际上来自Benford分布的每10个数据集中大约有1个失败,即使它们没问题。这是一个判断电话。

看起来Apache Commons Math具有卡方测试的Java实现:

ChiSquareTestImpl.chiSquare(double[] expected, long[] observed)

*注意自由度= 8:这是有道理的;您有9个数字,但它们有1个约束,即它们都必须加起来等于数据集的大小,因此,一旦知道直方图的前8个数字,就可以算出第九个数字。

Kolmogorov-Smirnov实际上更简单(直到我找到了关于其工作原理的足够简单的陈述后,我才意识到这一点),但可以用于连续发行版。该方法的工作方式如下:
  • 您可以为概率分布计算累积分布函数(CDF)。
  • 您可以计算经验累积分布函数(ECDF),可通过将数据集按排序顺序轻松获得。
  • 您会发现D =(大约)两条曲线之间的最大垂直距离。


  • 让我们为本福德定律更深入地处理这些问题。

    本福德定律的
  • CDF:这只是C = log10 x,其中x在[1,10)区间内,即包括1但不包括10。这可以很容易地看到,如果您查看generalized form of Benford's Law,而不是编写它log(1 + 1/n),将其写为log(n + 1)-log(n),换句话说,为了获得每个bin的概率,他们要减去log(n)的连续差,因此log(n)必须是CDF
  • ECDF:取数据集,并将每个数字设为正号,以科学计数法将其写入,然后将指数设置为0。(不确定数字为0时该怎么办;这似乎不适合借用本身,然后按Benford的定律分析。)然后按升序对数字进行排序。 ECDF是任何有效x的数据点数<= x。
  • 计算每个d [k] = max(CDF(y [k])-(k-1)/N,k/N-CDF(y [k])的最大差值D = max(d [k])。

  • 这是一个示例:假设我们的数据集= [3.02,1.99,28.3,47,0.61]。然后,用排序后的数组[1.99,2.83,3.02,4.7,6.1]表示ECDF,并按以下方式计算D:
    D = max(
      log10(1.99) - 0/5, 1/5 - log10(1.99),
      log10(2.83) - 1/5, 2/5 - log10(2.83),
      log10(3.02) - 2/5, 3/5 - log10(3.02),
      log10(4.70) - 3/5, 4/5 - log10(4.70),
      log10(6.10) - 4/5, 5/5 - log10(6.10)
    )
    

    其中= 0.2988(= log10(1.99)-0)。

    最后,您必须使用D统计量-我似乎无法在线找到任何信誉良好的表,但是Apache Commons Math具有KolmogorovSmirnovDistributionImpl.cdf()函数,该函数将计算出的D值作为输入,并告诉您D小于此值的可能性。 。取1-cdf(D)可能更容易,它告诉您D大于或等于您计算出的值的可能性:如果是1%或0.1%,则可能意味着数据不符合本福德定律,但如果是25%或50%,则可能是一个不错的选择。

    关于java - Java中的本福德定律-如何将数学函数转换为Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7815155/

    相关文章:

    java - 与 Java 中 == 的比较

    java - 使用 SearchView 过滤 Recyclerview 后位置错误

    python - 如果数字按降序排列,则返回 true

    java - Class.getClasses() 不适用于从接口(interface)继承的类

    c - dought从c中的函数返回数组和int数据类型

    javascript - 在javascript中将循环函数转换为递归函数

    math - sml 中的 rem 和 mod 函数有什么区别?

    algorithm - 如何将构成凸包的半空间转换为一组极值点?

    algorithm - 给定一个整数,找到给定它的最小函数

    java - Java中如何将数字四舍五入到小数点后n位