সাধারণ বিতরণের মিশ্রণ থেকে এলোমেলো পরিবর্তনগুলি তৈরি করা


20

আমি মিশ্রণ বিতরণ এবং বিশেষত সাধারণ বিতরণের মিশ্রণটি কীভাবে নমুনা করব R? উদাহরণস্বরূপ, যদি আমি এর থেকে নমুনা নিতে চাই:

0.3×N(0,1)+0.5×N(10,1)+0.2×N(3,.1)

আমি এটা কিভাবে করতে পারি?


3
আমি মিশ্রণটি বোঝানোর পক্ষে এই পদ্ধতিটি সত্যিই পছন্দ করি না। আমি জানি এটি প্রচলিতভাবে এ জাতীয়ভাবে করা হয়েছে তবে আমি এটি বিভ্রান্তিকর বলে মনে করি not বিজ্ঞপ্তিটি সূচিত করে যে নমুনা দেওয়ার জন্য আপনাকে তিনটি নরমালকে নমুনা তৈরি করতে হবে এবং সেই গুণাগুণগুলির দ্বারা ফলাফলগুলি ওজন করা উচিত যা স্পষ্টতই সঠিক হবে না। আরও ভাল স্বরলিপি কেউ জানেন?
StijnDeVuyst

আমি এই ধারণাটি পাই না। আমি বিতরণগুলি (এই ক্ষেত্রে তিনটি সাধারণ বিতরণকে) ফাংশন হিসাবে ভাবি এবং তারপরে ফলাফলটি অন্য ফাংশন।
রাউন্ডস্কোয়ার

@ স্টিজনডেভুইস্ট আপনি আপনার মন্তব্য থেকে উদ্ভূত এই প্রশ্নটি দেখতে চাইতে পারেন: stats.stackexchange.com/questions/431171/…
ankii

@ কঙ্কি: এটি নির্দেশ করার জন্য ধন্যবাদ!
StijnDeVuyst

উত্তর:


32

পারফরম্যান্সের কারণে forলুপগুলি এড়ানো ভাল অনুশীলন R। একটি বিকল্প সমাধান যা সত্যটিকে কাজে লাগায় rnormতা ভেক্টরাইজড:

N <- 100000

components <- sample(1:3,prob=c(0.3,0.5,0.2),size=N,replace=TRUE)
mus <- c(0,10,3)
sds <- sqrt(c(1,1,0.1))

samples <- rnorm(n=N,mean=mus[components],sd=sds[components])

3
বিকল্পভাবে, আপনি সর্বশেষ লাইনটি প্রতিস্থাপন করতে সাধারণ বিতরণের বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন samples <- rnorm(N)*sds[components]+mus[components]। আমি পড়তে সহজ মনে করি :)
এলভিস

খুব মার্জিত (সিসি @ এলভিস)!
ইটামার

18

সাধারণভাবে, একটি মিশ্রণ বিতরণ থেকে নমুনার সবচেয়ে সহজ উপায় নিম্নলিখিত:

অ্যালগরিদম পদক্ষেপ

1) একটি এলোমেলো পরিবর্তনশীল U ইউনিফর্ম তৈরি করুন ( 0 , 1 )UUniform(0,1)

U[i=1kpk,i=1k+1pk+1)pkkthkth

3) পদক্ষেপ 1) এবং 2) পুনরাবৃত্তি করুন যতক্ষণ না আপনি মিশ্রণ বিতরণ থেকে পছন্দসই নমুনাগুলি পান have

এখন উপরে বর্ণিত সাধারণ অ্যালগরিদম ব্যবহার করে আপনি নীচের Rকোডটি ব্যবহার করে আপনার নরমালদের উদাহরণের মিশ্রণটি থেকে নমুনা নিতে পারেন :

#The number of samples from the mixture distribution
N = 100000                 

#Sample N random uniforms U
U =runif(N)

#Variable to store the samples from the mixture distribution                                             
rand.samples = rep(NA,N)

#Sampling from the mixture
for(i in 1:N){
    if(U[i]<.3){
        rand.samples[i] = rnorm(1,0,1)
    }else if(U[i]<.8){
        rand.samples[i] = rnorm(1,10,1)
    }else{
        rand.samples[i] = rnorm(1,3,.1)
    }
}

#Density plot of the random samples
plot(density(rand.samples),main="Density Estimate of the Mixture Model")

#Plotting the true density as a sanity check
x = seq(-20,20,.1)
truth = .3*dnorm(x,0,1) + .5*dnorm(x,10,1) + .2*dnorm(x,3,.1)
plot(density(rand.samples),main="Density Estimate of the Mixture Model",ylim=c(0,.2),lwd=2)
lines(x,truth,col="red",lwd=2)

legend("topleft",c("True Density","Estimated Density"),col=c("red","black"),lwd=2)

