วิธีการตรวจสอบการกระจายที่เหมาะกับข้อมูลของฉันที่ดีที่สุด?


133

ฉันมีชุดข้อมูลและต้องการทราบว่าการกระจายแบบใดที่เหมาะกับข้อมูลของฉันที่สุด

ฉันใช้fitdistr()ฟังก์ชันเพื่อประมาณค่าพารามิเตอร์ที่จำเป็นเพื่ออธิบายการแจกแจงแบบสมมติ (เช่น Weibull, Cauchy, Normal) การใช้พารามิเตอร์เหล่านั้นฉันสามารถทำการทดสอบ Kolmogorov-Smirnov เพื่อประเมินว่าข้อมูลตัวอย่างของฉันมาจากการแจกแจงแบบเดียวกับการแจกแจงแบบสันนิษฐานของฉันหรือไม่

หากค่า p คือ> 0.05 ฉันสามารถสรุปได้ว่าข้อมูลตัวอย่างถูกดึงมาจากการแจกแจงแบบเดียวกัน แต่ค่า p ไม่ได้ให้ข้อมูลเกี่ยวกับความเหมาะสมของพระเจ้าใช่ไหม?

ดังนั้นในกรณีที่ค่า p ของข้อมูลตัวอย่างของฉันคือ> 0.05 สำหรับการแจกแจงแบบปกติรวมถึงการแจกแบบไวบูลฉันจะรู้ได้อย่างไรว่าการแจกแจงแบบใดที่เหมาะกับข้อมูลของฉันดีกว่า

นี่เป็นสิ่งที่ฉันทำ:

> mydata
 [1] 37.50 46.79 48.30 46.04 43.40 39.25 38.49 49.51 40.38 36.98 40.00
[12] 38.49 37.74 47.92 44.53 44.91 44.91 40.00 41.51 47.92 36.98 43.40
[23] 42.26 41.89 38.87 43.02 39.25 40.38 42.64 36.98 44.15 44.91 43.40
[34] 49.81 38.87 40.00 52.45 53.13 47.92 52.45 44.91 29.54 27.13 35.60
[45] 45.34 43.37 54.15 42.77 42.88 44.26 27.14 39.31 24.80 16.62 30.30
[56] 36.39 28.60 28.53 35.84 31.10 34.55 52.65 48.81 43.42 52.49 38.00
[67] 38.65 34.54 37.70 38.11 43.05 29.95 32.48 24.63 35.33 41.34

# estimate shape and scale to perform KS-test for weibull distribution
> fitdistr(mydata, "weibull")
     shape        scale   
   6.4632971   43.2474500 
 ( 0.5800149) ( 0.8073102)

# KS-test for weibull distribution
> ks.test(mydata, "pweibull", scale=43.2474500, shape=6.4632971)

        One-sample Kolmogorov-Smirnov test

data:  mydata
D = 0.0686, p-value = 0.8669
alternative hypothesis: two-sided

# KS-test for normal distribution
> ks.test(mydata, "pnorm", mean=mean(mydata), sd=sd(mydata))

        One-sample Kolmogorov-Smirnov test

data:  mydata
D = 0.0912, p-value = 0.5522
alternative hypothesis: two-sided

ค่า p คือ 0.8669 สำหรับการแจกแจงแบบ Weibull และ 0.5522 สำหรับการแจกแจงแบบปกติ ดังนั้นฉันสามารถสันนิษฐานได้ว่าข้อมูลของฉันติดตาม Weibull เช่นเดียวกับการแจกแจงแบบปกติ แต่ฟังก์ชั่นการกระจายแบบใดอธิบายข้อมูลของฉันได้ดีกว่ากัน?


หมายถึงelevendollarฉันพบรหัสต่อไปนี้ แต่ไม่ทราบวิธีการตีความผลลัพธ์:

fits <- list(no = fitdistr(mydata, "normal"),
             we = fitdistr(mydata, "weibull"))
sapply(fits, function(i) i$loglik)
       no        we 
-259.6540 -257.9268 

5
เหตุใดคุณต้องการทราบว่าการกระจายใดเหมาะกับข้อมูลของคุณที่สุด
Roland

6
เพราะฉันต้องการสร้างตัวเลขสุ่มหลอกตามการแจกแจงที่ให้
tobibo

