2013-04-23 6 views
5

Così, oggi mi sono imbattuto in un problema nella costruzione di una macchina Boltzmann con restrizioni che dovrebbe essere banale, ma che sembra essere estremamente difficile. Fondamentalmente sto inizializzando i valori di 2k ai doppi random tra 0 e 1.Calcolo della media geometrica di una lunga lista di doppi casuali

Quello che mi piacerebbe fare è calcolare la media geometrica di questo set di dati. Il problema che sto incontrando è che dal momento che il set di dati è così lungo, moltiplicare tutto insieme risulterà sempre pari a zero, e fare la radice corretta ad ogni passo sarà solo rail a 1.

Potrei potenzialmente chunk l'elenco su, ma penso che sia davvero grave. Qualche idea su come farlo in modo elegante?

In teoria mi piacerebbe estendere il mio codice RBM corrente per avere più vicino a 15k + voci, ed essere in grado di eseguire l'RBM su più thread. Purtroppo questo esclude la matematica comune di apache (metodo medio geometrico non sincronizzato), longitudine.

+0

Il numero diventa super piccolo e sto cercando una soluzione a più lungo termine. Ho intenzione di provare qualcosa di simile con un elenco di quasi 15k e vorrei una soluzione che funzioni anche con questo. –

+1

https://en.wikipedia.org/wiki/Geometric_mean#Calculation – nhahtdh

risposta

11

Wow, utilizzare un tipo di decimale di grandi dimensioni è eccessivo!

Basta prendere il logaritmo di tutto, trovare la media aritmetica e quindi esponenziare.

0

Sembra che dopo un numero sufficiente di moltiplicazioni la doppia precisione non sia più sufficiente. Troppi zeri iniziali, se vuoi.

The wiki page on arbitrary precision arithmetic mostra alcuni modi per affrontare il problema. In Java, BigDecimal sembra la strada da percorrere, anche se a scapito della velocità.

1

La soluzione per il logaritmo di Mehrdad funziona sicuramente. Si può farlo più velocemente (e forse più accuratamente), però:

  1. calcolare la somma degli esponenti dei numeri, diciamo S.
  2. Blocca tutti gli esponenti a zero in modo che ogni numero sia compreso tra 1/2 e 1.
  3. Raggruppa i numeri in mazzi di massimo 1000.
    • Per ogni gruppo, calcolare il prodotto dei numeri. Questo non sarà insufficiente.
    • Aggiungere l'esponente del prodotto a S e bloccare l'esponente a zero.
  4. Ora avete circa 1/1000 di numeri. Ripeti i passaggi 2 e 3 a meno che tu non abbia un solo numero.
  5. Chiamare il numero rimanente T. La media geometrica è T1/NS/N, dove N è la dimensione dell'input.
+0

Sono un po 'poco chiaro sul tuo processo qui, di quali esponenti stai parlando? Anche la moltiplicazione di 1000 numeri casuali insieme sarà assolutamente insufficiente. Nell'ordine del 10^-300. Probabilmente alcuni ordini di grandezza più bassi. –

+0

@SlaterTyranus: "Esponente" qui indica la parte esponenziale del doppio --- la parte che non è il bit o il significato del segno. Moltiplicando 1000 doppi tra 1/2 e 1 non verrà effettuato il underflow poiché il più piccolo esponente rappresentabile è inferiore a -1000; è per questo che ho scelto 1000. – tmyklebu

+0

Credo che l'esponente più piccolo sia effettivamente dell'ordine di -300. http://www.cplusplus.com/forum/general/53760/, che mette questo in pericolo di underflow, anche se in lotti più piccoli andrebbe bene. Hai eseguito benchmark su questo? Non è una soluzione elegante, ma se i miglioramenti delle prestazioni sono significativi sarei disposto a passare. La mia intuizione dice che sarebbe più lento, ma non conosco una quantità enorme del logaritmo integrato di Java. –

Problemi correlati