Saya menulis sebuah algoritma di mana, diberikan model, saya menghitung kemungkinan untuk daftar dataset dan kemudian perlu menormalkan (untuk probabilitas) masing-masing kemungkinan. Jadi sesuatu seperti [0,00043, 0,00004, 0,00321] mungkin dikonversi menjadi seperti [0,2, 0,03, 0,77].
Masalah saya adalah kemungkinan log, saya bekerja dengan, cukup kecil (misalnya, dalam ruang log, nilainya seperti -269647.432, -231444.981 dll). Dalam kode C ++ saya, ketika saya mencoba untuk menambahkan dua dari mereka (dengan mengambil eksponen mereka) saya mendapatkan jawaban "Inf". Saya mencoba menambahkannya di ruang log (Penjumlahan / Pengurangan log) , tetapi sekali lagi menemukan masalah yang sama.
Adakah yang bisa berbagi pendapat ahli tentang hal ini?
log1p
Jawaban:
Kurangi logaritma maksimum dari semua log. Buang semua hasil yang sangat negatif sehingga akan melemahkan eksponensial. (Kemungkinannya, untuk semua tujuan praktis, nol.)
Memang, jika Anda menginginkan presisi relatif dari (seperti untuk digit presisi) dan Anda memiliki kemungkinan, buanglah hasil yang kurang dari logaritma . Kemudian lanjutkan seperti biasa untuk membuat eksponensial nilai yang dihasilkan dan bagi masing-masing dengan jumlah semua eksponensial.ϵ = 10 - d d n ϵ / nϵ ϵ = 10- d d n ϵ / n
Bagi mereka yang suka rumus, biarkan logaritma menjadi dengan . Untuk logaritma ke basis b \ gt 1 , tentukanλ n = maks ( λ i ) b > 1λ1, λ2, … , Λn λn= maks ( λsaya) b > 1
Kemungkinan dinormalisasi sama dengan , Ini berfungsi karena mengganti semua underflow dengan nol membuat kesalahan total paling banyak sedangkan, karena dan semua adalah non-negatif, penyebut , di mana total kesalahan relatif karena aturan penggantian nol secara ketat lebih kecil dari , seperti yang diinginkan. i = 1 , 2 , … , n . α i ( n - 1 ) ϵ / n < ϵ α n = b λ n - λ n = b 0 = 1 α i A = ∑ j α j ≥ 1 ( ( n - 1αsaya/ ∑nj = 1αj i = 1 , 2 , … , n . αsaya ( n - 1 ) ϵ / n < ϵ αn= bλn- λn= b0= 1 αsaya A = ∑jαj≥ 1 ( ( n - 1 ) ϵ / n ) / A < ϵ
Untuk menghindari kesalahan pembulatan yang terlalu banyak, hitung jumlah yang dimulai dengan nilai terkecil dari . Ini akan dilakukan secara otomatis ketika pertama kali disortir dalam urutan yang meningkat. Ini hanya pertimbangan untuk sangat besar .λ i nαsaya λsaya n
BTW, resep ini mengasumsikan basis log lebih besar dari . Untuk basis kurang dari , pertama negasikan semua log dan lanjutkan seolah-olah basis sama dengan .b 1 1 / b1 b 1 1 / b
Contoh
Biarkan ada tiga nilai dengan logaritma (log natural, katakanlah) sama dengan dan Yang terakhir adalah yang terbesar; Mengurangkannya dari masing-masing nilai memberi dan- 231444.981 , - 231444.699. - 38202.733 , - 0.282 , 0.- 269647.432 , - 231444.981 , - 231444.699. - 38202.733 , - 0,282 , 0.
Misalkan Anda ingin presisi sebanding dengan dua kali lipat IEEE (sekitar 16 angka desimal), sehingga dan . (Anda tidak dapat benar-benar mencapai ketepatan ini, karena hanya diberikan kepada tiga angka penting, tapi tidak apa-apa: kami hanya membuang nilai yang dijamin tidak akan memengaruhi ketepatan yang Anda inginkan, dan ketepatan yang sebenarnya Anda dapatkan have.) Hitung = = Yang pertama dari tiga perbedaan, lebih sedikit dari ini, jadi buanglah, hanya dan Memberi eksponensial memberi n = 3 - 0,282 log ( ϵ / n ) log ( 10 - 16 ) - log ( 3 ) - 37,93997. - 38202.733 , - 0.282 0. exp ( - 0.282 ) = 0.754 exp ( 0 ) = 1 0 0.754 / ( 1 + 0.754 ) =ϵ = 10- 16 n = 3 −0.282 log(ϵ/n) log(10−16)−log(3) −37.93997. −38202.733, −0.282 0. exp(−0.282)=0.754 dan (tentu saja). Nilai yang dinormalisasi adalah - dalam urutan - untuk yang Anda buang, , dan .exp(0)=1 0 0.754/(1+0.754)=0.430 1/(1+0.754)=0.570
sumber