Zipf yasası katsayısı bir dizi üst frekanstan nasıl hesaplanır?


25

Birkaç sorgu sıklığım var ve Zipf yasasının katsayısını tahmin etmem gerekiyor. Bunlar en üst frekanslar:

26486
12053
5052
3033
2536
2391
1444
1220
1152
1039

wikipedia sayfasına göre Zipf yasasının iki parametresi var. Elemanlarının sayısı N ve s üs. Senin durumunda nedir N, 10? Frekanslar, tedarik edilen değerleri, tedarik edilen tüm değerlerin toplamına bölerek hesaplanabilir mi?
mpiktas

bırakalım, ve verilmiş olan değerlerin, verilmiş olan değerlerin toplamına bölünmesiyle frekanslar hesaplanabilir. Nasıl tahmin edebilirim?
Diegolo

Yanıtlar:


22

Güncelle @whuber önerisine göre kodu maksimum olasılık tahmincisi ile güncelledim. Günlük teorik olasılıkları ve günlük frekansları arasındaki farkların karelerinin toplamının en aza indirilmesine rağmen cevap verilmesi, bir tür M-tahmin edicisi olduğu gösterilebilirse istatistiksel bir prosedür olacaktır. Ne yazık ki aynı sonuçları verebilecek hiçbir şey düşünemedim.

İşte benim girişimim. Frekansların logaritmalarını hesaplıyorum ve bu formülle verilen teorik olasılıkların logaritmalarına uymaya çalışıyorum . Nihai sonuç makul görünüyor. İşte R kodum.

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

En iyi ikinci dereceden uygunluk .s=1.47

R'deki maksimum olasılık, standart hataları yararlı bir şekilde hesaplayan (doğru negatif maksimum olasılık işlevi sağlanmışsa) mleişleviyle ( stats4paketten) gerçekleştirilebilir :

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 

İşte log-log ölçeğinde uygunluk grafiği (yine @whuber'ın önerdiği gibi):

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)

Kırmızı çizgi karelerin sığma toplamıdır, yeşil çizgi maksimum olabilirlik uyumudur.

Günlüklerin log-log grafiği


1
Bir R paketi de var zipfR cran.r-project.org/web/packages/zipfR/index.html Yine de denemedim.
Şubat'ta

@onestop, bağlantı için teşekkürler. Birinin bu soruyu bu paketi kullanarak cevaplaması iyi olurdu. Çözümüm kesinlikle bir derinlikten yoksundur, ancak bir tür cevap verir.
mpiktas

(+1) Gerçekten etkileyicisin. Çok farklı istatistiksel alanlarda çok iyi katkı!
22'de

@chl, teşekkürler! Kesinlikle bu sitede böyle özelliklere sahip tek kişi olmadığımı hissediyorum;)
mpiktas

25

Herhangi bir tahmin probleminde bizden önce birkaç sorun vardır:

  1. Parametreyi tahmin et.

  2. Bu tahminin kalitesini değerlendirin.

  3. Verileri araştırın.

  4. Uygunluğu değerlendirin.

İstatistiksel yöntemleri anlama ve iletişim için kullanacak olanlar için , ilk önce diğerleri olmadan yapılmamalıdır.

i=1,2,,nisss>0

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

i1n

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

frekansları ile özetlenen bağımsız veriler için , olasılık bireysel olasılıkların ürünüdür.fi,i=1,2,,n

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

Böylece verinin log olasılığı

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

Sabit gibi verileri dikkate alındığında, ve bir fonksiyonu olarak açıkça bu ifade , bu günlüğü yapar Olabilirlik .s

verilen verilerle olabilirlik ve . Bu önemli ölçüde daha iyi (ama zar zor çok) (log frekansları göre) en küçük kareler çözelti daha ile . (Optimizasyon, mpiktas tarafından sağlanan zarif ve net R kodunda küçük bir değişiklikle yapılabilir .)s^=1.45041Λ(s^)=94046.7s^ls=1.463946Λ(s^ls)=94049.5

ML , her zamanki gibi için güven limitlerini tahmin edecektir . Ki-kare yaklaşımı verir (eğer hesaplamaları doğru yaparsam :-).[ 1.43922 , 1.46162 ]s[1.43922,1.46162]