6
คุณไม่สามารถใช้ KS เพื่อตรวจสอบว่าการกระจายพร้อมพารามิเตอร์ที่พบจากชุดข้อมูลตรงกับชุดข้อมูล ดูตัวอย่างที่ # 2 ในหน้านี้รวมถึงทางเลือกอื่น (และวิธีอื่น ๆ ที่การทดสอบ KS อาจทำให้เข้าใจผิด)
tpg2114

การสนทนาอื่นที่นี่พร้อมตัวอย่างโค้ดเกี่ยวกับวิธีใช้การทดสอบ KS เมื่อพารามิเตอร์ถูกประเมินจากตัวอย่าง
Aksakal

1
I used the fitdistr() function ..... อะไรคือfitdistrฟังก์ชั่น? มีบางอย่างจาก Excel ใช่ไหม หรือบางสิ่งที่คุณเขียนด้วยตัวเองใน C?
wolfies

คำตอบ:


162

ก่อนอื่นต่อไปนี้เป็นข้อคิดเห็นบางส่วน:

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

แต่เรามาสำรวจกัน ฉันจะใช้fitdistrplusแพ็คเกจที่ยอดเยี่ยมซึ่งมีฟังก์ชั่นที่ดีสำหรับการจัดจำหน่ายที่เหมาะสม เราจะใช้ฟังก์ชั่นdescdistเพื่อรับแนวคิดบางอย่างเกี่ยวกับการแจกแจงผู้สมัครที่เป็นไปได้

library(fitdistrplus)
library(logspline)

x <- c(37.50,46.79,48.30,46.04,43.40,39.25,38.49,49.51,40.38,36.98,40.00,
38.49,37.74,47.92,44.53,44.91,44.91,40.00,41.51,47.92,36.98,43.40,
42.26,41.89,38.87,43.02,39.25,40.38,42.64,36.98,44.15,44.91,43.40,
49.81,38.87,40.00,52.45,53.13,47.92,52.45,44.91,29.54,27.13,35.60,
45.34,43.37,54.15,42.77,42.88,44.26,27.14,39.31,24.80,16.62,30.30,
36.39,28.60,28.53,35.84,31.10,34.55,52.65,48.81,43.42,52.49,38.00,
38.65,34.54,37.70,38.11,43.05,29.95,32.48,24.63,35.33,41.34)

ตอนนี้ให้ใช้descdist:

descdist(x, discrete = FALSE)

Descdist

ความโด่งและความเบ้ของตัวอย่างของคุณนั้นเป็นจุดสีฟ้าที่ชื่อว่า "การสังเกต" ดูเหมือนว่าการแจกแจงที่เป็นไปได้ ได้แก่ การแจกแจงแบบ Weibull, Lognormal และอาจเป็นแกมมา

มาพอดีกับการแจกแจงแบบ Weibull และการแจกแจงแบบปกติ:

fit.weibull <- fitdist(x, "weibull")
fit.norm <- fitdist(x, "norm")

ตอนนี้ตรวจสอบความพอดีสำหรับคนปกติ:

plot(fit.norm)

พอดีปกติ

และสำหรับ Weibull พอดี:

plot(fit.weibull)

พอดี Weibull

ทั้งสองดูดี แต่ตัดสินโดย QQ-Plot Weibull อาจดูดีขึ้นเล็กน้อยโดยเฉพาะที่ส่วนท้าย ในทำนองเดียวกัน AIC ของ Weibull พอดีต่ำกว่าเมื่อเทียบกับปกติ:

fit.weibull$aic
[1] 519.8537

fit.norm$aic
[1] 523.3079

การจำลองการทดสอบ Kolmogorov-Smirnov

ฉันจะใช้ขั้นตอนของ @ Aksakal อธิบายไว้ที่นี่เพื่อจำลอง KS-statistic ภายใต้ null

n.sims <- 5e4

stats <- replicate(n.sims, {      
  r <- rweibull(n = length(x)
                , shape= fit.weibull$estimate["shape"]
                , scale = fit.weibull$estimate["scale"]
  )
  estfit.weibull <- fitdist(r, "weibull") # added to account for the estimated parameters
  as.numeric(ks.test(r
                     , "pweibull"
                     , shape= estfit.weibull$estimate["shape"]
                     , scale = estfit.weibull$estimate["scale"])$statistic
  )      
})

