Tôi có một số tần số truy vấn và tôi cần ước tính hệ số của luật Zipf. Đây là những tần số hàng đầu:
26486
12053
5052
3033
2536
2391
1444
1220
1152
1039
Tôi có một số tần số truy vấn và tôi cần ước tính hệ số của luật Zipf. Đây là những tần số hàng đầu:
26486
12053
5052
3033
2536
2391
1444
1220
1152
1039
Câu trả lời:
Cập nhật Tôi đã cập nhật mã với công cụ ước tính khả năng tối đa theo đề xuất @whuber. Tối thiểu hóa tổng bình phương của sự khác biệt giữa xác suất lý thuyết log và tần số log mặc dù đưa ra câu trả lời sẽ là một thủ tục thống kê nếu có thể chỉ ra rằng đó là một loại công cụ ước lượng M. Thật không may, tôi không thể nghĩ ra cái nào có thể cho kết quả tương tự.
Đây là nỗ lực của tôi. Tôi tính toán logarit của các tần số và cố gắng khớp chúng với logarit của xác suất lý thuyết được đưa ra bởi công thức này . Kết quả cuối cùng có vẻ hợp lý. Đây là mã của tôi trong 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
Phù hợp bậc hai tốt nhất sau đó là .
Khả năng tối đa trong R có thể được thực hiện bằng mle
hàm (từ stats4
gói), tính toán một cách hữu ích các lỗi tiêu chuẩn (nếu chức năng khả năng tối đa âm chính xác được cung cấp):
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
Dưới đây là biểu đồ về sự phù hợp trong thang đo log-log (một lần nữa như @whuber đề xuất):
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)
Đường màu đỏ là tổng của hình vuông phù hợp, đường màu xanh là khả năng phù hợp tối đa.
Có một số vấn đề trước chúng tôi trong bất kỳ vấn đề ước tính nào :
Ước tính tham số.
Đánh giá chất lượng của ước tính đó.
Khám phá dữ liệu.
Đánh giá sự phù hợp.
Đối với những người sẽ sử dụng các phương pháp thống kê để hiểu và giao tiếp, việc đầu tiên không bao giờ nên được thực hiện mà không có những người khác.
Để ước tính , thuận tiện để sử dụng khả năng tối đa (ML). Các tần số rất lớn, chúng ta có thể mong đợi các thuộc tính tiệm cận nổi tiếng sẽ được giữ. ML sử dụng phân phối xác suất giả định của dữ liệu.
Do đó, xác suất đăng nhập cho dữ liệu là
mã được cung cấp bởi mpiktas.)
(nếu tôi thực hiện các phép tính chính xác :-).
Với bản chất của luật Zipf, cách phù hợp để vẽ biểu đồ sự phù hợp này là trên biểu đồ log-log , trong đó sự phù hợp sẽ là tuyến tính (theo định nghĩa):
Để đánh giá mức độ phù hợp và khám phá dữ liệu, hãy xem phần dư (dữ liệu / sự phù hợp, trục log-log một lần nữa):
Do phần dư xuất hiện ngẫu nhiên, nên trong một số ứng dụng, chúng tôi có thể chấp nhận Luật của Zipf (và ước tính của chúng tôi về tham số) dưới dạng mô tả sơ bộ về tần số . Tuy nhiên, phân tích này cho thấy sẽ là một sai lầm khi cho rằng ước tính này có bất kỳ giá trị giải thích hoặc dự đoán nào cho bộ dữ liệu được kiểm tra ở đây.
Một trong những ngôn ngữ lập trình xác suất như PyMC3 đưa ra ước tính này tương đối đơn giản. Các ngôn ngữ khác bao gồm Stan có các tính năng tuyệt vời và cộng đồng hỗ trợ.
Dưới đây là triển khai Python của tôi về mô hình được trang bị trên dữ liệu OP (cũng trên 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()
ở dạng phân phối. Thông báo làm thế nào nhỏ gọn là ước tính! Với xác suất 95% giá trị thực của tham sốnằm trong phạm vi [1.439,1.461]; giá trị trung bình là khoảng 1,45, rất gần với ước tính của MLE.
Để cung cấp một số chẩn đoán lấy mẫu cơ bản, chúng ta có thể thấy rằng việc lấy mẫu là "trộn tốt" vì chúng ta không thấy bất kỳ cấu trúc nào trong dấu vết:
Để chạy mã, người ta cần Python với các gói Theano và PyMC3 được cài đặt.
Cảm ơn @ w-huber vì câu trả lời và bình luận tuyệt vời của anh ấy!
Đây là nỗ lực của tôi để phù hợp với dữ liệu, đánh giá và khám phá kết quả bằng 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
Trong trường hợp của chúng tôi, giả thuyết null của Chi vuông là dữ liệu được phân phối theo luật của zipf, do đó giá trị p lớn hơn hỗ trợ cho tuyên bố rằng dữ liệu được phân phối theo dữ liệu đó. Lưu ý rằng ngay cả các giá trị p rất lớn không phải là một bằng chứng, chỉ là một chỉ báo.
Để cho vui, đây là một trường hợp khác trong đó UWSE có thể cung cấp giải pháp dạng đóng chỉ sử dụng tần số cao nhất - mặc dù với chi phí chính xác. Xác suất trênlà duy nhất trên các giá trị tham số. Nếu biểu thị tần số tương đối sau đó,
Trong trường hợp này, kể từ khi , chúng tôi nhận được:
Một lần nữa, UWSE chỉ cung cấp một ước tính nhất quán - không có khoảng tin cậy và chúng ta có thể thấy một số sự đánh đổi chính xác. giải pháp của mpiktas ở trên cũng là một ứng dụng của UWSE - mặc dù việc lập trình là bắt buộc. Để biết giải thích đầy đủ về công cụ ước tính, hãy xem: https://paradsp.wordpress.com/ - tất cả các cách ở phía dưới.
Giải pháp của tôi cố gắng bổ sung cho các câu trả lời được cung cấp bởi mpiktas và whuber khi thực hiện bằng Python. Tần số và phạm vi x của chúng tôi là:
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])
Vì chức năng của chúng tôi không được xác định trong tất cả các phạm vi, chúng tôi cần kiểm tra xem chúng tôi có đang bình thường hóa mỗi lần chúng tôi tính toán nó không. Trong trường hợp riêng biệt, một xấp xỉ đơn giản là chia cho tổng của tất cả y (x). Bằng cách này, chúng ta có thể so sánh các tham số khác nhau.
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)
Kết quả cho chúng ta độ dốc 1.450408 như trong các câu trả lời trước.