যা উত্পন্ন করে:

এখানে চিত্র বর্ণনা লিখুন

এবং স্যানিটি পরীক্ষা হিসাবে:

এখানে চিত্র বর্ণনা লিখুন


ওহে! অনেক ধন্যবাদ! এই উত্তরটি আমাকে অনেক সাহায্য করেছে। আমি এটি একটি গবেষণা প্রকল্পে ব্যবহার করছি। আমি উপরের জন্য একটি রেফারেন্স উদ্ধৃত করতে ইচ্ছুক। আপনি দয়া করে একটি গবেষণা নিবন্ধ উদ্ধৃতি প্রস্তাব করতে পারেন।
অভিষেক ভাটিয়া

7

kR

set.seed(8)               # this makes the example reproducible
N     = 1000              # this is how many data you want
probs = c(.3,.8)          # these are *cumulative* probabilities; since they 
                          #   necessarily sum to 1, the last would be redundant
dists = runif(N)          # here I'm generating random variates from a uniform
                          #   to select the relevant distribution

# this is where the actual data are generated, it's just some if->then
#   statements, followed by the normal distributions you were interested in
data = vector(length=N)
for(i in 1:N){
  if(dists[i]<probs[1]){
    data[i] = rnorm(1, mean=0, sd=1)
  } else if(dists[i]<probs[2]){
    data[i] = rnorm(1, mean=10, sd=1)
  } else {
    data[i] = rnorm(1, mean=3, sd=.1)
  }
}

# here are a couple of ways of looking at the results
summary(data)
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
# -3.2820  0.8443  3.1910  5.5350 10.0700 13.1600 

plot(density(data))

এখানে চিত্র বর্ণনা লিখুন


উত্তম উত্তর, আপনি আমাকে পোস্ট করতে মারলেন: পি

1
টিপসের জন্য ধন্যবাদ, বাবকপি। আমি নিশ্চিত না যে এটি কী ছিল। এটি ifelse()বিবৃতিতে কিছু ছিল তবে আমাকে এটি পরে বের করতে হবে। আমি সেই কোডটি ডাব্লু / একটি লুপ প্রতিস্থাপন করেছি।
গুং - মনিকা পুনরায়

6
RfindInterval()cumsum()μmuσ2spmix <- function(n,mu,s,p) { ii <- findInterval(runif(n),cumsum(p))+1; x <- rnorm(n,mean=mu[ii],sd=sqrt(s[ii])); return(x); }

1
@ ম্যাক্রো, খুব সত্য এবং খুব সুন্দর কোড! আমি findInterval()কমান্ডটি আগে দেখিনি , তবে আমি এখানে কোডটি যতটা সরলভাবে লিখতে চাই তাতে লিখতে পছন্দ করি কারণ আমি চাই এটি দক্ষতার চেয়ে বোঝার সরঞ্জাম হয়ে উঠুক।

1
আমি বললাম এগুলি ভাল উত্তর ছিল। আমার উদ্দেশ্য আপনাকে সমালোচনা করা নয় বরং এমন একটি পদ্ধতির অফার দেওয়া ছিল যা কোনও কোড নয়, কেবল একটি একক যুক্তি পরিবর্তন করে সহজেই তিনটির বেশি মাত্রায় সাধারণীকরণ করে। আপনি যেটা লিখেছেন তার চেয়ে কেন স্বচ্ছ তা আমার কাছে স্পষ্ট নয় তবে আমি অবশ্যই সে সম্পর্কে তর্ক করতে চাই না। চিয়ার্স।
ম্যাক্রো

0

ইতিমধ্যে নিখুঁত উত্তর দেওয়া হয়েছে, সুতরাং যারা পাইথনে এটি অর্জন করতে চান তাদের জন্য, এখানে আমার সমাধান:

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

mu = [0, 10, 3]
sigma = [1, 1, 1]
p_i = [0.3, 0.5, 0.2]
n = 10000

x = []
for i in range(n):
    z_i = np.argmax(np.random.multinomial(1, p_i))
    x_i = np.random.normal(mu[z_i], sigma[z_i])
    x.append(x_i)

def univariate_normal(x, mean, variance):
    """pdf of the univariate normal distribution."""
    return ((1. / np.sqrt(2 * np.pi * variance)) * 
            np.exp(-(x - mean)**2 / (2 * variance)))

a = np.arange(-7, 18, 0.01)
y = p_i[0] * univariate_normal(a, mean=mu[0], variance=sigma[0]**2) + p_i[1] * univariate_normal(a, mean=mu[1], variance=sigma[0]**2)+ p_i[2] * univariate_normal(a, mean=mu[2], variance=sigma[0]**2)

fig, ax = plt.subplots(figsize=(8, 4))

ax.hist(x, bins=100, density=True)
ax.plot(a, y)

এখানে চিত্র বর্ণনা লিখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.