joo:
Есть ли какие нибудь более быстрые способы расчета степени числа с заданной наперед точностью?
ну вообще есть древний алгоритм возведения в натуральную степень. не уверен что вам подойдет.
double fastPow(double base, int exponent) { double res = 1; while(exponent > 0) { if (exponent % 2 == 0) { exponent /= 2; base *= base; } else { exponent--; res *= base; } } return res; };
ну вообще есть древний алгоритм возведения в натуральную степень. не уверен что вам подойдет.
Можно чуть ускорить, но человеку скорее всего нужна именно дробная степень.
double fastPow(double base,int exponent) { double res=1; while(exponent>0) { if(exponent%2==0) { exponent>>=1; // вот тут base*=base; } else { exponent--; res*=base; } } return res; };
В вики тоже красивый алгоритм, но тоже целая степень.
int power(int t,int k) { // возведение t в степень k int res=1; while(k) { if(k &1) res*=t; t *= t; k>>= 1; } return res; }
Быстрей всего рациональная сигмоида. Вот тест.
void OnStart() { double x,f; uint start; start=GetTickCount(); for(x=-100;x<=100;x+=0.00001) { f=(2.0/(1.0+MathPow(2.0,-x)))-1.0; } Print("sigmoid pow = ",IntegerToString(GetTickCount()-start)); start=GetTickCount(); for(x=-100;x<=100;x+=0.00001) { f=(2.0/(1.0+MathExp(-x)))-1.0; } Print("sigmoid exp = ",IntegerToString(GetTickCount()-start)); start=GetTickCount(); for(x=-100;x<=100;x+=0.00001) { f=x/(1.0+MathAbs(x)); } Print("sigmoid abs = ",IntegerToString(GetTickCount()-start)); }
2011.02.04 02:56:31 Sigmoid_Test_Rate (AUDUSD,H4) sigmoid abs = 1594
2011.02.04 02:56:29 Sigmoid_Test_Rate (AUDUSD,H4) sigmoid exp = 4313
2011.02.04 02:56:25 Sigmoid_Test_Rate (AUDUSD,H4) sigmoid pow = 6828
Urain прав, мне нужно было (уже ненужно, объяснение и результаты ниже) возведение в степень вещественного числа.
В моей приведённой формуле забыл поставить коэффициент 10. Прелесть этой формулы заключается в том, что "чувствительность" её лежит в [-1;1], а на выходе соответственно (-1;1), что во многих случаях удобно (и не только с сетками), и в том, что кривизна кривой более-менее равномерна в диапазоне чувствительности. Немного изменил формулы, предложенные Serj Che, для того, что бы функции работали в нужном диапазоне.
Вот график моей функции:
Вот график с экспонентой:
Вот без возведения в степень вообще:
Это хорошая функция в плане скорости, но кривизная её меня не устроила,
и я чуток ещё поэксперементировал, и получил такую формулу:
Видим вполне приличную кривизну.
А теперь собственно тест на скорость:
void OnStart() { double x,f; uint start,t1,t2,t3,t4; //------------------------------------- Sleep(10); start=GetTickCount(); for(x=-1.0;x<=1.0;x+=0.00000001) { f=(2.0/(1.0+MathPow(2.0,-x*10.0)))-1.0; } t1=GetTickCount()-start; //------------------------------------- //------------------------------------- Sleep(10); start=GetTickCount(); for(x=-1.0;x<=1.0;x+=0.00000001) { f=(2.0/(1.0+MathExp(-x*7.0)))-1.0; } t2=GetTickCount()-start; //------------------------------------- //------------------------------------- Sleep(10); start=GetTickCount(); for(x=-1.0;x<=1.0;x+=0.00000001) { f=6.0*x/(1.0+MathAbs(5.0*x)); } t3=GetTickCount()-start; //------------------------------------- //------------------------------------- Sleep(10); start=GetTickCount(); for(x=-1.0;x<=1.0;x+=0.00000001) { f=3.0*x/(1.0+MathAbs(x)+x*x); } t4=GetTickCount()-start; Print("sigmoid pow = ",t1," sigmoid exp = ",t2," sigmoid abs = ",t3," sigmoid new = ",t4); }
Результат, как говорится, на лицо:
2011.02.04 12:07:26 Sigma 1 (EURUSD,M15) sigmoid pow = 25703 sigmoid exp = 12718 sigmoid abs = 2500 sigmoid new = 2437
Получилось, почему то, даже быстрее, чем по предыдущей формуле. Ускорение составляет больше чем в 10 раз, по сравнению с моей первой формулой сигмоиды!
Всем большое спасибо. Чуть позже выложу результат тестирования, так сказать, на "натуре" - запущу сетку с весами штук эдак под 1000-2000.
А какова скорость стандартной функции pow?
Результат оказался скромнее, чем ожидал. :(
Так, для сети с 1260 весами (60 нейронов с функцией активации, 150000 запусков, такие результаты:
2011.02.04 12:51:32 Tests MLP easy v2 (EURUSD,M15) 4547 мс - Время исполнения
2011.02.04 12:45:24 Tests MLP easy (EURUSD,M15) 5219 мс - Время исполнения
Ускорение всего лишь в 1,15 раза, против ожидаемых 10. Видимо интенсивные операции с массивами сжирают намного больше ресурсов, чем возведение в степень, и выигрыш в скорости сходит на нет.
Но все равно, теперь я быстрее конкурентов на 15%. :)
- www.mql5.com
Результат оказался скромнее, чем ожидал. :(
:) А теперь посчитаем.
допустим, в сети 80 входов, 200 на скрытом слое, 5 на выходе, сигмоиды только на скрытом слое, простой 3-слойный персептрон.
Распространение сигнала = O1 (80*200 + 5*200) = О1(85*200), преобразование сигнала = О2 (1*200).
Итого, получаем, чтобы цифры были равнозначны, функция вычисления степени должна быть в 100 раз дороже (примерно) чем умножение + сумма. Тогда получим выигрыш в 2 раза, если ускорим функцию в 100 раз. Впечатляют расчеты?
Если оптимизация действительно нужна (уже вряд ли, процесс обучения сети редко является узким местом, т.к. он априори подразумевает большие времязатраты), то надо мерять действительно узкие места, а не на глазок. Например, хорошее ускорение даст распараллеливание распространения сигнала по сети.
Воистину преждевременная оптимизация зло.
Результат оказался скромнее, чем ожидал. :(
Так, для сети с 1260 весами (60 нейронов с функцией активации, 150000 запусков, такие результаты:
2011.02.04 12:51:32 Tests MLP easy v2 (EURUSD,M15) 4547 мс - Время исполнения
2011.02.04 12:45:24 Tests MLP easy (EURUSD,M15) 5219 мс - Время исполнения
Ускорение всего лишь в 1,15 раза, против ожидаемых 10. Видимо интенсивные операции с массивами сжирают намного больше ресурсов, чем возведение в степень, и выигрыш в скорости сходит на нет.
Но все равно, теперь я быстрее конкурентов на 15%. :)
Ты не в том приложении строишь графики, у тебя ничего не видно , наложи графики разных сигмоидов на один чарт увидишь много нового.
Классический сигмоид возьми за образец поведения , прогони все функции на разных коэффициентах угла атаки.
double Sigma(double d,double A){return( 1./(1.+exp(-A*d)) );}здесь A-коэффициентах угла атаки. Во все остальные формулы типа sigmoid abs , sigmoid new не так то легко встроить этот коэффициент а ведь с этого же всё началось, Коэф в функции активации это основное что тебе нужно? или тебе просто нужна функция делающая нелинейное преобразование?
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Вычисление степени числа очень ресурсоемкая задача.
Так, если используется в коде нейронная сеть с достаточно большим количеством нейронов с сигмоидой в качестве активационной функции, то время вычисления сети может запросто оказаться большим, чем требуется для остальной части кода программы. Возникает естественное желание ускорить вычисления с помощью различных ухищрений.
Первое, правда и последнее, что пришло на ум, заранее рассчитать функцию с достаточно для практического применения мелким шагом на заданном диапазоне чисел:
записать полученные значения в массив. А уже по мере надобности искать положение аргумента функции между двумя рассчитанными заранее значениями в массиве. Останется только интерполяцией или другим способом посчитать искомое значение функции.
Есть ли какие нибудь более быстрые способы расчета степени числа с заданной наперед точностью?