6.17. ตัวแก้สมการและตัวเลขสุ่ม#

เมื่อฟังก์ชันที่ต้องการศึกษาถูกกำหนดโดยโค้ด Python แทนที่จะเป็นบัฟเฟอร์ของตัวอย่าง กลุ่มเครื่องมืออีกประเภทหนึ่งจะเหมาะสมกว่า ได้แก่ รากของฟังก์ชันอยู่ที่ไหน ค่าต่ำสุดอยู่ที่ไหน ค่าอินทิกรัลในช่วงที่กำหนดเป็นเท่าไร โมดูลย่อย scipy.integrate และ scipy.optimize ครอบคลุมงานดังกล่าว แต่ละอัลกอริทึมเรียกกลับไปยังฟังก์ชัน Python ที่ผู้ใช้ระบุ ดังนั้นต้นทุนต่อรอบการทำงานจึงสูงกว่าการลดขนาดบัฟเฟอร์ ความสะดวกอยู่ที่ไม่ต้องเขียนตัวแก้สมการเอง

โมดูลย่อย scipy.special ครอบคลุมฟังก์ชันพิเศษทางสถิติ (ฟังก์ชันความผิดพลาด แกมมา) ที่ปรากฏเมื่อคำนวณ ฟังก์ชันการแจกแจงแบบสะสม (CDF ความน่าจะเป็นที่ตัวอย่างมีค่าไม่เกินค่าที่กำหนด) หรือ ฟังก์ชันความหนาแน่นของความน่าจะเป็น (PDF ความน่าจะเป็นสัมพัทธ์ที่ค่าที่กำหนด) numpy.random ครอบคลุมตัวสร้างตัวเลขสุ่มเทียมสำหรับการ dithering การจำลอง และข้อมูลทดสอบสังเคราะห์

6.17.1. การอินทิเกรตเชิงตัวเลขของ callable#

เมื่อ integrand เป็นฟังก์ชัน Python แทนที่จะเป็นบัฟเฟอร์ของตัวอย่าง scipy.integrate เปิดเผยอัลกอริทึม quadrature สี่แบบ:

  • quad() -- Gauss-Kronrod แบบปรับตัว ค่าเริ่มต้นที่ถูกต้องสำหรับ integrand ที่เรียบ คืนค่า (value, error)

  • romberg() -- Romberg / Newton-Cotes แบบคลาสสิก คืนค่า float เดี่ยว เลิกใช้งานต้นทาง รวมไว้เพื่อความเข้ากันได้

  • simpson() -- กฎ Simpson แบบปรับตัว คืนค่า float เดี่ยว

  • tanhsinh() -- quadrature แบบ double-exponential ใช้เมื่อ integrand มีจุดเอกฐานที่ปลายหรือขีดจำกัดอนันต์ คืนค่า (value, error)

Gaussian integral ที่คำนวณด้วยกฎ double-exponential (tanhsinh):

from math import exp
from math import pi
from math import sqrt
from ulab import numpy as np
from ulab import scipy as sp

f = lambda x: exp(-x * x)
value, err = sp.integrate.tanhsinh(f, -np.inf, np.inf)
print("approx:", value, "   exact:", sqrt(pi))

ผลลัพธ์:

approx: 1.7724538...   exact: 1.7724538...

6.17.2. การหารากและการหาค่าต่ำสุด#

scipy.optimize ครอบคลุมตัวแก้สมการตัวแปรเดียวแบบคลาสสิกสามตัว แต่ละรอบการทำงานจะเรียกกลับไปยังฟังก์ชัน Python ที่ผู้ใช้ระบุ ดังนั้นความเร็วที่เพิ่มขึ้นเมื่อเทียบกับตัวแก้สมการ Python แบบบริสุทธิ์จึงน้อยมาก (ประมาณ 2 เท่า) ความสะดวกอยู่ที่ไม่ต้องเขียนตัวแก้สมการเอง

  • bisect() -- หารากของ f บน [a, b] โดยการแบ่งช่วงครึ่ง f(a) และ f(b) ต้องมีเครื่องหมายตรงข้ามกัน:

    def f(x):
        return x * x - 1
    
    sp.optimize.bisect(f, 0, 4)        # ~1.0
    
  • newton() -- หารากโดยใช้การวนซ้ำ secant / Newton-Raphson:

    def f(x):
        return x * x * x - 2.0
    
    sp.optimize.newton(f, 3., tol=0.001, rtol=0.01)
    # ~1.260
    
  • fmin() -- หาค่าต่ำสุดท้องถิ่นโดยใช้วิธี downhill-simplex (Nelder-Mead):

    def f(x):
        return (x - 1) ** 2 - 1
    
    sp.optimize.fmin(f, 3.0)           # ~1.0
    

