एक काट बहुराष्ट्रीय वितरण का नमूना कैसे लें?


9

मुझे एक छोटा बहुराष्ट्रीय वितरण नमूना करने के लिए एक एल्गोरिथ्म की आवश्यकता है। अर्थात्,

x1Zp1x1pkxkx1!xk!

जहां एक सामान्यीकरण स्थिरांक है, में सकारात्मक घटक हैं, और । मैं केवल रेंज में मानों पर विचार करता हूं, ।ZxΣएक्समैं=nएक्सएक्स

मैं इस छंटनी वाले बहुराष्ट्रीय वितरण का नमूना कैसे ले सकता हूं?

नोट: विकिपीडिया को एक गैर-छंटनी वाले बहुराष्ट्रीय वितरण के नमूने के लिए देखें । क्या इस एल्गोरिथ्म को काट-छाँट वितरण के लिए अनुकूलित करने का एक तरीका है?

समरूप संस्करण: समस्या का एक सरल संस्करण सभी समान, में लेता है । यदि आप कम से कम इस मामले में कम वितरण के नमूने के लिए एक एल्गोरिथ्म डिज़ाइन कर सकते हैं, तो कृपया इसे पोस्ट करें। हालांकि सामान्य उत्तर नहीं है, जो इस समय मुझे अन्य व्यावहारिक समस्याओं को हल करने में मदद करेगा।पीमैंपीमैं=1/

जवाबों:


9

अगर मैं आपको सही तरीके से समझूं, तो आप नमूना लेना चाहते हैं एक्स1,...,एक्स संभावनाओं के साथ बहुराष्ट्रीय वितरण से मूल्य पी1,...,पी ऐसा है कि Σमैंएक्समैं=n, हालांकि आप चाहते हैं कि वितरण कम हो मैंएक्समैंमैं सबके लिए एक्समैं

मैं तीन समाधान देखता हूं (न ही गैर-काटे गए मामले में उतना ही सुंदर):

  1. स्वीकार अस्वीकार। गैर-छंटनी वाली बहुराष्ट्रीय से नमूना, नमूना को स्वीकार करें यदि यह छंटनी सीमाओं को फिट बैठता है, अन्यथा प्रक्रिया को अस्वीकार और दोहराएं। यह तेज़ है, लेकिन बहुत अक्षम हो सकता है।
rtrmnomReject <- function(R, n, p, a, b) {
  x <- t(rmultinom(R, n, p))
  x[apply(a <= x & x <= b, 1, all) & rowSums(x) == n, ]
}
  1. प्रत्यक्ष अनुकरण। फैशन में नमूना जो डेटा-जनरेट करने की प्रक्रिया से मिलता-जुलता है, यानी एक यादृच्छिक कलश से एकल संगमरमर का नमूना और इस प्रक्रिया को तब तक दोहराएं जब तक आप नमूना न लेंn कुल में पत्थर, लेकिन जब आप दिए गए कलश से कुल संख्या को तैनात करते हैं (एक्समैं पहले से ही के बराबर है मैं) तो ऐसे कलश से ड्राइंग बंद करो। मैंने इसे एक स्क्रिप्ट में नीचे लागू किया है।
