최고 주파수 세트에서 Zipf의 법칙 계수를 계산하는 방법은 무엇입니까?


25

몇 가지 쿼리 빈도가 있으며 Zipf의 법칙 계수를 추정해야합니다. 이들은 최고 주파수입니다 :

26486
12053
5052
3033
2536
2391
1444
1220
1152
1039

Wikipedia 페이지 에 따르면 Zipf의 법칙에는 두 가지 매개 변수가 있습니다. 요소 수 과 지수. 귀하의 경우 은 무엇입니까 , 10? 제공된 값을 제공된 모든 값의 합계로 나누어 주파수를 계산할 수 있습니까? NNsN
mpiktas

10으로 설정하고 제공된 값을 제공된 모든 값의 합계로 나누어 주파수를 계산할 수 있습니다. 어떻게 추정 할 수 있습니까?
Diegolo

답변:


22

업데이트 @ 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 차 는 입니다.s=1.47

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)

빨간색 선은 제곱합의 합이고 녹색 선은 최대 가능성에 맞습니다.

적합치의 로그-로그 그래프


1
R 패키지 zipfR cran.r-project.org/web/packages/zipfR/index.html도 있지만 아직 시도하지 않았습니다.
onestop

@onestop, 링크 주셔서 감사합니다. 누군가이 패키지를 사용 하여이 질문에 대답하면 좋을 것입니다. 내 솔루션에는 깊이가 부족하지만 어떤 종류의 답변을 제공합니다.
mpiktas

(+1) 당신은 정말 인상적입니다. 다양한 통계 분야에서 많은 기여를했습니다!
chl

@chl, 감사합니다! 나는 확실히이 사이트에서 그런 특성을 가진 유일한 사람은 아니라고 생각한다;)
mpiktas

25

에서 우리 앞에 몇 가지 문제가 있습니다 어떤 추정 문제는 :

  1. 모수를 추정하십시오.

  2. 해당 추정치의 품질을 평가하십시오.

  3. 데이터를 탐색하십시오.

  4. 적합을 평가하십시오.

이해와 의사 소통을 위해 통계적 방법을 사용 하려는 사람들은 다른 사람들 없이는 먼저 수행해서는 안됩니다.

대한 추정 은 사용에 편리 maximimum 우도 (ML). 주파수가 너무 커서 잘 알려진 점근 적 특성이 유지 될 것으로 예상 할 수 있습니다. ML은 추정 된 확률 분포 데이터를 사용합니다. Zipf의 법칙 은 의 확률이 일정한 전력 (보통 )에 대해 에 비례한다고 가정합니다 . 이러한 확률은 단일성을 합산해야하기 때문에 비례 상수는 합의 역수입니다.i - s s s > 0i=1,2,,nisss>0

Hs(n)=11s+12s++1ns.

따라서, 모든 결과에 대한 확률의 대수 간의 및 이고1 Ni1n

log(Pr(i))=log(isHs(n))=slog(i)log(Hs(n)).

빈도 요약 된 독립 데이터의 경우 확률은 개별 확률의 곱입니다.fi,i=1,2,,n

Pr(f1,f2,,fn)=Pr(1)f1Pr(2)f2Pr(n)fn.

따라서 데이터의 로그 확률은

Λ(s)=si=1nfilog(i)(i=1nfi)log(Hs(n)).

데이터를 고정 된 것으로 간주하고 이를 의 함수로 명시 적으로 표현 하면 로그 가능성이 됩니다.s

로그의 수치 최소화 질문에 제공된 데이터의 가능성은 및 입니다. 이것은 훨씬 더 (그러나 겨우 정도)의 (로그 주파수 기준) 최소 제곱 솔루션보다 로 . ( mpiktas에서 제공 하는 우아하고 명확한 R 코드 를 약간 변경하여 최적화를 수행 할 수 있습니다 .)s^=1.45041Λ(s^)=94046.7s^ls=1.463946Λ(s^ls)=94049.5

ML은 또한 일반적인 방법으로 에 대한 신뢰 한계 를 추정 합니다. 카이 제곱 근사는 (계산을 올바르게 수행 한 경우 :-).s[1.43922,1.46162]

Zipf의 법칙의 특성을 고려할 때, 이 피팅을 그래프로 그리는 올바른 방법은 로그-로그 플롯 에 있습니다.

여기에 이미지 설명을 입력하십시오

적합도를 평가하고 데이터를 탐색 하려면 잔차 (데이터 / 적합, 로그-로그 축을 다시 확인)를 확인하십시오.

여기에 이미지 설명을 입력하십시오

이는 그리 크지 않습니다. 잔차에 명백한 일련의 상관 관계 나 이분산성은 없지만 일반적으로 약 10 % (1.0에서 멀어짐)입니다. 주파수가 수천 개이면 편차가 몇 퍼센트 이상 예상되지 않습니다. 적합도는 쉽게 테스트를 거쳤 카이 제곱 . 우리는 = 9 자유 도로 을 얻는다 ; 이것은 Zipf의 법칙에서 출발했다는 매우 중요한 증거입니다 .χ2=656.476


잔차가 무작위로 표시되기 때문에 일부 응용 프로그램 에서는 주파수에 대한 대략적인 설명이지만 Zipf의 법칙 (및 매개 변수의 추정치)을 수용 가능한 것으로 받아 들일 수 있습니다 . 그러나이 분석은이 추정치가 여기에서 조사 된 데이터 세트에 대한 설명 적 또는 예측 적 가치를 가졌다 고 가정하는 것이 실수라는 것을 보여줍니다.


