วิธีการคำนวณค่าสัมประสิทธิ์ของกฎหมายของ Zipf จากชุดของความถี่สูงสุด?


25

ฉันมีความถี่ในการสืบค้นหลายครั้งและฉันจำเป็นต้องประเมินค่าสัมประสิทธิ์ของกฎหมายของ Zipf นี่คือความถี่สูงสุด:

26486
12053
5052
3033
2536
2391
1444
1220
1152
1039

ตามวิกิพีเดียหน้ากฎหมายของ Zipf มีสองพารามิเตอร์ จำนวนองค์ประกอบและเลขชี้กำลัง อะไรคือในกรณีของคุณ 10 และความถี่สามารถคำนวณได้โดยหารค่าที่คุณให้มาด้วยผลรวมของค่าทั้งหมดที่ให้มา? NsN
mpiktas

ให้มันเป็นสิบและความถี่สามารถคำนวณได้โดยหารค่าที่คุณให้มาด้วยผลรวมของค่าทั้งหมดที่ให้มา .. ฉันจะประมาณได้อย่างไร
Diegolo

คำตอบ:


22

อัปเดตฉันได้อัปเดตโค้ดด้วยตัวประมาณโอกาสสูงสุดตามคำแนะนำ @whuber การลดผลรวมกำลังสองของความแตกต่างระหว่างความน่าจะเป็นในทางทฤษฎีของการบันทึกและความถี่ของการบันทึกแม้ว่าจะให้คำตอบจะเป็นขั้นตอนทางสถิติถ้ามันแสดงให้เห็นว่ามันเป็น M-estimator น่าเสียดายที่ฉันไม่สามารถนึกถึงสิ่งใดที่สามารถให้ผลลัพธ์เดียวกัน

นี่คือความพยายามของฉัน ฉันคำนวณลอการิทึมของความถี่และพยายามปรับให้เข้ากับลอการิทึมของความน่าจะเป็นเชิงทฤษฎีที่กำหนดโดยสูตรนี้ ผลลัพธ์สุดท้ายดูเหมือนสมเหตุสมผล นี่คือรหัสของฉันในอาร์

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

ที่ดีที่สุดของพอดีกำลังสองแล้วเป็นss=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. ประเมินความเหมาะสม

สำหรับผู้ที่จะใช้วิธีการทางสถิติเพื่อความเข้าใจและการสื่อสารไม่ควรทำสิ่งแรกโดยไม่ใช้วิธีอื่น

i=1,2,,nisss>0

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

i1n

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

s^=1.45041Λ(s^)=-94,046.7s^ล.s=1.463946Λ(s^ล.s)=-94,049.5

s[1.43922,1.46162]

เมื่อพิจารณาถึงกฎของ Zipf วิธีที่ถูกต้องในการทำกราฟฟิตนี้อยู่บนพล็อตการบันทึกล็อกซึ่งความพอดีจะเป็นแบบเส้นตรง (ตามคำนิยาม):

ป้อนคำอธิบายรูปภาพที่นี่

หากต้องการประเมินความดีของการฟิตและสำรวจข้อมูลให้ดูที่ส่วนที่เหลือ (ข้อมูล / พอดีแกนล็อก - บันทึกอีกครั้ง):

ป้อนคำอธิบายรูปภาพที่นี่

χ2=656.476


เพราะเหลือปรากฏสุ่มในการใช้งานบางอย่างที่เราอาจจะมีเนื้อหาที่จะยอมรับกฎหมาย Zipf (และประมาณการของเราที่พารามิเตอร์) ในฐานะที่เป็นที่ยอมรับได้แม้ว่าหยาบคำอธิบายของความถี่ การวิเคราะห์นี้แสดงให้เห็นว่ามันจะเป็นความผิดพลาดในการสมมติว่าการประเมินนี้มีค่าที่อธิบายหรือคาดการณ์สำหรับชุดข้อมูลที่ตรวจสอบที่นี่


1
@whuber ฉันอาจขอแนะนำเล็กน้อยอย่างระมัดระวังด้วยสูตรที่กำหนดไว้ข้างต้น กฎหมายของ Zipf มักจะถูกระบุว่าเป็นผลญาติ - ความถี่ มันไม่ได้ (โดยปกติจะพิจารณา) การแจกแจงที่ดึงตัวอย่าง iid เฟรมเวิร์ก iid อาจไม่ใช่แนวคิดที่ดีที่สุดสำหรับข้อมูลเหล่านี้ บางทีฉันจะโพสต์เพิ่มเติมในภายหลังนี้
พระคาร์ดินัล