# single draw from truncated multinomial with a,b truncation points
rtrmnomDirect <- function(n, p, a, b) {
  k <- length(p)

  repeat {
    pp <- p         # reset pp
    x <- numeric(k) # reset x
    repeat {
      if (sum(x<b) == 1) { # if only a single category is left
        x[x<b] <- x[x<b] + n-sum(x) # fill this category with reminder
        break
      }
      i <- sample.int(k, 1, prob = pp) # sample x[i]
      x[i] <- x[i] + 1  
      if (x[i] == b[i]) pp[i] <- 0 # if x[i] is filled do
      # not sample from it
      if (sum(x) == n) break    # if we picked n, stop
    }
    if (all(x >= a)) break # if all x>=a sample is valid
    # otherwise reject
  }

  return(x)
}
  1. महानगर एल्गोरिथ्म। अंत में, तीसरा और सबसे कुशल दृष्टिकोण मेट्रोपोलिस एल्गोरिथ्म का उपयोग करना होगा । पहले नमूने को आकर्षित करने के लिए प्रत्यक्ष सिमुलेशन (लेकिन अलग-अलग तरह से आरंभीकृत किया जा सकता है) का उपयोग करके एल्गोरिथ्म को आरंभ किया जाता हैएक्स1। निम्नलिखित चरणों में पुनरावृत्ति: प्रस्ताव मूल्यy=क्ष(एक्समैं-1) के रूप में स्वीकार किया जाता है एक्समैं संभावना के साथ (y)/(एक्समैं-1), अन्यथा एक्समैं-1 मान उस स्थान पर लिया जाता है, जहां (एक्स)αΠमैंपीमैंएक्समैं/एक्समैं!। एक प्रस्ताव के रूप में मैंने फ़ंक्शन का उपयोग कियाक्ष वह प्राप्त करता है एक्समैं-1मान और बेतरतीब ढंग से stepमामलों की संख्या से 0 से फ़्लिप करता है और इसे दूसरी श्रेणी में ले जाता है।
# draw R values
# 'step' parameter defines magnitude of jumps
# for Meteropolis algorithm
# 'init' is a vector of values to start with
rtrmnomMetrop <- function(R, n, p, a, b,
                          step = 1,
                          init = rtrmnomDirect(n, p, a, b)) {

  k <- length(p)
  if (length(a)==1) a <- rep(a, k)
  if (length(b)==1) b <- rep(b, k)

  # approximate target log-density
  lp <- log(p)
  lf <- function(x) {
    if(any(x < a) || any(x > b) || sum(x) != n)
      return(-Inf)
    sum(lp*x - lfactorial(x))
  }

  step <- max(2, step+1)

  # proposal function
  q <- function(x) {
    idx <- sample.int(k, 2)
    u <- sample.int(step, 1)-1
    x[idx] <- x[idx] + c(-u, u)
    x
  }

  tmp <- init
  x <- matrix(nrow = R, ncol = k)
  ar <- 0

  for (i in 1:R) {
    proposal <- q(tmp)
    prob <- exp(lf(proposal) - lf(tmp))
    if (runif(1) < prob) {
      tmp <- proposal
      ar <- ar + 1
    }
    x[i,] <- tmp
  }

  structure(x, acceptance.rate = ar/R, step = step-1)
}

एल्गोरिथ्म शुरू होता है एक्स1और फिर वितरण के विभिन्न क्षेत्रों में घूमते हैं। यह स्पष्ट रूप से तेज है, फिर पिछले वाले, लेकिन आपको यह याद रखने की आवश्यकता है कि यदि आप इसका उपयोग छोटी संख्या के मामलों का नमूना करने के लिए करते हैं, तो आप ड्रॉ के साथ समाप्त हो सकते हैं जो एक दूसरे के करीब हैं। एक और समस्या यह है कि आपको stepआकार के बारे में निर्णय लेने की आवश्यकता है , अर्थात एल्गोरिथ्म को कितना बड़ा करना चाहिए - बहुत छोटा धीरे-धीरे आगे बढ़ सकता है, बहुत बड़ा हो सकता है बहुत सारे अमान्य प्रस्ताव बनाने और उन्हें अस्वीकार करने के लिए। आप इसका उपयोग नीचे देख सकते हैं। भूखंडों पर आप देख सकते हैं: पहली पंक्ति में सीमांत घनत्व, दूसरी पंक्ति में ट्रेसप्लाट और चर के जोड़े के लिए बाद में कूदता हुआ प्लॉट दिखाते हैं।

n <- 500
a <- 50
b <- 125
p <- c(1,5,2,4,3)/15
k <- length(p)
x <- rtrmnomMetrop(1e4, n, p, a, b, step = 15)

cmb <- combn(1:k, 2)

par.def <- par(mfrow=c(4,5), mar = c(2,2,2,2))
for (i in 1:k)
  hist(x[,i], main = paste0("X",i))
