몇 가지 쿼리 빈도가 있으며 Zipf의 법칙 계수를 추정해야합니다. 이들은 최고 주파수입니다 :
26486
12053
5052
3033
2536
2391
1444
1220
1152
1039
몇 가지 쿼리 빈도가 있으며 Zipf의 법칙 계수를 추정해야합니다. 이들은 최고 주파수입니다 :
26486
12053
5052
3033
2536
2391
1444
1220
1152
1039
답변:
업데이트 @ whuber 제안에 따라 최대 가능성 추정기로 코드를 업데이트했습니다. 대수 이론적 확률과 대수 빈도 사이의 차이의 제곱의 합을 최소화하는 것이 일종의 M- 추정 자임을 보여줄 수 있다면 통계적 절차가 될 것입니다. 불행히도 나는 동일한 결과를 줄 수있는 것을 생각할 수 없었습니다.
여기 내 시도가 있습니다. 주파수의 로그를 계산 하고이 공식에 의해 주어진 이론적 확률의 로그에 맞추려고합니다 . 최종 결과는 합리적입니다. 다음은 R 코드입니다.
fr <- c(26486, 12053, 5052, 3033, 2536, 2391, 1444, 1220, 1152, 1039)
p <- fr/sum(fr)
lzipf <- function(s,N) -s*log(1:N)-log(sum(1/(1:N)^s))
opt.f <- function(s) sum((log(p)-lzipf(s,length(p)))^2)
opt <- optimize(opt.f,c(0.5,10))
> opt
$minimum
[1] 1.463946
$objective
[1] 0.1346248
그러면 최적의 2 차 는 입니다.
R의 최대 우도는 mle
함수를 사용 하여 수행 할 수 있으며 ( stats4
패키지에서) 표준 오류를 계산하는 데 도움이됩니다 (정확한 음의 최대 우도 함수가 제공되는 경우).
ll <- function(s) sum(fr*(s*log(1:10)+log(sum(1/(1:10)^s))))
fit <- mle(ll,start=list(s=1))
> summary(fit)
Maximum likelihood estimation
Call:
mle(minuslogl = ll, start = list(s = 1))
Coefficients:
Estimate Std. Error
s 1.451385 0.005715046
-2 log L: 188093.4
다음은 로그 로그 스케일에 맞는 그래프입니다 (@whuber가 제안한 것처럼).
s.sq <- opt$minimum
s.ll <- coef(fit)
plot(1:10,p,log="xy")
lines(1:10,exp(lzipf(s.sq,10)),col=2)
lines(1:10,exp(lzipf(s.ll,10)),col=3)
빨간색 선은 제곱합의 합이고 녹색 선은 최대 가능성에 맞습니다.
에서 우리 앞에 몇 가지 문제가 있습니다 어떤 추정 문제는 :
모수를 추정하십시오.
해당 추정치의 품질을 평가하십시오.
데이터를 탐색하십시오.
적합을 평가하십시오.
이해와 의사 소통을 위해 통계적 방법을 사용 하려는 사람들은 다른 사람들 없이는 먼저 수행해서는 안됩니다.
대한 추정 은 사용에 편리 maximimum 우도 (ML). 주파수가 너무 커서 잘 알려진 점근 적 특성이 유지 될 것으로 예상 할 수 있습니다. ML은 추정 된 확률 분포 데이터를 사용합니다. Zipf의 법칙 은 의 확률이 일정한 전력 (보통 )에 대해 에 비례한다고 가정합니다 . 이러한 확률은 단일성을 합산해야하기 때문에 비례 상수는 합의 역수입니다.i - s s s > 0
따라서, 모든 결과에 대한 확률의 대수 간의 및 이고1 N
빈도 요약 된 독립 데이터의 경우 확률은 개별 확률의 곱입니다.
따라서 데이터의 로그 확률은
데이터를 고정 된 것으로 간주하고 이를 의 함수로 명시 적으로 표현 하면 로그 가능성이 됩니다.
로그의 수치 최소화 질문에 제공된 데이터의 가능성은 및 입니다. 이것은 훨씬 더 (그러나 겨우 정도)의 (로그 주파수 기준) 최소 제곱 솔루션보다 로 . ( mpiktas에서 제공 하는 우아하고 명확한 R 코드 를 약간 변경하여 최적화를 수행 할 수 있습니다 .)
ML은 또한 일반적인 방법으로 에 대한 신뢰 한계 를 추정 합니다. 카이 제곱 근사는 (계산을 올바르게 수행 한 경우 :-).
Zipf의 법칙의 특성을 고려할 때, 이 피팅을 그래프로 그리는 올바른 방법은 로그-로그 플롯 에 있습니다.
적합도를 평가하고 데이터를 탐색 하려면 잔차 (데이터 / 적합, 로그-로그 축을 다시 확인)를 확인하십시오.
이는 그리 크지 않습니다. 잔차에 명백한 일련의 상관 관계 나 이분산성은 없지만 일반적으로 약 10 % (1.0에서 멀어짐)입니다. 주파수가 수천 개이면 편차가 몇 퍼센트 이상 예상되지 않습니다. 적합도는 쉽게 테스트를 거쳤 카이 제곱 . 우리는 = 9 자유 도로 을 얻는다 ; 이것은 Zipf의 법칙에서 출발했다는 매우 중요한 증거입니다 .
잔차가 무작위로 표시되기 때문에 일부 응용 프로그램 에서는 주파수에 대한 대략적인 설명이지만 Zipf의 법칙 (및 매개 변수의 추정치)을 수용 가능한 것으로 받아 들일 수 있습니다 . 그러나이 분석은이 추정치가 여기에서 조사 된 데이터 세트에 대한 설명 적 또는 예측 적 가치를 가졌다 고 가정하는 것이 실수라는 것을 보여줍니다.
최대 우도 추정치는 모수 점 추정치입니다 . 추정치의 신뢰 구간도 찾으려면 추가 노력이 필요합니다. 문제는이 간격이 확률 적이 지 않다는 것입니다. "파라미터 값 s = ...는 [...] 범위에서 확률이 95 %입니다"라고 말할 수 없습니다.
PyMC3 과 같은 확률 적 프로그래밍 언어 중 하나는 이 추정을 비교적 간단하게 만듭니다. 다른 언어에는 훌륭한 기능과 지원 커뮤니티를 가진 Stan 이 포함됩니다 .
다음은 OP 데이터에 맞는 모델의 Python 구현입니다 ( Github 에도 있음 ).
import theano.tensor as tt
import numpy as np
import pymc3 as pm
import matplotlib.pyplot as plt
data = np.array( [26486, 12053, 5052, 3033, 2536, 2391, 1444, 1220, 1152, 1039] )
N = len( data )
print( "Number of data points: %d" % N )
def build_model():
with pm.Model() as model:
# unsure about the prior...
#s = pm.Normal( 's', mu=0.0, sd=100 )
#s = pm.HalfNormal( 's', sd=10 )
s = pm.Gamma('s', alpha=1, beta=10)
def logp( f ):
r = tt.arange( 1, N+1 )
return -s * tt.sum( f * tt.log(r) ) - tt.sum( f ) * tt.log( tt.sum(tt.power(1.0/r,s)) )
pm.DensityDist( 'obs', logp=logp, observed={'f': data} )
return model
def run( n_samples=10000 ):
model = build_model()
with model:
start = pm.find_MAP()
step = pm.NUTS( scaling=start )
trace = pm.sample( n_samples, step=step, start=start )
pm.summary( trace )
pm.traceplot( trace )
pm.plot_posterior( trace, kde_plot=True )
plt.show()
if __name__ == '__main__':
run()
다음은 매개 변수의 추정치 분포 형태는. 추정치가 얼마나 간결한 지 확인하십시오! 확률이 95 % 일 때 모수 의 실제 값은 [1.439,1.461] 범위입니다. 평균은 약 1.45이며 MLE 추정치에 매우 가깝습니다.
몇 가지 기본적인 샘플링 진단을 제공하기 위해 추적에서 구조가 보이지 않기 때문에 샘플링이 "혼합 중"임을 알 수 있습니다.
코드를 실행하려면 Theano 및 PyMC3 패키지가 설치된 Python이 필요합니다.
훌륭한 답변과 의견을 보내 주신 @ w-huber에게 감사드립니다!
다음은 데이터를 맞추고 VGAM을 사용하여 결과를 평가하고 탐색하려는 시도입니다.
require("VGAM")
freq <- dzipf(1:100, N = 100, s = 1)*1000 #randomizing values
freq <- freq + abs(rnorm(n=1,m=0, sd=100)) #adding noize
zdata <- data.frame(y = rank(-freq, ties.method = "first") , ofreq = freq)
fit = vglm(y ~ 1, zipf, zdata, trace = TRUE,weight = ofreq,crit = "coef")
summary(fit)
s <- (shat <- Coef(fit)) # the coefficient we've found
probs <- dzipf(zdata$y, N = length(freq), s = s) # expected values
chisq.test(zdata$ofreq, p = probs)
plot(zdata$y,(zdata$ofreq),log="xy") #log log graph
lines(zdata$y, (probs)*sum(zdata$ofreq), col="red") # red line, num of predicted frequency
Chi-squared test for given probabilities
data: zdata$ofreq
X-squared = 99.756, df = 99, p-value = 0.4598
우리의 경우 Chi square의 귀무 가설은 데이터가 zipf의 법칙에 따라 분포된다는 것이므로 p- 값이 클수록 데이터가 그것에 따라 분포된다는 주장을 뒷받침합니다. 매우 큰 p- 값조차도 증거가 아니라 지표 일뿐입니다.
재미를 위해서 이것은 UWSE가 최고 비용만을 사용하여 폐쇄 형 솔루션을 제공 할 수있는 또 다른 사례입니다. 의 확률 은 모수 값에서 고유합니다. 경우 다음, 대응하는 상대를 나타낸다
이 경우 과 같이됩니다.
다시 말하지만 UWSE는 일관된 추정치 만 제공하며 신뢰 구간은 없으며 정확성의 일부 상충 관계를 볼 수 있습니다. 위의 mpiktas 솔루션은 프로그래밍이 필요하지만 UWSE의 응용 프로그램입니다. 견적에 대한 자세한 설명은 https://paradsp.wordpress.com/을 참조하십시오 .
내 솔루션은 mpiktas 및 whuber가 Python에서 구현하는 답변을 보완하려고합니다. 우리의 주파수와 범위 x는 :
freqs = np.asarray([26486, 12053, 5052, 3033, 2536, 2391, 1444, 1220, 1152, 1039])
x = np.asarray([1, 2, 3, 4, 5 ,6 ,7 ,8 ,9, 10])
함수가 모든 범위에 정의되어 있지 않으므로 계산할 때마다 정규화되고 있는지 확인해야합니다. 이산 형의 경우 간단한 근사값은 모든 y (x)의 합으로 나눕니다. 이런 식으로 우리는 다른 매개 변수를 비교할 수 있습니다.
f,ax = plt.subplots()
ax.plot(x, f1, 'o')
ax.set_xscale("log")
ax.set_yscale("log")
def loglik(b):
# Power law function
Probabilities = x**(-b)
# Normalized
Probabilities = Probabilities/Probabilities.sum()
# Log Likelihoood
Lvector = np.log(Probabilities)
# Multiply the vector by frequencies
Lvector = np.log(Probabilities) * freqs
# LL is the sum
L = Lvector.sum()
# We want to maximize LogLikelihood or minimize (-1)*LogLikelihood
return(-L)
s_best = minimize(loglik, [2])
print(s_best)
ax.plot(x, freqs[0]*x**-s_best.x)
결과는 이전 답변에서와 같이 1.450408 의 기울기를 제공 합니다.