Dlaczego dodawanie prawdopodobieństw dziennika jest szybsze niż pomnożenie prawdopodobieństw?

21

Aby sformułować pytanie, w informatyce często chcemy obliczyć iloczyn kilku prawdopodobieństw:

P(A,B,C) = P(A) * P(B) * P(C)

Najprostszym podejściem jest po prostu pomnożenie tych liczb i właśnie to zamierzałem zrobić. Jednak mój szef powiedział, że lepiej jest dodać dziennik prawdopodobieństwa:

log(P(A,B,C)) = log(P(A)) + log(P(B)) + log(P(C))

Daje to prawdopodobieństwo dziennika, ale w razie potrzeby możemy je później uzyskać:

P(A,B,C) = e^log(P(A,B,C))

Dodawanie dziennika jest uważane za lepsze z dwóch powodów:

  1. Zapobiega „niedomiarowi”, przez co iloczyn prawdopodobieństwa jest tak mały, że zostaje zaokrąglony do zera. Może to często stanowić ryzyko, ponieważ prawdopodobieństwo jest często bardzo małe.
  2. Jest to szybsze, ponieważ wiele architektur komputerowych może wykonywać dodawanie szybciej niż mnożenie.

Moje pytanie dotyczy drugiej kwestii. Tak to widziałem, ale nie bierze ono pod uwagę dodatkowych kosztów uzyskania dziennika! Powinniśmy porównać „koszt dziennika + koszt dodania” do „kosztu pomnożenia”. Czy po uwzględnieniu tego jest jeszcze mniejszy?

Strona Wikipedii ( prawdopodobieństwo dziennika ) jest pod tym względem myląca, mówiąc: „Konwersja do postaci dziennika jest kosztowna, ale następuje tylko raz”. Nie rozumiem tego, ponieważ myślę, że musisz dodać dziennik każdego terminu niezależnie przed dodaniem. czego mi brakuje?

Wreszcie uzasadnienie, że „komputery wykonują dodawanie szybciej niż mnożenie” jest niejasne. Czy jest to specyficzne dla zestawu instrukcji x86, czy może jest to bardziej fundamentalna cecha architektury procesorów?

Stephen
źródło
18
Pierwsza korzyść (unikanie niedomiaru) jest często o wiele ważniejsza niż wzrost wydajności, więc nawet jeśli nie byłoby to szybsze, nadal używalibyśmy prawdopodobieństw dziennika.
DW
Aby rozwinąć to, co powiedział @DW, istnieje podobna „sztuczka log-sum-exp” używana specjalnie w celu rozwiązania problemu niedomiaru, bez względu na wydajność. W rzeczywistości po raz pierwszy widziałem, że ktoś uważa logarytmy za technikę poprawy wydajności!
Mehrdad

Odpowiedzi:

14

Również strona Wikipedii ( https://en.wikipedia.org/wiki/Log_probability ) jest myląca pod tym względem, stwierdzając: „Konwersja do postaci dziennika jest kosztowna, ale następuje tylko raz”. Nie rozumiem tego, ponieważ myślę, że musisz dodać dziennik każdego terminu niezależnie przed dodaniem. czego mi brakuje?

Jeśli chcesz tylko raz obliczyć , masz rację. Będziesz musiał obliczyć n logarytmów i n - 1 dodatków, podczas gdy naiwna metoda wymaga n - 1 multiplikacji.P(A1)P(An)nn1n1

Jednak często zdarza się, że chcesz odpowiadać na zapytania formularza:

Oblicz dla niektórych podzbiorów I z { 1 , n } .iIP(Ai)I{1,n}

W takim przypadku możesz wstępnie przetworzyć swoje dane, aby obliczyć wszystkie tylko raz i odpowiedzieć na każde zapytanie, wykonując | Ja | wzbogacenie.logP.(ZAja)|ja|

Wreszcie uzasadnienie, że „komputery wykonują dodawanie szybciej niż mnożenie” jest niejasne. Czy jest to specyficzne dla zestawu instrukcji x86, czy może jest to bardziej fundamentalna cecha architektury procesorów?

To jest szersze pytanie. Zasadniczo (prawdopodobnie?) Trudniej jest obliczyć mnożenie niż dodawanie. Obliczanie + b jest liniowa w rozmiarze i B (przy użyciu algorytmu trywialne), natomiast obecnie nie wiem jak obliczyć do × B o tej samej złożoności czasowej (Sprawdź najlepsze algorytmy tutaj ).za+bzabza×b

Oczywiście nie ma ostatecznej odpowiedzi: na przykład, jeśli masz do czynienia tylko z liczbami całkowitymi i mnożymy przez potęgi , powinieneś raczej porównać shift z operacjami dodawania.2)

Niemniej jednak jest to rozsądne stwierdzenie na wszystkich popularnych architekturach komputerowych: mnożenie liczb zmiennoprzecinkowych będzie wolniejsze niż dodawanie.

md5
źródło
1
P.(ZAja)
Co z końcowym exp ()? Czy to nie jest wolne?
Mehrdad
Θ(M.(n)logn)M.(n)Θ(nM.(n)logn+nqQ|jaq|)Qto zestaw zapytań).
md5
2
expn(0,1)log10
1
Czy dodawanie jest jeszcze szybsze niż mnożenie, jeśli używasz pływaków IEEE - co z pewnością zrobisz w tym przypadku? Nowoczesne cpus są całkiem dobre w pomnażaniu liczb, podczas gdy dodawanie zmiennoprzecinkowe ma kilka kroków, których nie można wykonać jednocześnie - wyrównaj mantysy (przesuń w lewo na podstawie wyniku odejmowania), a następnie dodaj je, a następnie normalizuj (co może powodować zarówno niedopełnienie, jak i przepełnienie, tak). W obwodzie jest dość dużo matrycy, w mikrokodzie każdy krok kosztuje cykl lub kilka.
John Dvorak
4

N.p1,...pN.pja

N.

O(n)nO(n2))

Nawiasem mówiąc, ten pomysł jest podobny do modularnego mnożenia Montgomery, w którym mnożenia są wykonywane w postaci Montgomery, która jest znacznie szybsza niż zwykłe mnożenie, a następnie redukcja.

fade2black
źródło
1
@ Mehrdad, mam nadzieję, że nauczyłeś się szkolnego mnożenia dwóch liczb. Że algorytm jest nadal szeroko stosowany w układach komputerowych, spójrz tutaj. Masz na myśli algorytmy na poziomie oprogramowania, które są gorsze niż czas liniowy. Czy te algorytmy mnożenia są powszechnie stosowane jak w obwodzie mnożenia?
fade2black
1
Duch odpowiedzi jest jednak nadal poprawny, prawda? Jeśli żaden z algorytmów mnożenia nie będzie pasował do liniowego czasu dodawania?
Stephen
1
@ Stephen, w rzeczywistości pytanie nie dotyczyło dokładnej najlepszej złożoności algorytmu mnożenia. Mógłbym udzielić dodatkowych informacji na ten temat, jeśli komentatorzy tego wymagają. Myślę, że długa dyskusja na ten temat byłaby tutaj nie na temat. )))
fade2black