for (i in 1:k)
  plot(x[,i], main = paste0("X",i), type = "l", col = "lightblue")
for (i in 1:ncol(cmb))
  plot(jitter(x[,cmb[1,i]]), jitter(x[,cmb[2,i]]),
       type = "l", main = paste(paste0("X", cmb[,i]), collapse = ":"),
       col = "gray")
par(par.def)

यहाँ छवि विवरण दर्ज करें

इस वितरण से नमूने के साथ समस्या यह है कि सामान्य रूप से एक बहुत ही अक्षम नमूनाकरण रणनीति का वर्णन है । कल्पना करो किपी1पी तथा 1==, 1=... तथा मैंके करीब हैं मैंऐसे मामले में, आप अलग-अलग संभावनाओं वाली श्रेणियों के लिए नमूना बनाना चाहते हैं, लेकिन अंत में समान आवृत्तियों की अपेक्षा करते हैं। चरम मामले में, दो-श्रेणीगत वितरण की कल्पना करें जहांपी1»पी2, तथा 1«2, 1«2इस तरह के मामले में आप कुछ बहुत ही दुर्लभ घटना होने की उम्मीद करते हैं (इस तरह के वितरण का वास्तविक जीवन उदाहरण शोधकर्ता होगा जो नमूना को दोहराता है जब तक कि वह उस नमूने को नहीं पाता है जो उसकी परिकल्पना के अनुरूप है, इसलिए इसका यादृच्छिक नमूने की तुलना में धोखा देने से अधिक है) ।

वितरण बहुत कम समस्याग्रस्त है यदि आप इसे रुखिन (2007, 2008) के रूप में परिभाषित करते हैं जहां आप नमूना लेते हैं nपीमैं प्रत्येक श्रेणी के लिए मामले, यानी आनुपातिक रूप से नमूना पीमैं'है।


रुखिन, एएल (2007)। उपचार के आवंटन की समस्याओं में सामान्य क्रम के आँकड़े और ज्यामितीय यादृच्छिक चर की रकम। सांख्यिकी और संभावना पत्र, 77 (12), 1312-1321।

रुखिन, एएल (2008)। संतुलित आवंटन समस्याओं में नियम रोकना: सटीक और विषम वितरण। अनुक्रमिक विश्लेषण, 27 (3), 277-292।


अमान्य नमूनों को अस्वीकार करना बहुत धीमा हो सकता है। अनुवाद करना सरल है,yमैं=एक्समैं-मैं, =n-Σमैंमैं। इस तरह आपके पास केवल ऊपरी सीमा है,yमैंमैं-मैंके बारे में चिंता करना। फिर आप उस पंक्ति को हटा सकते हैं जहां आप नमूने को अस्वीकार करते हैं यदिएक्स का उल्लंघन किया जाता है (व्यक्ति गर्भधारण के मूल्यों को स्वीकार कर सकता है) जहां यह अस्वीकृति बहुत अक्षम होगी)
बेको जू

@becko यदि आप मेरे द्वारा वर्णित एक ऐसे दृष्टिकोण की तुलना करते हैं तो आप देखेंगे कि वे अलग-अलग समाधान देते हैं।
टिम

मुझे समझ नहीं आता कि वे अलग कैसे हो सकते हैं? मैंने जो कुछ किया वह सब चर का परिवर्तन था।
बेको

@becko आपका शुरुआती बिंदु यह है कि सभी x[i] >= a। कल्पना कीजिए कि आपने सिर की संभावना के साथ एक पक्षपाती सिक्का उछाला = 0.9। आप कम से कम 10 सिर और 10 पूंछ प्राप्त होने तक सिक्के को उछालें। रुकने के बिंदु पर आपके पास पूंछ की तुलना में औसतन बहुत अधिक सिर होंगे। शुरू करने का x[1] = ... = x[k] = aमतलब है कि आप इस तथ्य को अनदेखा करते हैं कि प्रत्येक के शुरुआती बिंदु x[i]अलग-अलग हैं p[i]
टिम