Zipf yasasının niteliği göz önüne alındığında, bu uyumu grafiklendirmek için doğru yol , uyumu lineer olacağı bir log-log grafiğidir (tanım gereği):

görüntü tanımını buraya girin

Uyumun iyiliğini değerlendirmek ve verileri araştırmak için , kalıntılara bakın (tekrar veri / uyum, log-log eksenleri):

görüntü tanımını buraya girin

Bu çok büyük değil: Kalıntılarda belirgin bir seri korelasyon veya heterosistemiklik olmamasına rağmen, bunlar tipik olarak% 10 civarındadır (1.0'dan uzakta). Binlerce frekansla, sapmaların yüzde birkaçından daha fazla olmasını beklemeyiz. Uyum iyiliği kolaylıkla test edilmiştir ki kare . 10 - 1 = 9 serbestlik derecesiyle elde ediyoruz ; Bu, Zipf Yasası'ndan ayrılmanın oldukça önemli bir kanıtıdır .χ2=656.476


Artıklar rastgele göründüğü için, bazı uygulamalarda , frekansların kaba bir açıklaması olsa da , Zipf Yasasını (ve parametre tahminimizi) kabul etmekten memnunuz . Bu analiz, bu tahminin burada incelenen veri seti için açıklayıcı veya öngörücü bir değere sahip olduğunu varsaymanın yanlış olacağını göstermektedir.


1
@whuber, alçakgönüllülükle yukarıda verilen formülasyon ile biraz dikkatli önerebilir. Zipf yasası genellikle nispi frekans sonucu olarak ifade edilir. Bir iid numunesinin çizildiği dağılım (normal kabul edilir) değildir. Bir iid çerçeve muhtemelen bu veriler için en iyi fikir değildir. Belki bunu daha sonra yayınlayacağım.
kardinal

3
@cardinal Söyleyeceğiniz şeyi sabırsızlıkla bekliyorum. Tam bir cevap almak için zamanınız yoksa, "bu veriler için en iyi fikir" olabileceğini düşündüğünüz bir taslak bile en iyi şekilde olacaktır. Bununla nereye gideceğinizi tahmin edebilirim: veriler sıralandı, bağımlılıklar yaratan bir süreç ve sıralamanın potansiyel etkilerini fark etmeden elde edilen bir olasılığı savunmamı gerektiren bir süreç. Daha sağlam bir gerekçeyle bir tahmin prosedürü görmek güzel olurdu. Yine de, analizimin veri setinin büyüklüğü tarafından kurtarılabileceğine ümit ediyorum.
whuber

1
@cardinal, bize Fermat yapmayın :) Eğer diğer cevaplayıcılardan biraz farklı bir görüşünüz varsa, kendi başına geçerli bir cevap oluşturmasa bile, ayrı cevaplarda ifade etmekten çekinmeyin. In math.SE örneğin durumlar oldukça sık ortaya çıkar.
mpiktas

1
@cardinal Kolayca. Örneğin, frekansları toplar ve en yüksek on olanı tanımlar ve sıralarsınız. Zipf Yasasını varsayıyorsun. Yeni bir frekans seti toplar ve önceki sıralamaya göre raporlarsınız . Eskiler ile aynı fikirde olan yeni rütbelere bağlı olarak, analizimin mükemmel bir şekilde uygun olduğu durum budur .
whuber

1
@whuber, sabrınız için teşekkürler. Şimdi akıl yürütme şeklinizi tamamen anlıyorum. Şimdi tamamen tükenmiş örnekleme modelinde analizinize katılıyorum. Belki de en son ifadeniz hala biraz kaygandır. Sıralama, yönteminizden daha güçlü bir bağımlılık yaratmazsa, muhafazakar olur. Eğer indüklenen bağımlılık orta derecede güçlüyse antiko-koruyucu olabilir. Soykırım karşısında sana sabrın için teşekkürler.
kardinal

2

Maksimum Olabilirlik tahminleri yalnızca parametresinin nokta tahminleridir . Tahminin güven aralığını da bulmak için ekstra çaba gerekir. Sorun, bu aralığın olasılıksız olmamasıdır. Birisi "s = ... parametre değeri [...] aralığında% 95 olasılık ile." Diyemez.s