ขอบเขตตัวแปรเดียวเพียงพอสำหรับการเพิ่มประสิทธิภาพส่วนใหญ่ทางฝั่งกล้อง เช่น ค่าคงที่การสอบเทียบของเซนเซอร์ ค่าเกนที่เพิ่มการวัดค่าคอนทราสต์ให้สูงสุด ค่าขีดแบ่งที่ทำให้ฮิสโตแกรมมี bimodality ชัดเจนที่สุด สำหรับปัญหาหลายตัวแปร คำตอบที่ถูกต้องโดยทั่วไปคือการกำหนดปัญหาใหม่เป็นการแก้สมการพีชคณิตเชิงเส้นขนาดเล็กแทนที่จะใช้ตัวหาค่าเหมาะสมที่ไม่เชิงเส้นทั่วไป

6.17.3. ฟังก์ชันพิเศษ#

scipy.special เปิดเผยฟังก์ชันทางสถิติและความน่าจะเป็นจำนวนหนึ่งที่ทำงานเหมือนฟังก์ชันสากล โดยรับ scalar, iterable หรือ ndarray และคืนค่า ndarray แบบ float:

x = np.linspace(0, 4, num=8)

sp.special.erf(x)         # error function
sp.special.erfc(x)        # complementary error function
sp.special.gamma(x + 1)   # gamma function
sp.special.gammaln(x + 1) # log-gamma function

ฟังก์ชันความผิดพลาดและส่วนเสริมปรากฏใน CDF ของการแจกแจง Gaussian ซึ่งเป็นแอปพลิเคชันที่เหมาะสำหรับการแปลงระหว่าง z-score ที่วัดได้กับความน่าจะเป็น หรือสำหรับการคำนวณ tail integral ของการแจกแจงปกติ ฟังก์ชัน gamma และ log-gamma ปรากฏในการคำนวณ beta / chi-squared / student-t โดย gammaln เป็นรูปแบบที่มีความเสถียรเชิงตัวเลขสำหรับอาร์กิวเมนต์ขนาดใหญ่ที่ gamma เองจะล้นค่า

6.17.4. ตัวเลขสุ่ม#

numpy.random ให้คลาส Generator ที่ดึงตัวอย่างจากการแจกแจงทั่วไป ตัวสร้างมีสถานะ: แต่ละการเรียกจะก้าวหน้าสถานะภายใน ดังนั้นการเรียกต่อเนื่องจะคืนค่าตัวอย่างที่เป็นอิสระ:

from ulab import numpy as np

rng = np.random.Generator(seed=42)

rng.random(size=5)             # 5 uniform [0.0, 1.0) samples
rng.uniform(low=-1.0, high=1.0, size=10)
rng.normal(loc=0.0, scale=1.0, size=(2, 4))

ประเภทข้อมูลเอาต์พุตจะเป็น float เสมอ size= รับจำนวนเต็ม (เอาต์พุต 1 มิติ) หรือ tuple (เอาต์พุต n มิติ) เมื่อไม่ระบุ จะคืนค่า Python float เดี่ยว

ตัวสร้างเหมาะสำหรับการจำลอง การ dithering ข้อมูลทดสอบสังเคราะห์ และแอปพลิเคชันอื่น ๆ ที่ไม่ต้องการความแข็งแกร่งในระดับ cryptographic ไม่ เหมาะสำหรับคีย์หรือ token ให้ใช้แหล่งสุ่มของระบบผ่าน os สำหรับสิ่งเหล่านั้น

6.17.5. ความพร้อมใช้งานในเวลาสร้าง#

ว่าแต่ละโมดูลย่อยมีอยู่จริงหรือไม่ขึ้นอยู่กับวิธีที่สร้างกล้อง scipy.optimize และ scipy.special ไม่ได้เปิดใช้งานบนกล้องทุกตัว การเรียกฟังก์ชันที่กล้องไม่รวมไว้จะทำให้เกิด AttributeError dir(sp), dir(sp.optimize), dir(np.random) และคำสั่งที่คล้ายกันจะรายงานสิ่งที่มีอยู่บนกล้องที่กำหนดเป้าหมาย