में तुम्हारी बात समझ रहा हूँ। केवल एक चीज जो मुझे आपके समाधान के बारे में पसंद नहीं है वह यह है कि मुझे लगता है कि मापदंडों के विशेष विकल्पों के लिए यह बहुत अक्षम हो सकता है।
बेकु

1

यहां टिम के आर कोड को पायथन में अनुवाद करने की कोशिश में मेरा प्रयास है। चूंकि मैंने इस समस्या को समझने में कुछ समय बिताया और पायथन में एल्गोरिदम को कोडित किया, इसलिए मैंने सोचा कि अगर लोग रुचि रखते हैं तो मैं उन्हें यहां साझा करूंगा।

  1. स्वीकार-अस्वीकार एल्गोरिथ्म :
def sample_truncated_multinomial_accept_reject(k, pVec, a, b):
    x = list(np.random.multinomial(k, pVec, size=1)[0])
    h = [x[i] >= a[i] and x[i] <= b[i] for i in range(len(x))]
    while sum(h) < len(h):
        x = list(np.random.multinomial(k, pVec, size=1)[0])
        h = [x[i] >= a[i] and x[i] <= b[i] for i in range(len(x))]
    return x
  1. प्रत्यक्ष अनुकरण
def truncated_multinomial_direct_sampling_from_urn(k, pVec, a, b):
    n = len(pVec)
    while True:
        pp = pVec 
        x = [0 for _ in range(n)] 
        while True:
            if sum([x[h] < b[h] for h in range(n)])==1:
                indx = [h for h in range(n) if x[h] < b[h]][0]
                x[indx] = k - sum(x)
                break
            i = np.random.choice(n, 1, p=pp)[0]
            x[i] += 1
            if x[i] == b[i]:
                pp = [pp[j]/(1-pp[i]) for j in range(n)]
                pp[i] = 0 
            if sum(x) == k:
                break  
        if sum([x[h] < a[h] for h in range(n)]) == 0:
            break 
    return x 
  1. महानगर एल्गोरिथ्म
def compute_log_function(x, pVec, a, b):
    x_less_a = sum([x[i] < a[i] for i in range(len(pVec))])
    x_more_a = sum([x[i] > b[i] for i in range(len(pVec))])
    if x_less_a or x_more_a or sum(x) != k:
        return float("-inf")
    return np.sum(np.log(pVec)*x - np.array([math.lgamma(h+1) for h in x]))
def sampling_distribution(original, pVec, a, b, step):
    x = copy.deepcopy(original) 
    idx = np.random.choice(len(x), 2, replace=False)
    u = np.random.choice(step, 1)[0]
    x[idx[0]] -= u
    x[idx[1]] += u
    x_less_a = sum([x[i] < a[i] for i in range(len(pVec))])
    x_more_a = sum([x[i] > b[i] for i in range(len(pVec))])
    while x_less_a or x_more_a or sum(x) != k:
        x = copy.deepcopy(original)  
        idx = np.random.choice(len(x), 2, replace=False)
        u = np.random.choice(step, 1)[0]
        x[idx[0]] -= u
        x[idx[1]] += u
        x_less_a = sum([x[i] < a[i] for i in range(len(pVec))])
        x_more_a = sum([x[i] > b[i] for i in range(len(pVec))])
    return x 
def sample_truncated_multinomial_metropolis_hasting(k, pVec, a, b, iters, step=1):
    tmp=sample_truncated_multinomial_accept_reject(k, pVec, a, b)[0]
    step = max(2, step)
    for i in range(iters):
        proposal = sampling_distribution(tmp, pVec, a, b, step)
        if compute_log_function(proposal, pVec, a, b) == float("-inf"):
            continue             
        prob = np.exp(np.array(compute_log_function(proposal, pVec, a, b)) -\
                      np.array(compute_log_function(tmp, pVec, a, b)))
        if np.random.uniform() < prob:
            tmp = proposal 
        step -= 1 
    return tmp

इस कोड के पूर्ण कार्यान्वयन के लिए कृपया मेरे Github भंडार को देखें

https://github.com/mohsenkarimzadeh/sampling

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.