মেশিনের নির্ভুলতার চেয়ে পার্থক্যটি ছোট কিনা তা যাচাই করার সঠিক / মানক উপায় কী?


36

আমি প্রায়শই এমন পরিস্থিতিতে পড়েছি যেখানে প্রাপ্ত পার্থক্যটি মেশিনের নির্ভুলতার চেয়ে উপরে কিনা তা পরীক্ষা করা দরকার। এই উদ্দেশ্য আর একটি সহজ পরিবর্তনশীল হয়েছে মত মনে হয়: .Machine$double.eps। তবে আমি যখন এই মানটি ব্যবহারের দিকনির্দেশগুলির জন্য আর উত্স কোডটিতে ফিরে যাই তখন আমি একাধিক বিভিন্ন নিদর্শন দেখতে পাই।

উদাহরণ

এখানে statsগ্রন্থাগার থেকে কয়েকটি উদাহরণ দেওয়া হয়েছে :

t.test.R

if(stderr < 10 *.Machine$double.eps * abs(mx))

chisq.test.R

if(abs(sum(p)-1) > sqrt(.Machine$double.eps))

integrate.R

rel.tol < max(50*.Machine$double.eps, 0.5e-28)

lm.influence.R

e[abs(e) < 100 * .Machine$double.eps * median(abs(e))] <- 0

princomp.R

if (any(ev[neg] < - 9 * .Machine$double.eps * ev[1L]))

প্রভৃতি

প্রশ্নাবলি

  1. কিভাবে এক সব পিছনে যারা বিভিন্ন যুক্তি বুঝতে পারেন 10 *, 100 *, 50 *এবং sqrt()সংশোধনকারীদের?
  2. .Machine$double.epsনির্ভুলতার কারণে পার্থক্য সামঞ্জস্য করার জন্য ব্যবহারের বিষয়ে গাইডলাইন রয়েছে ?



6
সুতরাং, উভয় পোস্টই সিদ্ধান্ত নিয়েছে যে "যুক্তিসঙ্গত যুক্তিসঙ্গত ডিগ্রি" আপনার আবেদনের উপর নির্ভর করে। কেস স্টাডি হিসাবে, আপনি আর-ডেভেল এ এই পোস্টটি পরীক্ষা করতে পারেন ; "আহা! সংখ্যাগুলি যখন ডাবল ডিজিটের হয় তখন এতটা 100 গুণ মেশিন যথার্থ হয় না।" (পিটার ডালগার্ড, আর কোর দলের সদস্য)
হেনরিক

1
@ কারোলিসকনসেভিয়াস, আমি মনে করি এটি এত সহজ নয়। এটি ভাসমান পয়েন্ট গণিতে উপস্থিত সাধারণ ত্রুটিগুলির সাথে সম্পর্কিত এবং আপনি তাদের উপর কতগুলি ক্রিয়াকলাপ চালান। আপনি যদি কেবল ভাসমান পয়েন্ট সংখ্যার সাথে তুলনা করেন তবে ব্যবহার করুন double.eps। যদি আপনি কোনও ফ্লোটিং পয়েন্ট নম্বরে বেশ কয়েকটি ক্রিয়াকলাপ সম্পাদন করে থাকেন তবে আপনার ত্রুটি সহনশীলতাটিও সামঞ্জস্য করা উচিত। এজন্য all.equal আপনাকে একটি toleranceযুক্তি দেয় ।
জোসেফ উড

1
আর এর পরবর্তী কার্যকারিতা বাস্তবায়নের দিকেও একবার নজর রাখুন যা আপনাকে পরবর্তী বৃহত্তর দ্বিগুণ সংখ্যা দেবে।
GKi

উত্তর:


4

এর জন্য মেশিনের নির্ভুলতা doubleতার বর্তমান মানের উপর নির্ভর করে। .Machine$double.epsমানগুলি 1 হলে নির্ভুলতা দেয় আপনি nextAfterঅন্যান্য ক্রিয়াকলাপের জন্য মেশিনের নির্ভুলতা পেতে সি ফাংশনটি ব্যবহার করতে পারেন ।

library(Rcpp)
cppFunction("double getPrec(double x) {
  return nextafter(x, std::numeric_limits<double>::infinity()) - x;}")

(pr <- getPrec(1))
#[1] 2.220446e-16
1 + pr == 1
#[1] FALSE
1 + pr/2 == 1
#[1] TRUE
1 + (pr/2 + getPrec(pr/2)) == 1
#[1] FALSE
1 + pr/2 + pr/2 == 1
#[1] TRUE
pr/2 + pr/2 + 1 == 1
#[1] FALSE

