เมื่อใดควรใช้ log1p และ expm1


30

ฉันมีคำถามง่ายๆที่ยากสำหรับ Google (นอกเหนือจากสิ่งที่บัญญัติไว้ในสิ่งที่นักวิทยาศาสตร์คอมพิวเตอร์ทุกคนควรรู้เกี่ยวกับกระดาษคำนวณเลขทศนิยม )

เมื่อใดควรใช้ฟังก์ชันเช่นlog1pหรือexpm1ใช้แทนlogและexp? เมื่อใดที่ไม่ควรใช้ การใช้งานที่แตกต่างกันของฟังก์ชั่นเหล่านั้นแตกต่างกันอย่างไรในแง่ของการใช้งาน?


2
ยินดีต้อนรับสู่ Scicomp.SE! นั่นเป็นคำถามที่สมเหตุสมผล แต่จะตอบได้ง่ายกว่าถ้าคุณอธิบายเล็กน้อยที่ log1pคุณอ้างถึง (โดยเฉพาะอย่างยิ่งวิธีการนำไปปฏิบัติ
Christian Clason

4
สำหรับอาร์กิวเมนต์ที่มีมูลค่าจริงควรใช้log1p และ expm1 ( x )เมื่อxมีขนาดเล็กเช่นเมื่อ1 + x = 1ในความแม่นยำของจุดลอยตัว ดูเช่นdocs.scipy.org/doc/numpy/reference/generated/numpy.expm1.htmlและdocs.scipy.org/doc/numpy/reference/generated/numpy.log1p.html (x)(x)x1+x=1
GoHokies

@ ChristianianClason ขอบคุณฉันหมายถึง C ++ std หรือ R เป็นส่วนใหญ่ แต่ในขณะที่คุณถามฉันเริ่มคิดว่าการเรียนรู้เกี่ยวกับความแตกต่างในการใช้งานจะน่าสนใจมาก
ทิม

นี่คือตัวอย่าง: scicomp.stackexchange.com/questions/8371/…
Juan M. Bello-Rivas

1
@ user2186862 "เมื่อมีขนาดเล็ก" ถูกต้อง แต่ไม่เพียง "เมื่อ1 + x = 1ในความแม่นยำจุดลอย" (ซึ่งเกิดขึ้นสำหรับx 10 - 16ในเลขคณิตความแม่นยำสองเท่าปกติ) หน้าเอกสารที่คุณเชื่อมโยงแสดงว่ามีประโยชน์สำหรับx 10 - 10แล้ว x1+x=1x1016x1010
Federico Poloni

คำตอบ:


25

เราทุกคนรู้ว่า

exp(x)=n=0xnn!=1+x+12x2+
บอกเป็นนัยสำหรับ|x|1เรามีexp(x)1+xx ซึ่งหมายความว่าหากเราต้องประเมินค่าใน floating pointexp(x)1, สำหรับ|x|1ภัยพิบัติการยกเลิกสามารถเกิดขึ้นได้

สิ่งนี้สามารถแสดงให้เห็นได้อย่างง่ายดายในไพ ธ อน:

>>> from math import (exp, expm1)

>>> x = 1e-8
>>> exp(x) - 1
9.99999993922529e-09
>>> expm1(x)
1.0000000050000001e-08

>>> x = 1e-22
>>> exp(x) - 1
0.0
>>> expm1(x)
1e-22

ค่าที่แน่นอนคือ

exp(108)1=0.000000010000000050000000166666667083333334166666668exp(1022)1=0.000000000000000000000100000000000000000000005000000

โดยทั่วไปการดำเนินการ "ถูกต้อง" ของexpและexpm1ควรถูกต้องไม่เกิน 1ULP (เช่นหนึ่งหน่วยของสถานที่สุดท้าย) อย่างไรก็ตามเนื่องจากการบรรลุความแม่นยำนี้ส่งผลให้มีรหัส "ช้า" บางครั้งมีการใช้งานที่รวดเร็วและแม่นยำน้อยกว่า ตัวอย่างเช่นใน CUDA เรามีexpfและexpm1fที่fย่อมาจากอย่างรวดเร็ว ตามคู่มือการเขียนโปรแกรม CUDA C แอป D the expfมีข้อผิดพลาดของ 2ULP

หากคุณไม่สนใจเกี่ยวกับข้อผิดพลาดตามลำดับของ ULPS เพียงไม่กี่ครั้งการใช้งานฟังก์ชันเลขชี้กำลังต่างกันจะเท่ากัน แต่ระวังว่าข้อบกพร่องอาจถูกซ่อนอยู่ที่ไหนสักแห่ง ... (จำข้อผิดพลาด Pentium FDIV ได้ไหม)

ดังนั้นจึงสวยชัดเจนว่าexpm1ควรจะใช้ในการคำนวณexp(x)1สำหรับธุรกิจขนาดเล็กxxการใช้งานกับxทั่วไปนั้นไม่เป็นอันตรายเนื่องจากexpm1คาดว่าจะแม่นยำตลอดช่วงเต็มรูปแบบ:

>>> exp(200)-1 == exp(200) == expm1(200)
True

(ในตัวอย่างข้างต้น1มีค่าต่ำกว่า 1ULP ของexp(200)ดังนั้นทั้งสามนิพจน์จะคืนค่าหมายเลขทศนิยมเหมือนกันทุกประการ)

การสนทนาที่คล้ายกันมีไว้สำหรับฟังก์ชันผกผันlogและlog1pตั้งแต่log(1+x)xสำหรับ|x|1 1


1
คำตอบนี้มีอยู่ในความคิดเห็นของคำถาม OP แล้ว อย่างไรก็ตามฉันรู้สึกว่ามีประโยชน์ที่จะทำให้บัญชียาวขึ้น (แม้ว่าจะเป็นพื้นฐาน) เพียงเพื่อความชัดเจนเราหวังว่ามันจะมีประโยชน์สำหรับผู้อ่านบางคน
Stefano M

ตกลง แต่อย่างใดอย่างหนึ่งก็สามารถสรุป "เพื่อให้ฉันสามารถใช้ expm1 แทน exp" ...
ทิม

1
@ เวลาข้อสรุปของคุณผิด: คุณสามารถใช้expm1(x)แทนexp(x)-1ได้ตลอดเวลา แน่นอนexp(x) == exp(x) - 1ไม่ถือโดยทั่วไป
Stefano M

ตกลงนั่นชัดเจน และมีเกณฑ์การตัดใด ๆ ที่ชัดเจนสำหรับ ? x«1
ทิม

1
@ เวลาไม่มีเกณฑ์การตัดที่ชัดเจนและคำตอบนั้นขึ้นอยู่กับความแม่นยำของการใช้จุดลอยตัว (และปัญหาที่แก้ไข) ในขณะที่expm1(x)ควรจะถูกต้องกว่า 1ULP ทั้งช่วง , ความก้าวหน้า looses แม่นยำจากไม่กี่ ULP เมื่อx 1การสลายเสร็จสมบูรณ์เมื่อx < εที่εเป็นเครื่อง epsilon 0x1exp(x) - 1x1x<ϵϵ
Stefano M

1

หากต้องการขยายความแตกต่างระหว่างlogและlog1pอาจช่วยในการเรียกคืนกราฟหากลอการิทึม:

Logarithm

logx0ln(x)x0ln(x)ln(1e)=1ln(1e10)=10

ในทางกลับกันเช่น x วิธีการ 0, คุณค่าของ LN(x+1) วิธีการ 0จากทิศทางบวก ตัวอย่างเช่นLN(1+1อี)~0.31 และ LN(1+1อี10)~0.000045. ดังนั้นlog1pสร้างค่าบวกเท่านั้นและกำจัด 'อันตราย' ของตัวเลขติดลบจำนวนมาก ซึ่งโดยทั่วไปจะรับประกันการกระจายที่เป็นเนื้อเดียวกันมากขึ้นเมื่อชุดข้อมูลมีตัวเลขใกล้เคียงกับศูนย์

กล่าวโดยย่อถ้าชุดข้อมูลมีค่ามากกว่าทั้งหมด 1logปกติแล้วก็ไม่เป็นไร แต่ถ้าชุดข้อมูลมีตัวเลขอยู่ระหว่าง0 และ 1แล้วlog1pโดยปกติจะดีกว่า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.