如何在 Python 中使数据正确符合幂律?

0x9*_*x90 6 python math statistics r power-law

我正在考虑《莫比迪克》小说中独特单词的出现次数,并使用powerlawpython 包将 Words\xe2\x80\x99 频率拟合为幂律。

\n

我不知道为什么我不能重述 Clauset 等人之前工作的结果。因为 p 值和 KS 分数都是“坏”。

\n

这个想法是将独特单词的频率符合幂律。然而,Kolmogorov-Smirnov 测试通过计算得出的拟合优度scipy.stats.kstest看起来很糟糕。

\n

我有以下函数可以使数据符合幂律:

\n
import numpy as np\nimport powerlaw\nimport scipy\nfrom scipy import stats\n\ndef fit_x(x):\n    fit = powerlaw.Fit(x, discrete=True)\n    alpha = fit.power_law.alpha\n    xmin  = fit.power_law.xmin\n    print(\'powerlaw\', scipy.stats.kstest(x, "powerlaw", args=(alpha, xmin), N=len(x)))\n    print(\'lognorm\', scipy.stats.kstest(x, "lognorm", args=(np.mean(x), np.std(x)), N=len(x)))\n
Run Code Online (Sandbox Code Playgroud)\n
\n

下载 Herman Melville 的小说 Moby Dick 中独特单词的频率(根据 Aaron Clauset 等人的说法,应该遵循幂律):

\n
wget http://tuvalu.santafe.edu/~aaronc/powerlaws/data/words.txt\n
Run Code Online (Sandbox Code Playgroud)\n

Python脚本:

\n
x =  np.loadtxt(\'./words.txt\')\nfit_x(x)\n
Run Code Online (Sandbox Code Playgroud)\n

结果:

\n
(\'powerlaw\', KstestResult(statistic=0.862264651286131, pvalue=0.0))\n(\'log norm\', KstestResult(statistic=0.9910368602492707, pvalue=0.0))\n
Run Code Online (Sandbox Code Playgroud)\n
\n

当我比较预期结果并在同一 Moby Dick 数据集上遵循此R 教程时,我得到了不错的 p 值和 KS 测试值:

\n
library("poweRlaw")\ndata("moby", package="poweRlaw")\nm_pl = displ$new(moby)\nest = estimate_xmin(m_pl)\nm_pl$setXmin(est)\nbs_p = bootstrap_p(m_pl)\nbs_p$p\n## [1] 0.6738\n
Run Code Online (Sandbox Code Playgroud)\n
\n

在计算 KS 测试值并通过powerlaw python 库对拟合进行后处理时,我缺少什么?PDF 和 CDF 对我来说看起来不错,但 KS 测试看起来有问题。

\n

在此输入图像描述

\n

0x9*_*x90 0

我仍然不清楚如何通过使用scipy.stats.kstest库来确定重要性和拟合优度powerlaw

不过,powerlaw 实现了自己的distribution_compare功能,返回似然比 R和 的p-val(请参阅此处RAaron Clauset 的一些内容):

R :两个分布与数据拟合的浮点对数似然比。如果大于 0,则首选第一种分布。如果小于 0,则首选第二种分布。

p : float R 的意义

from numpy import genfromtxt
import urllib
import powerlaw

urllib.urlretrieve('https://raw.github.com/jeffalstott/powerlaw/master/manuscript/words.txt', 'words.txt')
words = genfromtxt('words.txt')

fit = powerlaw.Fit(words, discrete=True)

print(fit.distribution_compare('power_law', 'exponential', normalized_ratio=True))
(9.135914718776998, 6.485614241379581e-20)
print(fit.distribution_compare('power_law', 'truncated_power_law'))
(-0.917123083373983, 0.1756268316869548)
print(fit.distribution_compare('power_law', 'truncated_power_law'))
(-0.917123083373983, 0.1756268316869548)
print(fit.distribution_compare('power_law', 'lognormal'))
(0.008785246720842022, 0.9492243713193919)
Run Code Online (Sandbox Code Playgroud)