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
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
Yanıtlar:
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 .
R'deki maksimum olasılık, standart hataları yararlı bir şekilde hesaplayan (doğru negatif maksimum olasılık işlevi sağlanmışsa) mle
işleviyle ( stats4
paketten) 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.
Herhangi bir tahmin probleminde bizden önce birkaç sorun vardır:
Parametreyi tahmin et.
Bu tahminin kalitesini değerlendirin.
Verileri araştırın.
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.
frekansları ile özetlenen bağımsız veriler için , olasılık bireysel olasılıkların ürünüdür.
Böylece verinin log olasılığı
Sabit gibi verileri dikkate alındığında, ve bir fonksiyonu olarak açıkça bu ifade , bu günlüğü yapar Olabilirlik .
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 .)
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 ]
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):
Uyumun iyiliğini değerlendirmek ve verileri araştırmak için , kalıntılara bakın (tekrar veri / uyum, log-log eksenleri):
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 .
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.
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.
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.s
Bazı temel örnekleme diyagnostiklerini sağlamak için, izlemede herhangi bir yapı görmediğimizden örneklemenin “iyi karışıyor” olduğunu görebiliriz:
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!
İş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
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.
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 = 1
Bu durumda, alıyoruz:
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.
Çö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)
Sonuç bize önceki cevaplarda olduğu gibi 1.450408 eğim veriyor.