ECDF ของสถิติ KS จำลองมีลักษณะดังนี้:

plot(ecdf(stats), las = 1, main = "KS-test statistic simulation (CDF)", col = "darkorange", lwd = 1.7)
grid()

สถิติ KS จำลอง

p

fit <- logspline(stats)

1 - plogspline(ks.test(x
                       , "pweibull"
                       , shape= fit.weibull$estimate["shape"]
                       , scale = fit.weibull$estimate["scale"])$statistic
               , fit
)

[1] 0.4889511

สิ่งนี้เป็นการยืนยันข้อสรุปเชิงกราฟิกของเราว่าตัวอย่างเข้ากันได้กับการแจกแจงแบบ Weibull

ตามที่อธิบายไว้ที่นี่เราสามารถใช้ bootstrapping เพื่อเพิ่มช่วงความเชื่อมั่นแบบจุดตามจุดใน Weibull PDF หรือ CDF โดยประมาณ:

xs <- seq(10, 65, len=500)

true.weibull <- rweibull(1e6, shape= fit.weibull$estimate["shape"]
                         , scale = fit.weibull$estimate["scale"])

boot.pdf <- sapply(1:1000, function(i) {
  xi <- sample(x, size=length(x), replace=TRUE)
  MLE.est <- suppressWarnings(fitdist(xi, distr="weibull"))  
  dweibull(xs, shape=MLE.est$estimate["shape"],  scale = MLE.est$estimate["scale"])
}
)

boot.cdf <- sapply(1:1000, function(i) {
  xi <- sample(x, size=length(x), replace=TRUE)
  MLE.est <- suppressWarnings(fitdist(xi, distr="weibull"))  
  pweibull(xs, shape= MLE.est$estimate["shape"],  scale = MLE.est$estimate["scale"])
}
)   

#-----------------------------------------------------------------------------
# Plot PDF
#-----------------------------------------------------------------------------

par(bg="white", las=1, cex=1.2)
plot(xs, boot.pdf[, 1], type="l", col=rgb(.6, .6, .6, .1), ylim=range(boot.pdf),
     xlab="x", ylab="Probability density")
for(i in 2:ncol(boot.pdf)) lines(xs, boot.pdf[, i], col=rgb(.6, .6, .6, .1))

# Add pointwise confidence bands

quants <- apply(boot.pdf, 1, quantile, c(0.025, 0.5, 0.975))
min.point <- apply(boot.pdf, 1, min, na.rm=TRUE)
max.point <- apply(boot.pdf, 1, max, na.rm=TRUE)
lines(xs, quants[1, ], col="red", lwd=1.5, lty=2)
lines(xs, quants[3, ], col="red", lwd=1.5, lty=2)
lines(xs, quants[2, ], col="darkred", lwd=2)

CI_Density

#-----------------------------------------------------------------------------
# Plot CDF
#-----------------------------------------------------------------------------

par(bg="white", las=1, cex=1.2)
plot(xs, boot.cdf[, 1], type="l", col=rgb(.6, .6, .6, .1), ylim=range(boot.cdf),
     xlab="x", ylab="F(x)")
for(i in 2:ncol(boot.cdf)) lines(xs, boot.cdf[, i], col=rgb(.6, .6, .6, .1))

# Add pointwise confidence bands

quants <- apply(boot.cdf, 1, quantile, c(0.025, 0.5, 0.975))
min.point <- apply(boot.cdf, 1, min, na.rm=TRUE)
max.point <- apply(boot.cdf, 1, max, na.rm=TRUE)
lines(xs, quants[1, ], col="red", lwd=1.5, lty=2)
lines(xs, quants[3, ], col="red", lwd=1.5, lty=2)
lines(xs, quants[2, ], col="darkred", lwd=2)
#lines(xs, min.point, col="purple")
#lines(xs, max.point, col="purple")

CI_CDF


การกระจายอัตโนมัติที่เหมาะสมกับ GAMLSS

gamlssRfitDisttype = "realline"type = "realsplus"kk=2klog(n)

library(gamlss)
library(gamlss.dist)
library(gamlss.add)