PyMC3 gibi olası programlama dillerinden biri, bu tahminin nispeten basit olmasını sağlar. Diğer diller arasında , mükemmel özellikleri ve destekleyici topluluğu olan Stan bulunur.

İşte OPs verilerine dayanan modelin Python uygulaması (ayrıca Github'da ):

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()

İşte parametresinin dağılım formundaki tahminleri . Tahminin ne kadar küçük olduğuna dikkat edin! % 95 olasılık ile parametresinin gerçek değeri [1.439,1.461]; ortalama, MLE tahminlerine çok yakın olan yaklaşık 1.45'tir.sss

görüntü tanımını buraya girin

Bazı temel örnekleme diyagnostiklerini sağlamak için, izlemede herhangi bir yapı görmediğimizden örneklemenin “iyi karışıyor” olduğunu görebiliriz:

görüntü tanımını buraya girin

Kodu çalıştırmak için, Theano ve PyMC3 paketlerinin yüklü olduğu Python'a ihtiyaç vardır.

Mükemmel yanıtı ve yorumları için @ w-huber'e teşekkürler!


1

İşte VGAM kullanarak verileri sığdırmak, değerlendirmek ve sonuçları araştırmak:

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

görüntü tanımını buraya girin

    Chi-squared test for given probabilities

data:  zdata$ofreq
X-squared = 99.756, df = 99, p-value = 0.4598

Bizim durumumuzda Chi square'ın boş hipotezi, verilerin zipf yasasına göre dağıtılmasıdır, dolayısıyla daha büyük p değerleri, verilerin buna göre dağıtıldığı iddiasını desteklemektedir. Çok büyük p değerlerinin bile ispat olmadığını, sadece bir gösterge olduğunu unutmayın.


0

Sadece eğlence için, bu, UWSE'nin sadece en yüksek frekansı kullanarak kapalı bir form çözümü sunabileceği bir başka örnektir - doğruluk maliyeti olsa da. olasılık, parametre değerleri arasında benzersizdir. Eğer , daha sonra karşılık gelen nispi frekansı temsil eder^ w x = 1x=1wx=1^

sUWSE^=H101(1wx=1^)

Bu durumda, alıyoruz:wx=1^=0.4695599775

sUWSE^=1.4

Yine, UWSE yalnızca tutarlı bir tahmin sunar - güven aralığı yok ve doğrulukla bir miktar takas görebiliriz. mpiktas'ın yukarıdaki çözümü de UWSE'nin bir uygulamasıdır - ancak programlama gerekli. Tahmincinin tam bir açıklaması için bakınız: https://paradsp.wordpress.com/ - alttaki tüm yol.


UWSE'nin Zipf yasası ile ilişkisi nedir?
Michael R. Chernick

UWSE (Eşsiz Ağırlık Alanı Tahmini), en yüksek olasılık / frekansın s parametresini bulmak için belirli bir N için s parametresinin farklı değerleri arasında benzersiz olduğu gerçeğini kullanır. Zipf yasası ile ilgili olarak, bu bize, N, en üst sıradaki sıklığa bir dizi madde verilmişse, kalan öğelere (2, ..., N) sıklık atayabilecek tek bir yol olduğunu, "n. öğe, bazı s'ler için en sık kullanılan öğenin büyüklüğünün 1 / n ^ s katıdır" deyin. Başka bir deyişle, bu bilgi göz önüne alındığında, Zipf yasasının geçerli olduğunu varsayarsak, tabii ki, Zipf yasasının tutmasının tek yolu vardır.
CYP450,

0

Çözümüm, mpiktas ve whuber tarafından Python'da bir uygulama yaparken verilen cevapları tamamlayıcı olmaya çalışıyorum. Frekans ve aralıklarımız 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])

Fonksiyonumuz tüm aralıklarda tanımlanmadığından, her hesapladığımızda normalize ettiğimizi kontrol etmemiz gerekir. Kesikli durumda, basit bir yaklaşım tüm y (x) 'nin toplamına bölünmesidir. Bu şekilde farklı parametreleri karşılaştırabiliriz.

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)

görüntü tanımını buraya girin

Sonuç bize önceki cevaplarda olduğu gibi 1.450408 eğim veriyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.