3
@ cardinal ฉันหวังว่าจะเป็นสิ่งที่คุณพูด หากคุณไม่มีเวลาสำหรับการตอบสนองอย่างละเอียดแม้แต่ภาพร่างของสิ่งที่คุณคิดว่าอาจเป็น "ความคิดที่ดีที่สุดสำหรับข้อมูลเหล่านี้" ก็ยินดีต้อนรับมากที่สุด ฉันสามารถเดาได้ว่าคุณกำลังทำอะไรกับสิ่งนี้: ข้อมูลถูกจัดอันดับเป็นกระบวนการที่สร้างการพึ่งพาและควรกำหนดให้ฉันต้องปกป้องโอกาสที่ได้รับโดยไม่ต้องคำนึงถึงผลกระทบที่อาจเกิดขึ้นจากการจัดอันดับ มันจะเป็นการดีที่ได้เห็นขั้นตอนการประมาณค่าด้วยเหตุผลที่ทำให้เกิดเสียง ฉันหวังว่าการวิเคราะห์ของฉันจะได้รับการช่วยเหลือด้วยขนาดที่แท้จริงของชุดข้อมูล
whuber

1
@ cardinal อย่าทำแฟร์มาต์กับเรา :) หากคุณมีความเข้าใจที่แตกต่างจากผู้ตอบคนอื่น ๆ อย่าลังเลที่จะแสดงมันในคำตอบที่แยกต่างหากแม้ว่ามันจะไม่ถือว่าเป็นการตอบที่ถูกต้องก็ตาม ในวิชาคณิตศาสตร์ตัวอย่างเช่นสถานการณ์ดังกล่าวเกิดขึ้นค่อนข้างบ่อย
mpiktas

1
@cardinal ได้อย่างง่ายดาย ตัวอย่างเช่นคุณรวบรวมความถี่และระบุและจัดอันดับสิบที่สูงที่สุด คุณตั้งสมมติฐานกฏของ Zipf คุณรวบรวมความถี่ชุดใหม่และรายงานตามการจัดอันดับก่อนหน้า นั่นเป็นสถานการณ์ที่การวิเคราะห์ของฉันเหมาะอย่างยิ่งโดยขึ้นอยู่กับอันดับใหม่ที่เห็นด้วยกับกลุ่มเก่า
whuber

1
@whuber ขอบคุณสำหรับความอดทนของคุณ ตอนนี้ฉันมีเหตุผลที่ชัดเจนในการให้เหตุผลของคุณ ภายใต้รูปแบบการสุ่มตัวอย่างที่คุณได้รับจากข้อมูลทั้งหมดฉันเห็นด้วยกับการวิเคราะห์ของคุณ บางทีคำแถลงสุดท้ายของคุณอาจลื่นหน่อย หากการเรียงลำดับไม่ก่อให้เกิดการพึ่งพาที่แข็งแกร่งกว่าวิธีการของคุณจะเป็นแบบอนุรักษ์นิยม หากการพึ่งพาอาศัยกันที่เกิดขึ้นมีความรุนแรงพอสมควรก็อาจกลายเป็น anticonservative ขอบคุณสำหรับความอดทนของคุณในการเผชิญกับคนเดินเท้าของฉัน
พระคาร์ดินัล

2

s

หนึ่งในภาษาโปรแกรมที่น่าจะเป็นเช่นPyMC3ทำให้การประมาณค่านี้ค่อนข้างตรงไปตรงมา ภาษาอื่น ๆ รวมถึงStanซึ่งมีคุณสมบัติที่ยอดเยี่ยมและชุมชนที่สนับสนุน

นี่คือการใช้งาน Python ของรุ่นที่ติดตั้งบนข้อมูล OPs (บน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()

ss

enter image description here

เพื่อให้การวินิจฉัยการสุ่มตัวอย่างพื้นฐานบางอย่างเราจะเห็นว่าการสุ่มตัวอย่างนั้นเป็นการ "ผสมกัน" เนื่องจากเราไม่เห็นโครงสร้างใด ๆ ในการติดตาม:

enter image description here

ในการเรียกใช้รหัสจำเป็นต้องใช้ Python พร้อมกับแพ็คเกจ Theano และ PyMC3

ขอบคุณ @ 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

enter image description here

    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

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

UWSE (การประมาณค่าน้ำหนักพื้นที่ที่ไม่ซ้ำ) ใช้ความจริงที่ความน่าจะเป็น / ความถี่สูงสุดบนสุดนั้นไม่ซ้ำกันในค่าต่าง ๆ ของพารามิเตอร์สำหรับ N ที่กำหนดเพื่อค้นหา ด้วยความเคารพกฎหมายของ Zipf สิ่งนี้บอกเราว่าเมื่อได้รับสิ่งของจำนวนหนึ่งเพื่อจัดอันดับ N และความถี่สูงสุดมีเพียงวิธีเดียวเท่านั้นที่กำหนดความถี่ให้กับรายการที่เหลือ (2, ... , N) เช่นนี้ พูดว่า "รายการที่ n คือ 1 / n ^ s ครั้งใหญ่เท่ารายการที่พบบ่อยที่สุดสำหรับบางคน" กล่าวอีกนัยหนึ่งเมื่อได้รับข้อมูลนี้มีเพียงหนทางเดียวที่กฎหมายของ Zipf จะถือได้ - แน่นอนโดยสมมติว่ากฎหมายของ Zipf นั้นเป็นจริง
CYP450

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)

enter image description here

ผลลัพธ์ทำให้เรามีความชัน1.450408เหมือนกับคำตอบก่อนหน้า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.