x <- c(37.50,46.79,48.30,46.04,43.40,39.25,38.49,49.51,40.38,36.98,40.00,
       38.49,37.74,47.92,44.53,44.91,44.91,40.00,41.51,47.92,36.98,43.40,
       42.26,41.89,38.87,43.02,39.25,40.38,42.64,36.98,44.15,44.91,43.40,
       49.81,38.87,40.00,52.45,53.13,47.92,52.45,44.91,29.54,27.13,35.60,
       45.34,43.37,54.15,42.77,42.88,44.26,27.14,39.31,24.80,16.62,30.30,
       36.39,28.60,28.53,35.84,31.10,34.55,52.65,48.81,43.42,52.49,38.00,
       38.65,34.54,37.70,38.11,43.05,29.95,32.48,24.63,35.33,41.34)

fit <- fitDist(x, k = 2, type = "realplus", trace = FALSE, try.gamlss = TRUE)

summary(fit)

*******************************************************************
Family:  c("WEI2", "Weibull type 2") 

Call:  gamlssML(formula = y, family = DIST[i], data = sys.parent()) 

Fitting method: "nlminb" 


Coefficient(s):
             Estimate  Std. Error  t value   Pr(>|t|)    
eta.mu    -24.3468041   2.2141197 -10.9962 < 2.22e-16 ***
eta.sigma   1.8661380   0.0892799  20.9021 < 2.22e-16 ***

จากข้อมูลของ AIC การกระจาย Weibull (โดยเฉพาะอย่างยิ่งWEI2การแบ่งพารามิเตอร์พิเศษของมัน) เหมาะกับข้อมูลที่ดีที่สุด ตัวแปรที่แน่นอนของการกระจายWEI2เป็น detailled ในเอกสารนี้ในหน้า 279 ลองตรวจสอบพอดีโดยดูที่เหลือในส่วนพล็อตหนอน (พื้น de-แนวโน้ม QQ พล็อต):

WormPlot

เราคาดว่าส่วนที่เหลือจะอยู่ใกล้กับเส้นแนวนอนกลางและ 95% ของพวกมันอยู่ระหว่างเส้นโค้งจุดบนและล่างซึ่งทำหน้าที่เป็นช่วงความเชื่อมั่นแบบจุด 95% ในกรณีนี้พล็อตหนอนดูดีสำหรับฉันแสดงว่าการกระจาย Weibull นั้นเหมาะสมอย่างยิ่ง


1
+1 การวิเคราะห์ที่ดี แต่คำถามหนึ่งข้อ ข้อสรุปเชิงบวกเกี่ยวกับความเข้ากันได้กับการแจกแจงหลักเฉพาะ (Weibull ในกรณีนี้) อนุญาตให้แยกแยะความเป็นไปได้ของการปรากฏตัวของการกระจายตัวของส่วนผสมหรือไม่? หรือเราจำเป็นต้องทำการวิเคราะห์ส่วนผสมที่เหมาะสมและตรวจสอบ GoF เพื่อแยกแยะทางเลือกนั้น?
Aleksandr Blekh

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

4
@whuber: +1 ชื่นชมคำอธิบายที่ยอดเยี่ยมของคุณ!
Aleksandr Blekh

1
@ Lourenco ฉันดูกราฟ Cullen และ Fey จุดสีน้ำเงินหมายถึงตัวอย่างของเรา คุณจะเห็นว่าจุดนั้นอยู่ใกล้กับเส้นของ Weibull, Lognormal และ Gamma (ซึ่งอยู่ระหว่าง Weibull และ Gamma) หลังจากปรับการแจกแจงแต่ละอย่างให้เหมาะสมฉันเปรียบเทียบสถิติความดีงามพอดีโดยใช้ฟังก์ชั่นgofstatและ AIC ไม่มีมติเกี่ยวกับวิธีที่ดีที่สุดในการพิจารณาการกระจาย "ดีที่สุด" คือ ฉันชอบวิธีกราฟิกและ AIC
COOLSerdash

