यह जाँचने के लिए सही / मानक तरीका है कि क्या अंतर मशीन की शुद्धता से छोटा है?


36

मैं अक्सर उन स्थितियों में समाप्त होता हूं, जहां यह जांचना आवश्यक है कि प्राप्त अंतर मशीन परिशुद्धता से ऊपर है या नहीं। इस उद्देश्य के लिए लगता है आर के पास एक आसान चर है .Machine$double.eps:। हालाँकि जब मैं इस मूल्य का उपयोग करने के दिशानिर्देशों के लिए R स्रोत कोड की ओर मुड़ता हूँ तो मुझे कई अलग-अलग पैटर्न दिखाई देते हैं।

उदाहरण

यहाँ 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
@ KarolisKoncevičius, मुझे नहीं लगता कि यह इतना आसान है। यह फ़्लोटिंग पॉइंट गणित में मौजूद सामान्य त्रुटियों और उन पर आपके द्वारा निष्पादित किए गए कितने ऑपरेशनों के साथ करना है। यदि आप फ्लोटिंग पॉइंट नंबरों की तुलना कर रहे हैं, तो उपयोग करें double.eps। यदि आप एक अस्थायी बिंदु संख्या पर कई ऑपरेशन कर रहे हैं, तो आपकी त्रुटि सहिष्णुता भी समायोजित होनी चाहिए। यही कारण है कि सभी। असमान आपको एक toleranceतर्क देता है।
जोसेफ वुड

1
आर में अगली कार्यक्षमता के कार्यान्वयन पर भी एक नज़र डालें जो आपको अगले बड़े दोहरे नंबर देगा।
जीके

जवाबों:


4

मशीन की शुद्धता doubleइसके वर्तमान मूल्य पर निर्भर करती है। .Machine$double.epsजब मान 1 होता है तो सटीकता देता है। nextAfterमशीन फ़ंक्शन को अन्य मानों के लिए प्राप्त करने के लिए आप C फ़ंक्शन का उपयोग कर सकते हैं ।

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नहीं बदलेगा bजब aहै <= यह मशीन परिशुद्धता के आधे। यह जाँच कर कि क्या अंतर मशीन की सटीकता की तुलना में स्मेलर है< । संशोधक विशिष्ट मामलों पर विचार कर सकते हैं कि कितनी बार इसके अलावा बदलाव नहीं दिखा।

में आर मशीन परिशुद्धता के साथ अनुमान लगाया जा सकता:

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जा सकता है (जो Rmpfr में है)।

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

Google मॉक में दोहरी सटीक तुलना के लिए कई फ्लोटिंग पॉइंट मैचर्स हैं , जिनमें शामिल हैं 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)

ये IEEE फ़्लोटिंग पॉइंट अंकगणित कंप्यूटर अंकगणित की एक प्रसिद्ध सीमा है और कई स्थानों पर चर्चा की जाती है:

dplyr::near()परीक्षण के लिए एक और विकल्प है यदि फ्लोटिंग पॉइंट संख्या के दो वैक्टर बराबर हैं।

फ़ंक्शन में एक सहिष्णुता पैरामीटर है: tol = .Machine$double.eps^0.5जिसे समायोजित किया जा सकता है। डिफ़ॉल्ट पैरामीटर के लिए डिफ़ॉल्ट के रूप में ही है all.equal()


2
जवाब देने के लिए धन्यवाद। फिलहाल मुझे लगता है कि स्वीकृत जवाब होना बहुत कम है। यह पोस्ट से दो मुख्य प्रश्नों को संबोधित नहीं करता है। उदाहरण के लिए यह बताता है कि "यह आपके कार्यक्रम की जरूरतों से निर्धारित होता है"। इस कथन के एक या दो उदाहरण दिखाना अच्छा होगा - शायद एक छोटा कार्यक्रम और उसके द्वारा सहिष्णुता कैसे निर्धारित की जा सकती है। हो सकता है कि उल्लेखित R लिपियों में से एक का उपयोग कर रहे हों। इसके अलावा all.equal()यह स्वयं की डिफ़ॉल्ट सहिष्णुता के रूप में धारणा है sqrt(double.eps)- यह डिफ़ॉल्ट क्यों है? यह उपयोग करने के लिए अंगूठे का एक अच्छा नियम है sqrt()?
कारोलिस कोनसेविसियस

यहाँ कोड R का उपयोग eps की गणना करने के लिए किया जाता है (अपने कार्यक्रम में निकाला जाता है)। इसके अलावा मैंने कई चर्चा बिंदुओं के साथ उत्तर को अपडेट किया है जो मैं पहले भी गया था। आशा है कि वही आपको बेहतर समझने में मदद करेगा।
श्रीराम नायर

सभी प्रयासों के लिए एक ईमानदार +1। लेकिन वर्तमान स्थिति में मैं अभी भी उत्तर को स्वीकार नहीं कर सकता। यह बहुत सारे संदर्भों के साथ थोड़ा बाहर तक पहुँचने वाला लगता है, लेकिन 2 पोस्ट किए गए प्रश्नों के वास्तविक उत्तर के संदर्भ में: 1) आर stats::स्रोत में 100x, 50x, आदि संशोधक कैसे समझें , और 2) दिशानिर्देश क्या हैं; जवाब काफी पतला है। केवल लागू वाक्य sqrt () के बारे में "न्यूमेरिकल व्यंजनों" से संदर्भ प्रतीत होता है कि यह एक अच्छा डिफ़ॉल्ट है, जो वास्तव में बिंदु पर है, मुझे लगता है। या शायद मुझे यहाँ कुछ याद आ रहा है।
करोलिस कोनसेविसियस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.