2010-05-22 24 views
9

que tienen una red neuronal escrito en Java que utiliza una función de transferencia sigmoide se define de la siguiente manera:Acelerar cálculos matemáticos en Java

private static double sigmoid(double x) 
{ 
    return 1/(1 + Math.exp(-x)); 
} 

y esto se llama muchos veces durante el entrenamiento y el cálculo usando la red. ¿Hay alguna forma de acelerar esto? No es que sea lento, es solo que se usa mucho, por lo que una pequeña optimización aquí sería una gran ganancia general.

+3

¿Se repiten los valores de x o es más probable que siempre sean diferentes cada vez que se llame al método? – DaveJohnston

+0

Además, ¿qué tan preciso debe ser el resultado? –

+0

@Dave - depende de la precisión deseada, pero todos son números flotantes, por lo que es bastante único – Simon

Respuesta

20

Para redes neuronales, no necesita el valor exacto de la función sigmoidea. Entonces puede precalcular 100 valores y reutilizar el valor que está más cerca de su entrada, o incluso mejor (como un comentario declarado) hacer una interpolación de los valores vecinos.

Cómo se puede hacer esto se describe en este article (enlace robado del answer of s-lott).

Ésta es la función sigmoide: Sigmoid function graph

Como se puede ver, sólo los valores de -10 < x 10 < son interesantes en absoluto. Y, como dijo otro comentario, la función es simétrica. Solo debe almacenar la mitad de los valores.


Editar: Siento que he mostrado el gráfico mal aquí. Lo he corregido

+1

Tal vez algo más de 100 si quieres un poco más de precisión. Una tabla de búsqueda de 5000 (pero probablemente incluso 1000) valores será absolutamente suficiente en mi humilde opinión. – nico

+2

Para obtener más precisión, probablemente sea mejor hacer una interpolación lineal entre los dos valores más cercanos. –

+2

El problema es simétrico, por lo que solo necesita la mitad de los valores. Calcular el otro lado es trivial. –

0

Desde un punto de vista matemático, no veo ninguna posibilidad de optimizarlo.

1

Es una función bastante suave, por lo que un esquema de búsqueda e interpolación es más que suficiente.

Cuando trazo la función en un rango de -10 <= x <= 10, obtengo una precisión de cinco lugares en los extremos. ¿Eso es lo suficientemente bueno para tu aplicación?

5

Si usted tiene una gran cantidad de nodos en los que el valor de x está fuera de la caja -10 .. + 10, puede simplemente dejar de calcular esos valores en absoluto, por ejemplo, al igual que ..

if(x < -10) 
    y = 0; 
else if(x > 10) 
    y = 1; 
else 
    y = 1/(1 + Math.exp(-x)); 
return y; 

Por supuesto, esto implica la sobrecarga de las comprobaciones condicionales para CADA cálculo, por lo que solo vale la pena si tiene muchos nodos saturados.

Otra cosa que vale la pena mencionar es, si está utilizando la retropropagación, y tiene que lidiar con la pendiente de la función, es mejor calcularla en partes en lugar de 'como está escrito'.

No recuerdo la inclinación en este momento, pero esto es de lo que estoy hablando usando un sigmoide bipolar como ejemplo. En lugar de calcular esta manera

y = (1 - exp(-x))/(1 + exp(-x)); 

que llega a exp() dos veces, se puede almacenar en caché los cálculos costosos en variables temporales, al igual que

temp = exp(-x); 
y = (1 - temp)/(1 + temp); 

Hay un montón de lugares para poner este tipo de cosas para usar en redes BP.

Cuestiones relacionadas