মানটির aসাথে মান যুক্ত করা যখন তার অর্ধেক মেশিন যথার্থ হয় তখন bপরিবর্তন হবে না মেশিনের নির্ভুলতার চেয়ে পার্থক্যটি স্মার্ট কিনা তা পরীক্ষা করা হচ্ছে । সংশোধকরা সাধারণ ক্ষেত্রে বিবেচনা করতে পারে যে কতবার সংযোজন কোনও পরিবর্তন প্রদর্শন করে না।ba<= <

ইন আর মেশিন স্পষ্টতা সঙ্গে আনুমানিক করা যেতে পারে:

getPrecR <- function(x) {
  y <- log2(pmax(.Machine$double.xmin, abs(x)))
  ifelse(x < 0 & floor(y) == y, 2^(y-1), 2^floor(y)) * .Machine$double.eps
}
getPrecR(1)
#[1] 2.220446e-16

প্রতিটি doubleমান একটি ব্যাপ্তি উপস্থাপন করে। একটি সাধারণ সংযোজনের জন্য, ফলাফলের পরিসীমা প্রতিটি সমন্ডের পুনরায় প্রয়োগ এবং তাদের যোগফলের ব্যাপ্তির উপর নির্ভর করে।

library(Rcpp)
cppFunction("std::vector<double> getRange(double x) {return std::vector<double>{
   (nextafter(x, -std::numeric_limits<double>::infinity()) - x)/2.
 , (nextafter(x, std::numeric_limits<double>::infinity()) - x)/2.};}")

x <- 2^54 - 2
getRange(x)
#[1] -1  1
y <- 4.1
getRange(y)
#[1] -4.440892e-16  4.440892e-16
z <- x + y
getRange(z)
#[1] -2  2
z - x - y #Should be 0
#[1] 1.9

2^54 - 2.9 + 4.1 - (2^54 + 5.9) #Should be -4.7
#[1] 0
2^54 - 2.9 == 2^54 - 2      #Gain 0.9
2^54 - 2 + 4.1 == 2^54 + 4  #Gain 1.9
2^54 + 5.9 == 2^54 + 4      #Gain 1.9

উচ্চতর নির্ভুলতা জন্য Rmpfrব্যবহার করা যেতে পারে।

library(Rmpfr)
mpfr("2", 1024L)^54 - 2.9 + 4.1 - (mpfr("2", 1024L)^54 + 5.9)
#[1] -4.700000000000000621724893790087662637233734130859375

যদি এটি পূর্ণসংখ্যায় রূপান্তরিত gmpহতে পারে তবে এটি ব্যবহার করা যেতে পারে (আরএমপিএফআরে যা রয়েছে)।

library(gmp)
as.bigz("2")^54 * 10 - 29 + 41 - (as.bigz("2")^54 * 10 + 59)
#[1] -47

অনেক ধন্যবাদ. আমি মনে করি এটি অনেক ভাল উত্তর। এটি অনেকগুলি পয়েন্ট সুন্দরভাবে বর্ণনা করেছে। আমার কাছে এখনও কিছুটা অস্পষ্ট যা কেবল তা হল - কেউ নিজের নিজের উপর পরিবর্তনকারী (যেমন * 9 ইত্যাদি) নিয়ে আসতে পারে? এবং যদি তাই হয় ...
করোলিস কনসেভিয়াস

আমি মনে করি এই পরিমার্জনকারী পরিসংখ্যানের তাত্পর্য স্তরের মতো এবং একটি সঠিক তুলনা প্রত্যাখ্যান করার জন্য আপনি নির্বাচিত ঝুঁকির সংমিশ্রণে পরিচালনা করেছেন এমন ক্রিয়াকলাপ বৃদ্ধি পাবে।
GKi

3

মেশিন.এপ্সের সংজ্ঞা: এটি সর্বনিম্ন মান  eps যার  1+eps জন্য নয় 1

থাম্বের একটি নিয়ম হিসাবে (বেস 2 সহ একটি ভাসমান পয়েন্ট উপস্থাপনা ধরে নেওয়া):
এটি epsপরিসীমা 1 .. 2 এর মধ্যে, 2 ব্যাপ্তির জন্য পার্থক্য তৈরি করে
.. 4 যথার্থতাটি2*eps
এবং আরও অনেক কিছু।

দুর্ভাগ্যক্রমে, এখানে থাম্বের কোনও ভাল নিয়ম নেই। এটি সম্পূর্ণ আপনার প্রোগ্রামের প্রয়োজনের দ্বারা নির্ধারিত।

আর এ আমরা আনুমানিক সাম্যতা পরীক্ষা করার জন্য বিল্ট হিসাবে একটি all.equal আছে। সুতরাং আপনি সম্ভবত কিছু ব্যবহার করতে পারে (x<y) | all.equal(x,y)

i <- 0.1
 i <- i + 0.05
 i
