বিপরীতমুখী রূপান্তর পরিবর্তে আহরনস এবং ডিয়েটার পদ্ধতি (1972) ব্যবহার করে কোনও ক্ষতিকারক র্যান্ডম জেনারেটরের সুবিধা কী কী?


11

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

আমি নিজেকে বুঝিয়েছি যে আহরনস-ডিয়েটার (এডি) পদ্ধতিটি সঠিক। তবুও, বিপরীত রূপান্তর (আইটি) পদ্ধতির তুলনায় তাদের পদ্ধতিটি ব্যবহার করার সুবিধা আমি দেখতে পাচ্ছি না। এডি কেবল আইটি-র চেয়ে বাস্তবায়ন করা জটিল নয়। গতি উপকারও হয় না বলে মনে হয়। ফলাফলগুলি অনুসরণ করে উভয় পদ্ধতি বেঞ্চমার্ক করার জন্য আমার আর কোডটি এখানে ।

invTrans <- function(n)
    -log(runif(n))
print("For the inverse transform:")
print(system.time(invTrans(1e8)))
print("For the Ahrens-Dieter algorithm:")
print(system.time(rexp(1e8)))

ফলাফল:

[1] "For the inverse transform:" 
user     system     elapsed
4.227    0.266      4.597 
[1] "For the Ahrens-Dieter algorithm:"
user     system     elapsed
4.919    0.265      5.213

দুটি পদ্ধতির কোডের তুলনা করে, এডি একটি ঘনিষ্ঠভাবে র্যান্ডম নম্বর পেতে কমপক্ষে দুটি অভিন্ন র্যান্ডম সংখ্যা ( সি ফাংশন সহ unif_rand()) আঁকেন । আইটিটির জন্য কেবল একটি অভিন্ন র্যান্ডম নম্বর প্রয়োজন। সম্ভবত আর কোর দলটি আইটি প্রয়োগের বিরুদ্ধে সিদ্ধান্ত নিয়েছিল কারণ এটি ধরে নিয়েছে যে লোগারিদম গ্রহণ করা আরও অভিন্ন র্যান্ডম সংখ্যার তুলনায় ধীর হতে পারে। আমি বুঝতে পারি লগারিদম নেওয়ার গতি মেশিন-নির্ভর হতে পারে তবে কমপক্ষে আমার পক্ষে বিপরীতটি সত্য। আইটি এর সংখ্যাগত নির্ভুলতার সাথে 0 তে লোগারিদমের এককত্বের সাথে সম্পর্কযুক্ত কিছু সমস্যা রয়েছে? তবে তারপরে, আর উত্স কোড sexp.cজানায় যে খ্রি বাস্তবায়ন কিছু সংখ্যাসূচক স্পষ্টতা হারায় কারণ সি কোডের নিম্নলিখিত অংশ অভিন্ন র্যান্ডম নম্বর থেকে নেতৃস্থানীয় বিট সরিয়ে ফেলা হবে তোমার দর্শন লগ করা

double u = unif_rand();
while(u <= 0. || u >= 1.) u = unif_rand();
for (;;) {
    u += u;
    if (u > 1.)
        break;
    a += q[0];
}
u -= 1.;

u পরবর্তীতে sexp.c এর অবশিষ্টাংশে অভিন্ন র্যান্ডম সংখ্যা হিসাবে পুনর্ব্যবহৃত হয় । এখনও পর্যন্ত, এটি প্রদর্শিত হবে

  • আইটি কোড করা সহজ,
  • এটি দ্রুত, এবং
  • আইটি এবং এডি উভয়ই সম্ভবত সংখ্যার যথার্থতা হারাবেন।

আমি সত্যিই প্রশংসা করব যদি কেউ ব্যাখ্যা করতে পারে যে কেন কেন এখনও AD এর জন্য একমাত্র উপলভ্য বিকল্প হিসাবে AD প্রয়োগ করে rexp()


