2010-05-22 3 views
9

У меня есть нейронная сеть, написанную на Java, которая использует функцию передачи сигмовидной определяются следующим образом:ускоряя расчеты Math в Java

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

и это называется много раз во время тренировок и вычисления с использованием сети. Есть ли способ ускорить это? Дело не в том, что это медленно, просто потому, что он используется много, поэтому небольшая оптимизация здесь будет большим общим выигрышем.

+3

Являются ли значения x когда-либо повторяющимися или это более вероятно, что они всегда будут отличаться при каждом вызове метода? – DaveJohnston

+0

Кроме того, насколько точным должен быть результат? –

+0

@Dave - зависит от желаемой точности, но все они являются числами с плавающей запятой, поэтому довольно много уникальных – Simon

ответ

20

Для нейронных сетей вам не требуется точное значение сигмовидной функции. Таким образом, вы можете предварительно вычислить 100 значений и повторно использовать значение, которое ближе всего к вашему входу, или даже лучше (как указано в комментарии) сделать интерполяцию из соседних значений.

Как вы можете это сделать, описано в этом article (ссылка украдена у answer of s-lott).

Это функция сигмовидной: Sigmoid function graph

Как вы можете видеть, только значения -10 < < х 10 интересны вообще. И, как сказал другой комментарий, функция симметрична. Вам нужно хранить только половину значений.


Edit: Я сожалею, что я показал неправильный график здесь. Я исправил это.

+1

Возможно, что-то более 100, если вы хотите немного больше точности. Таблица поиска 5000 (но, вероятно, даже 1000) значений будет абсолютно достаточной ИМХО. – nico

+2

Для большей точности, вероятно, лучше сделать линейную интерполяцию между ближайшими двумя значениями. –

+2

Проблема симметрия, поэтому вам нужно всего лишь половину значений. Вычисление другой стороны тривиально. –

0

С математической точки зрения, я не вижу возможности ее оптимизировать.

1

Это довольно гладкая функция, поэтому схема поиска и интерполяции, вероятно, будет более чем достаточной.

Когда я рисую функцию в диапазоне -10 <= x <= 10, я получаю точность пяти точек на крайности. Это достаточно хорошо для вашего приложения?

5

Если у вас есть много узлов, где значение х находится вне -10 .. + 10 коробки, вы можете просто опустить, чтобы вычислить эти значения на всех, например, как так ..

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

Конечно, это приводит к накладным расходам условных проверок для расчета EVERY, поэтому это стоит того, если у вас много насыщенных узлов.

Еще одна вещь, о которой стоит упомянуть, заключается в том, что если вы используете backpropagation, и вам приходится иметь дело с наклоном функции, лучше вычислить ее на куски, а не «как написано».

Я не могу вспомнить наклон в данный момент, но вот что я говорю об использовании биполярного сигмоида в качестве примера. Вместо того, чтобы вычислить этот путь

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

который бьет ехр() дважды, вы можете кэшировать до дорогостоящих вычислений во временных переменных, например, так

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

Есть много мест, чтобы поставить такого рода вещи для использования в сетях BP.