programa - Acelerando los cálculos matemáticos en Java
precedencia de operadores en programacion (4)
Tengo una red neuronal escrita en Java que usa una función de transferencia sigmoidea definida de la siguiente manera:
private static double sigmoid(double x)
{
return 1 / (1 + Math.exp(-x));
}
y esto se llama muchas veces durante el entrenamiento y el cálculo utilizando 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.
Desde un punto de vista matemático, no veo ninguna posibilidad de optimizarlo.
Es una función bastante suave, por lo que un esquema de búsqueda e interpolación es más que suficiente.
Cuando trazado 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?
Si tiene muchos nodos donde el valor de x está fuera del cuadro -10 .. + 10, puede omitir el cálculo de esos valores, por ejemplo, como ...
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 verificaciones 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 que, 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 puedo recordar la pendiente en este momento, pero esto es de lo que estoy hablando usando un sigmoide bipolar como ejemplo. En lugar de calcular de esta manera
y = (1 - exp(-x)) / (1 + exp(-x));
que golpea exp () dos veces, puede almacenar en caché los costosos cálculos en variables temporales, como
temp = exp(-x);
y = (1 - temp) / (1 + temp);
Hay muchos lugares para poner este tipo de cosas para usar en redes BP.
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 artículo (enlace robado de la respuesta de s-lott ).
Como puede ver, solo 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: lamento haber mostrado el gráfico equivocado aquí. Lo he corregido