2015-07-12 10 views
6

cách số lượng ổn định nhất tính là gì?Làm cách nào để triển khai logaddexp có trọng số ổn định?</p> <pre><code>log[(wx * exp(x) + wy * exp_y)/(wx + wy)] </code></pre> <p>nơi các trọng <code>wx, wy > 0</code>:

Nếu không có trọng lượng, chức năng này là logaddexp và có thể được thực hiện bằng Python với NumPy như:

tmp = x - y 
return np.where(tmp > 0, 
       x + np.log1p(np.exp(-tmp)), 
       y + np.log1p(np.exp(tmp))) 

Làm thế nào tôi nên khái quát này lên phiên bản trọng?

Trả lời

4

Bạn có thể sử dụng bản gốc logaddexp chức năng cho như vậy, mục đích, nếu bạn viết lại biểu thức trọng như,

new logadd expression

này tương đương với,

logaddexp(x + log(w_x), y + log(w_y)) - log(w_x + w_y) 

mà nên càng số lượng ổn định như thực hiện logaddexp gốc.

Lưu ý: tôi đề cập đến các numpy.logaddexp chức năng mà mất trong xy, không xexp_y, như bạn đề cập trong câu hỏi.

+0

Hình như nó có lẽ là tốt hơn so với những gì tôi đã làm, mà tôi sẽ bổ sung thêm như một câu trả lời để so sánh. –

+1

Đối với bất cứ ai đọc, tôi đã thử nghiệm điều này bằng cách sử dụng thư viện chính xác tùy ý 'mpmath' và thấy rằng nó tốt hơn nhiều so với giải pháp của tôi. –

+0

@NeilG Vâng, tôi cho rằng không có vấn đề làm thế nào bạn viết lại nó, bạn vẫn sẽ mất trong chính xác/tràn với nổi 64 bit vv, khi tham gia một số mũ lớn và tính toán đăng nhập trở lại. 'mpmath' dường như là một lựa chọn tốt ở đây, mặc dù nó sẽ chậm hơn. – rth

1
def weighted_logaddexp(x, wx, y, wy): 
    # Returns: 
    # log[(wx * exp(x) + wy * exp_y)/(wx + wy)] 
    # = log(wx/(wx+wy)) + x + log(1 + exp(y - x + log(wy)-log(wx))) 
    # = log1p(-wy/(wx+wy)) + x + log1p((wy exp_y)/(wx exp(x))) 
    if wx == 0.0: 
     return y 
    if wy == 0.0: 
     return x 
    total_w = wx + wy 
    first_term = np.where(wx > wy, 
          np.log1p(-wy/total_w), 
          np.log1p(-wx/total_w)) 
    exp_x = np.exp(x) 
    exp_y = np.exp(y) 
    wx_exp_x = wx * exp_x 
    wy_exp_y = wy * exp_y 
    return np.where(wy_exp_y < wx_exp_x, 
        x + np.log1p(wy_exp_y/wx_exp_x), 
        y + np.log1p(wx_exp_x/wy_exp_y)) + first_term 

Đây là cách tôi đã so sánh hai giải pháp:

import math 
import numpy as np 
import mpmath as mp 
from tools.numpy import weighted_logaddexp 

def average_error(ideal_function, test_function, n_args): 
    x_y = [np.linspace(0.1, 3, 20) for _ in range(n_args)] 
    xs_ys = np.meshgrid(*x_y) 

    def e(*args): 
     return ideal_function(*args) - test_function(*args) 
    e = np.frompyfunc(e, n_args, 1) 
    error = e(*xs_ys) ** 2 
    return np.mean(error) 


def ideal_function(x, wx, y, wy): 
    return mp.log((mp.exp(x) * wx + mp.exp(y) * wy)/mp.fadd(wx, wy)) 

def test_function(x, wx, y, wy): 
    return np.logaddexp(x + math.log(wx), y + math.log(wy)) - math.log(wx + wy) 

mp.prec = 100 
print(average_error(ideal_function, weighted_logaddexp, 4)) 
print(average_error(ideal_function, test_function, 4)) 
Các vấn đề liên quan