4
এলোমেলো সংখ্যার জেনারেটর সহ, "কোডিং করা সহজ" যদি না আপনি এটি করছেন তবে সত্যই বিবেচনা করা হবে না! গতি এবং নির্ভুলতা কেবল দুটি বিবেচনা। (অভিন্ন জেনারেটরের জন্য, জেনারেটরের সময়কালও রয়েছে)) পুরানো দিনগুলিতে, AD দ্রুত ছিল। আমার লিনাক্স বাক্সে, AD আপনার invTrans ফাংশনটি প্রায় 1/2 এবং আমার ল্যাপটপে প্রায় 2/3 সময়ের মধ্যে চলে। আপনি আরও বিস্তৃত সময়ের জন্য মাইক্রোব্যাঙ্কমার্কটি ব্যবহার করতে চাইতে পারেন।
জবোম্যান

5
আমি পরামর্শ দেব যে আমরা এটি স্থানান্তর করব না। এটি আমার কাছে বিষয় মনে হচ্ছে।
অ্যামিবা

1
প্রদত্ত যে আমি কোনও একক rexp(n)দৃশ্যে ভাবতে পারছি না যাতে বাধা হয়ে দাঁড়াবে, গতির পার্থক্য পরিবর্তনের পক্ষে দৃ argument় যুক্তি নয় (কমপক্ষে আমার কাছে)। আমি সংখ্যার নির্ভুলতা সম্পর্কে আরও উদ্বিগ্ন হতে পারি, যদিও এটি আমার কাছে পরিষ্কার নয় যে কোনটি সংখ্যাগতভাবে নির্ভরযোগ্য হবে।
ক্লিফ এবি

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

1
@ আমেবা আমার যেতে হবে আমার প্রস্তাবিত নতুন শিরোনামটি বিশেষত ব্যাকরণগত, এবং সম্ভবত প্রশ্নের পাঠ্যের আরও কয়েকটি অংশ পরিবর্তনের সাথে করতে পারে তা নিশ্চিত নয়। তবে আমি আশা করি এটি কমপক্ষে বিষয়টিতে আরও স্পষ্টভাবে প্রকাশিত হবে এবং আমি মনে করি না যে এটি অকার্যকর হয় বা এর উত্তরের কোনও পরিবর্তন দরকার।
সিলভারফিশ

উত্তর:


9

আমার কম্পিউটারে (আমার ফরাসিকে ক্ষমা করুন!):

> print(system.time(rexp(1e8)))
utilisateur     système      écoulé 
      4.617       0.320       4.935 
> print(system.time(rexp(1e8)))
utilisateur     système      écoulé 
      4.589       2.045       6.629 
> print(system.time(-log(runif(1e8))))
utilisateur     système      écoulé 
      7.455       1.080       8.528 
> print(system.time(-log(runif(1e8))))
utilisateur     système      écoulé 
      9.140       1.489      10.623

বিপরীত রূপান্তর আরও খারাপ করে। তবে আপনার পরিবর্তনশীলতার জন্য নজর রাখা উচিত। হারের প্যারামিটারের পরিচয় দেওয়া বিপরীত রূপান্তরটির জন্য আরও বেশি পরিবর্তনশীলতার দিকে পরিচালিত করে:

> print(system.time(rexp(1e8,rate=.01)))
utilisateur     système      écoulé 
      4.594       0.456       5.047 
> print(system.time(rexp(1e8,rate=.01)))
utilisateur     système      écoulé 
      4.661       1.319       5.976 
> print(system.time(-log(runif(1e8))/.01))
utilisateur     système      écoulé 
     15.675       2.139      17.803 
> print(system.time(-log(runif(1e8))/.01))
utilisateur     système      écoulé 
      7.863       1.122       8.977 
> print(system.time(rexp(1e8,rate=101.01)))
utilisateur     système      écoulé 
      4.610       0.220       4.826 