1
@Lourenco คุณหมายถึง lognormal หรือไม่ การกระจายโลจิสติกส์ (เครื่องหมาย "+") นั้นค่อนข้างห่างจากข้อมูลที่สังเกต lognormal ก็จะเป็นผู้สมัครที่ฉันเคยดูด้วย สำหรับบทช่วยสอนนี้ฉันเลือกที่จะไม่แสดงเพื่อให้โพสต์สั้น lognormal จะแสดงแบบที่แย่กว่าเมื่อเปรียบเทียบกับการแจกแจงแบบ Weibull และ Normal AIC คือ 537.59 และกราฟก็ดูไม่ดีเกินไป
COOLSerdash

15

พล็อตส่วนใหญ่เป็นวิธีที่ดีในการรับแนวคิดที่ดีกว่าว่าข้อมูลของคุณเป็นอย่างไร ในกรณีของคุณฉันขอแนะนำให้วางแผนฟังก์ชั่นการแจกแจงสะสมเชิงประจักษ์ (ecdf) กับ cdf เชิงทฤษฎีด้วยพารามิเตอร์ที่คุณได้รับจาก fitdistr ()

ฉันทำอย่างนั้นครั้งเดียวสำหรับข้อมูลของฉันและยังรวมถึงช่วงความมั่นใจ นี่คือภาพที่ฉันใช้ ggplot2 ()

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

เส้นสีดำคือฟังก์ชั่นการแจกแจงสะสมเชิงประจักษ์และเส้นสีเป็น cdf จากการแจกแจงที่ต่างกันโดยใช้พารามิเตอร์ที่ฉันใช้โดยใช้วิธีโอกาสสูงสุด เราสามารถเห็นได้อย่างง่ายดายว่าการแจกแจงแบบเอ็กซ์โพเนนเชียลและการแจกแจงแบบปกตินั้นไม่เหมาะสมกับข้อมูลเพราะเส้นมีรูปแบบที่แตกต่างจาก ecdf และเส้นค่อนข้างห่างจาก ecdf น่าเสียดายที่ distribtions อื่น ๆ ค่อนข้างใกล้ แต่ฉันจะบอกว่าเส้นบันทึกปกติอยู่ใกล้กับเส้นสีดำมากที่สุด การใช้การวัดระยะทาง (เช่น MSE) สามารถตรวจสอบสมมติฐานได้

หากคุณมีการแจกแจงการแข่งขันสองรายการเท่านั้น (ตัวอย่างเช่นการเลือกรายการที่ดูเหมือนจะดีที่สุดในพล็อต) คุณสามารถใช้การทดสอบความน่าจะเป็น- อัตราส่วน - ทดสอบเพื่อทดสอบว่าการแจกแจงแบบไหนดีกว่า


20
ยินดีต้อนรับสู่ CrossValidated! คำตอบของคุณอาจมีประโยชน์มากกว่านี้หากคุณสามารถแก้ไขเพื่อรวม (ก) รหัสที่คุณใช้ในการสร้างกราฟิกและ (b) ว่าจะอ่านกราฟิกอย่างไร
Stephan Kolassa

2
มีการวางแผนอะไรบ้าง นั่นคือพล็อตเลขชี้กำลังบางอย่างหรือไม่?
Glen_b

1
แต่คุณจะตัดสินใจว่าการกระจายแบบใดที่เหมาะกับข้อมูลของคุณที่สุด? ตามกราฟิกฉันไม่สามารถบอกคุณได้ว่า logNormal หรือ weibull เหมาะสมกับข้อมูลของคุณมากที่สุดหรือไม่
tobibo

4
หากคุณต้องการสร้างตัวสร้างตัวเลขสุ่มหลอกทำไมไม่ใช้ cdf เชิงประจักษ์? คุณต้องการวาดตัวเลขที่เกินกว่าการแจกแจงที่คุณสังเกตเห็นหรือไม่?
elevendollar

6
เมื่อพิจารณากราฟของคุณตามมูลค่าหน้าตาก็จะปรากฏว่าไม่มีการแจกแจงผู้สมัครของคุณที่ตรงกับข้อมูลเลย นอกจากนี้ ecdf ของคุณดูเหมือนจะมีเส้นกำกับแนวนอนที่น้อยกว่า 0.03 ซึ่งไม่สมเหตุสมผลดังนั้นฉันไม่แน่ใจว่ามันเป็น ecdf จริงๆในตอนแรก
Hong Ooi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.