1
@ whuber, 위의 공식에 약간의주의를 기울일 수 있습니다. Zipf의 법칙은 일반적으로 상대 주파수 결과로 표시됩니다. iid 샘플이 추출되는 분포는 일반적으로 고려되지 않습니다. iid 프레임 워크는 아마도 이러한 데이터에 대한 최상의 아이디어는 아닙니다. 아마도 이것에 대해서는 나중에 더 게시 할 것입니다.
추기경

3
@cardinal 나는 당신이 할 말을 기대합니다. 철저한 응답을 할 시간이 없다면 "이러한 데이터에 가장 적합한 아이디어"라고 생각하는 것의 스케치조차 가장 환영받을 것입니다. 나는 당신이 어디로 가고 있는지 추측 할 수 있습니다 : 데이터의 순위가 매겨졌으며, 의존성을 만드는 과정으로 순위의 잠재적 영향을 인식하지 않고 도출 된 가능성을 방어해야합니다. 더 정당화되는 추정 절차를 보는 ​​것이 좋을 것입니다. 그러나 데이터 세트의 크기에 따라 분석을 구할 수 있기를 바랍니다.
whuber

1
@cardinal, Fermat하지 말아주세요 :) 만약 당신이 다른 응답자와 다른 통찰력을 가지고 있다면, 그것은 그 자체로 유효한 답을 구성하지 않더라도 별도의 대답으로 자유롭게 표현하십시오. 예를 들어 math.SE 에서는 이러한 상황이 자주 발생합니다.
mpiktas

1
@ 카디널 쉽게. 예를 들어, 빈도를 수집하고 10 개 최고를 식별하고 순위를 매 깁니다. 당신은 Zipf의 법칙을 가정합니다. 새 빈도 세트를 수집하여 이전 순위 에 따라보고합니다 . 즉, IID 내 분석이 완벽하게 적합되는 상황,의 우발 옛 사람과 동의 새로운 계급에 따라 있습니다.
whuber

1
@ whuber, 양해 해 주셔서 감사합니다. 이제 나는 당신의 추론에 대해 완전히 명확합니다. 샘플링 모델에서 이제 완벽하게 다듬 었습니다. 귀하의 분석에 동의합니다. 아마도 당신의 마지막 진술은 여전히 ​​약간 미끄 럽습니다. 정렬이 방법보다 강한 의존성을 유도하지 않으면 보수적입니다. 유도 된 의존성이 적당히 강하면, 그것은 보수적이지 않을 수 있습니다. 내 pedantry 앞에서 인내심을 가져 주셔서 감사합니다.
추기경

2

최대 우도 추정치는 모수 점 추정치입니다 . 추정치의 신뢰 구간도 찾으려면 추가 노력이 필요합니다. 문제는이 간격이 확률 적이 지 않다는 것입니다. "파라미터 값 s = ...는 [...] 범위에서 확률이 95 %입니다"라고 말할 수 없습니다.s

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 추정치에 매우 가깝습니다.ss

여기에 이미지 설명을 입력하십시오

몇 가지 기본적인 샘플링 진단을 제공하기 위해 추적에서 구조가 보이지 않기 때문에 샘플링이 "혼합 중"임을 알 수 있습니다.

여기에 이미지 설명을 입력하십시오

코드를 실행하려면 Theano 및 PyMC3 패키지가 설치된 Python이 필요합니다.

훌륭한 답변과 의견을 보내 주신 @ w-huber에게 감사드립니다!


1

다음은 데이터를 맞추고 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- 값조차도 증거가 아니라 지표 일뿐입니다.


0

재미를 위해서 이것은 UWSE가 최고 비용만을 사용하여 폐쇄 형 솔루션을 제공 할 수있는 또 다른 사례입니다. 의 확률 은 모수 값에서 고유합니다. 경우 다음, 대응하는 상대를 나타낸다x=1wx=1^

sUWSE^=H101(1wx=1^)

이 경우 과 같이됩니다.wx=1^=0.4695599775

sUWSE^=1.4

다시 말하지만 UWSE는 일관된 추정치 만 제공하며 신뢰 구간은 없으며 정확성의 일부 상충 관계를 볼 수 있습니다. 위의 mpiktas 솔루션은 프로그래밍이 필요하지만 UWSE의 응용 프로그램입니다. 견적에 대한 자세한 설명은 https://paradsp.wordpress.com/을 참조하십시오 .


UWSE는 Zipf의 법칙과 어떤 관련이 있습니까?
Michael R. Chernick 2016 년

UWSE (Unique Weight Space Estimation)는 가장 높은 확률 / 주파수가 주어진 N에 대해 모수의 다른 값에서 고유하다는 사실을 사용하여을 찾습니다. Zipf의 법칙과 관련하여 이것은 우리에게 순위, N 및 최상위 주파수를 지정할 수있는 많은 항목이 주어지면 나머지 항목 (2, ..., N)에 주파수를 할당하는 방법은 하나뿐이라는 것을 알려줍니다. "n 번째 항목은 가장 빈번한 항목의 1 / n ^ s 배입니다 (일부 경우)"라고 말합니다. 다시 말해서,이 정보가 주어지면, Zipf의 법칙이 실제로 유지된다고 가정 할 때 Zipf의 법칙이 보유 할 수있는 유일한 방법이 있습니다.
CYP450 2016 년

0

내 솔루션은 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 의 기울기를 제공 합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.