> print(system.time(rexp(1e8,rate=101.01)))
utilisateur     système      écoulé 
      4.621       0.156       4.774 
> print(system.time(-log(runif(1e8))/101.01))
utilisateur     système      écoulé 
      7.858       0.965       8.819 > 
> print(system.time(-log(runif(1e8))/101.01))
utilisateur     système      écoulé 
     13.924       1.345      15.262 

এখানে ব্যবহার করে তুলনা করা হচ্ছে rbenchmark:

> benchmark(x=rexp(1e6,rate=101.01))
  elapsed user.self sys.self
  4.617     4.564    0.056
> benchmark(x=-log(runif(1e6))/101.01)
  elapsed user.self sys.self
  14.749   14.571    0.184
> benchmark(x=rgamma(1e6,shape=1,rate=101.01))
  elapsed user.self sys.self
  14.421   14.362    0.063
> benchmark(x=rexp(1e6,rate=.01))
  elapsed user.self sys.self
  9.414     9.281    0.136
> benchmark(x=-log(runif(1e6))/.01)
  elapsed user.self sys.self
  7.953     7.866    0.092
> benchmark(x=rgamma(1e6,shape=1,rate=.01))
  elapsed user.self sys.self
  26.69    26.649    0.056

মাইলেজ এখনও স্কেল উপর নির্ভর করে পরিবর্তিত হয়!


2
আমার ল্যাপটপে, সময়গুলি ওপির সাথে এতটা ঘনিষ্ঠ হয় যে আমার সন্দেহ হয় যে আমাদের একই মেশিন রয়েছে (বা কমপক্ষে একই প্রসেসর)। তবে আমি মনে করি যে এখানে আপনার বক্তব্যটি লক্ষ্য করা গতি সুবিধাটি প্ল্যাটফর্ম নির্ভর, এবং ন্যূনতম পার্থক্য দেওয়া, গতির ক্ষেত্রে একে অপরের পক্ষে সুস্পষ্ট সুবিধা নেই।
ক্লিফ এবি

4
আপনি সম্ভবত একটি microbenchmarkপরিবর্তে সঞ্চালন করতে পারেন ?
ফায়ারব্যাগ

2
rexp-log(runif())5.27±0.02Rlogrunif

7

এটি কেবলমাত্র "অ্যালগরিদম এলজি: (লোগারিদম পদ্ধতি)" বিভাগের অধীনে নিবন্ধটি উদ্ধৃত করছে:

X=ALOG(REGOL(IR))μμμu

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


6

স্রেফ এটি দিয়ে চলছে microbenchmark; আমার মেশিনে, আর এর নেটিভ পদ্ধতি অভিন্নভাবে দ্রুত:

library(microbenchmark)
microbenchmark(times = 10L,
               R_native = rexp(1e8),
               dir_inv = -log(runif(1e8)))
# Unit: seconds
#      expr      min       lq     mean   median       uq      max neval
#  R_native 3.643980 3.655015 3.687062 3.677351 3.699971 3.783529    10
#   dir_inv 5.780103 5.783707 5.888088 5.912384 5.946964 6.050098    10

λ=1

lambdas = seq(0, 10, length.out = 25L)[-1L]
png("~/Desktop/micro.png")
matplot(lambdas, 
        ts <- 
          t(sapply(lambdas, function(ll)
            print(microbenchmark(times = 50L,
                                 R_native = rexp(5e5, rate = ll),
                                 dir_inv = -log(runif(5e5))/ll),
                  unit = "relative")[ , "median"])),
        type = "l", lwd = 3L, xlab = expression(lambda),
        ylab = "Relative Timing", lty = 1L,
        col = c("black", "red"), las = 1L,
        main = paste0("Direct Computation of Exponential Variates\n",
                      "vs. R Native Generator (Ahrens-Dieter)"))
text(lambdas[1L], ts[1L, ], c("A-D", "Direct"), pos = 3L)
dev.off()

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

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