if(isTRUE(all.equal(i, .15))) { #code was getting sloppy &went to multiple lines
    cat("i equals 0.15\n") 
} else {
    cat("i does not equal 0.15\n")
}
#i equals 0.15

গুগল মকটিতে ডাবল স্পষ্টতা তুলনার জন্য বেশ কয়েকটি ভাসমান পয়েন্ট ম্যাথার রয়েছে DoubleEqএবং এর মধ্যে রয়েছে DoubleNear। আপনি এগুলিকে এই জাতীয় অ্যারে ব্যবহার করতে পারেন:

ASSERT_THAT(vec, ElementsAre(DoubleEq(0.1), DoubleEq(0.2)));

হালনাগাদ:

সংখ্যাসূচক রেসিপিগুলি একতরফা পার্থক্য ভাগফল ব্যবহার করে তা প্রদর্শনের জন্য একটি উপকরণ সরবরাহ করে, sqrt ডেরিভেটিভসের সীমাবদ্ধ পার্থক্য আনুমানিকতার জন্য ধাপের আকারের একটি ভাল পছন্দ এটি প্রমাণ করার জন্য একটি উপকরণ সরবরাহ করে।

উইকিপিডিয়া নিবন্ধ সাইট সংখ্যা সংক্রান্ত রেসিপি, তৃতীয় সংস্করণ, বিভাগ 5.7, যা পৃষ্ঠাগুলি 229-230 (সীমিত সংখ্যক পৃষ্ঠাগুলির http://www.nrbook.com/empanel/ এ উপলব্ধ )।

all.equal(target, current,
           tolerance = .Machine$double.eps ^ 0.5, scale = NULL,
           ..., check.attributes = TRUE)

এই আইইইই ফ্লোটিং পয়েন্ট গাণিতিক কম্পিউটার পাটিগণিতের একটি সুপরিচিত সীমাবদ্ধতা এবং এটি বেশ কয়েকটি জায়গায় আলোচিত হয়:

dplyr::near()ভাসমান পয়েন্ট সংখ্যার দুটি ভেক্টর সমান হলে পরীক্ষার জন্য আরেকটি বিকল্প।

ফাংশনটিতে সহনশীলতার প্যারামিটারটি অন্তর্নির্মিত রয়েছে: tol = .Machine$double.eps^0.5এটি সামঞ্জস্য করা যায়। ডিফল্ট পরামিতি ডিফল্ট হিসাবে একই all.equal()


2
উত্তরের জন্য ধন্যবাদ. এই মুহুর্তে আমি মনে করি এটি গ্রহণযোগ্য উত্তর হিসাবে খুব ন্যূনতম। পোস্ট থেকে এটি দুটি প্রধান প্রশ্নের সমাধান বলে মনে হচ্ছে না। উদাহরণস্বরূপ এটি "আপনার প্রোগ্রামের প্রয়োজনের দ্বারা এটি নির্ধারিত হয়" উল্লেখ করে। এই বিবৃতিটির একটি বা দুটি উদাহরণ দেখানো ভাল লাগবে - সম্ভবত একটি ছোট প্রোগ্রাম এবং এর দ্বারা কীভাবে সহনশীলতা নির্ধারণ করা যেতে পারে। সম্ভবত উল্লিখিত আর স্ক্রিপ্টগুলির মধ্যে একটি ব্যবহার করছে। এছাড়াও all.equal()এটি নিজের ধৃষ্টতা নেই ডিফল্ট সহনশীলতা হিসাবে করেনি sqrt(double.eps)কেন এটা ডিফল্ট - এটি থাম্ব ব্যবহার করার জন্য একটি ভাল নিয়ম sqrt()?
ক্যারোলিস কনসেভিয়াস

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

সমস্ত প্রচেষ্টার জন্য আন্তরিক +1। তবে বর্তমান অবস্থায় আমি এখনও উত্তরটি গ্রহণ করতে পারি না। এটি অনেকগুলি রেফারেন্স সহ কিছুটা প্রসারিত বলে মনে হচ্ছে, তবে 2 টি পোস্ট করা প্রশ্নের যথাযথ উত্তরের পরিপ্রেক্ষিতে: 1) আর stats::উত্সে 100x, 50x, ইত্যাদি সংশোধক কীভাবে বুঝতে হবে এবং 2) গাইডলাইনগুলি কী; উত্তরটি বেশ পাতলা। একমাত্র প্রযোজ্য বাক্যটি বোধহয় "সংখ্যার রেসিপিগুলি" থেকে বর্গফুট () ভাল ডিফল্ট হওয়া সম্পর্কে উল্লেখ করা হয়েছে, যা সত্যই বিন্দুতে রয়েছে বলে আমি মনে করি। অথবা আমি এখানে কিছু মিস করছি।
ক্যারোলিস কনসেভিয়াস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.