Нейронные сети. Вопросы экспертам. - страница 21

 
alsu:

4) параметры инициализации весов - форма распределения значений и их дисперсия.

Нашел. Есть возможность задавать параметры инициализации весов.

Похоже я использовал значения по умолчанию.


 
LeoV:
Краткосрочные курсы повышения квалификации "Искусственные нейронные сети
и генетические алгоритмы"

Заканчивается прием заявок на прохождение краткосрочных курсов повышения
квалификации "Искусственные нейронные сети и генетические алгоритмы",
проводимых факультетом дополнительного образования Московского
Государственного Университета им. М.В.Ломоносова на базе НИИ ядерной
физики МГУ. Окончившим курсы МГУ выдаёт удостоверение государственного
образца о повышении квалификации.
Занятия будут проходить два раза в неделю в вечернее время с 19-00.
Начало занятий 25 февраля 2011 г.

Ознакомиться с программой курсов, получить более подробную информацию и
подать заявку для прохождения курсов Вы можете по адресу:
http://www.neuroproject.ru/kpk.php
простите, это реклама или вы сами там будете обучаться?
 
lasso:

Нашел. Есть возможность задавать параметры инициализации весов.

Похоже я использовал значения по умолчанию.


Ну, кажется, понятно в чем тут дело.

Если отталкиваться от вашей задачи (как я понимаю, у вас имеются одномерные данные, которые вы хотите разбить на два класса), то суть ее состоит в том, чтобы найти на множестве входных значений точку (всего одну!), оптимальным образом производящую указанное разбиение. Допустим, вы взяли для этого сеть 1-7-1. В этой сети количество весов равно 21 ( семь входных у скрытого слоя, семь смещений у него же и семь входов выходного нейрона). Получается, что мы пытаемся найти одну точку, подбирая при этом 21 переменную. При такой избыточности двадцать один к одному нет ничего удивительного в том, что показания сети так пляшут - любое самое малое различие в начальных весах приводит к существенному разбросу выходов после обучения. Грубо говоря, выходит, что задача слишком проста для сети, но так как сама она об этом не знает, то и ищет то, чего нет. Формально это, наверное, можно назвать переобучением, но по сути - стрельба из пушки по воробьям.

Строго говоря, задачу разбиения одномерных данных на два класса с успехом выполняет единичный нейрон с одним входным весом и одним bias'ом.

 
lasso:

И еще. Меня настораживает "узость" диапазона актуальных выходов сети. Поясню:

-- сеть MLP 1-7-1

-- значения подаваемые на входы НС равномерно распределены в диапазоне [0;1], выходы в обучающих примерах представлены значениями 1 и -1.

Если после обучения через сеть прогнать весь диапазон значений входов, то мы увидим, что выходы сети лежат в очень узком диапазоне. Например:

opt_max_act=-0.50401336 opt_min_act=-0.50973881 step=0.0000286272901034

или даже так

opt_max_real=-0.99997914 opt_min_real=-0.99999908 step=0.00000010

.............................

Это правильно или нет?


Сложно сказать насчет правильности... зависит от ситуации

По вашему примеру:

Этот случай означает, что первая сеть на всех входах говорит "не знаю", а вторая на тех же входах "класс -1". Если данные одни и те же, а различия только в инициализации весов, то скорее всего, дело в сильной перемешанности классов ввиду чего сетки не могут толково разобрать закономерность обучения и в результате действуют "наобум". Говоря о том, каким образом это может происходить, я допускаю, что если в сети (наверное это так) использованы нейроны со смещением, то сетка просто обнуляет веса всех информационных входов и оставляет себе для анализа только bias. "Анализ", естественно, получается лишь номинальный, сеть работает по принципу страуса - она просто не видит входов. Для того, чтобы это подтвердить или опровергнуть, надо увидеть матрицы обученной сети.

 

Вот сгенерированный "Статистикой" код MLP НС:

/* ------------------------------------------------------------------------- */


#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif

#define MENUCODE -999


static double NNCode38Thresholds[] =
{

/* layer 1 */
-0.78576109762088242, -0.23216582173469763, -1.6708808507320108, -1.525614113040888,
1.4153558659332133, -0.77276960668316319, 2.3600992937381298, 2.473963708568014,
-0.43422405325901231, 0.68546943611132893, 0.19836417975077064, 0.26461366779934564,
-0.19131682804149783, 0.24687125804149584, -0.95588612620053504, 0.25329560565058901,
-1.0054817062488075, 1.3224622867600988, 0.88115523574528376, 0.32309684489223067,
0.52538428519764313,

/* layer 2 */
-1.8292886608617505

};

static double NNCode38Weights[] =
{

/* layer 1 */
1.8660729426318707,
1.3727568288578245,
3.1175074758006374,
3.356836518157698,
3.2574311486418068,
3.2774957848884769,
1.4284147042568165,
3.534875314491805,
2.4874577673065557,
2.1516346524000403,
1.9692127720516106,
4.3440737376517129,
2.7850179803408932,
-12.654434243399631,
2.4850018642785399,
2.1683631515554227,
1.77850226182071,
2.1342779960924272,
2.8753050022428206,
3.9464397902669828,
2.5227540467556553,

/* layer 2 */
-0.041641949353302246, -0.099151657230575702, 0.19915689162090328, -0.48586373846026099,
-0.091916813099494746, -0.16863091580772138, -0.11592356639654273, -0.55874391921850786,
0.12335845466035589, -0.022300206392803789, -0.083342117374385544, 1.550222748978116,
0.10305706982775611, 3.9280003726494575, 0.12771097131123971, -0.12144621860368633,
-0.40427171889553365, -0.072652508364580259, 0.20641498115269669, 0.1519896468808962,
0.69632055946019444

};

static double NNCode38Acts[46];

/* ---------------------------------------------------------- */
/*
  NNCode38Run - run neural network NNCode38

  Input and Output variables.
  Variable names are listed below in order, together with each
  variable's offset in the data set at the time code was
  generated (if the variable is then available).
  For nominal variables, the numeric code - class name
  conversion is shown indented below the variable name.
  To provide nominal inputs, use the corresponding numeric code.
  Input variables (Offset):
  stoch

  Выход:
  res
    1=1
    2=-1

*/
/* ---------------------------------------------------------- */

void NNCode38Run( double inputs[], double outputs[], int outputType )
{
  int i, j, k, u;
  double *w = NNCode38Weights, *t = NNCode38Thresholds;

  /* Process inputs - apply pre-processing to each input in turn,
   * storing results in the neuron activations array.
   */

  /* Input 0: standard numeric pre-processing: linear shift and scale. */
  if ( inputs[0] == -9999 )
    NNCode38Acts[0] = 0.48882189239332069;
  else
    NNCode38Acts[0] = inputs[0] * 1.0204081632653061 + 0;

  /*
   * Process layer 1.
   */

  /* For each unit in turn */
  for ( u=0; u < 21; ++u )
  {
    /*
     * First, calculate post-synaptic potentials, storing
     * these in the NNCode38Acts array.
     */

    /* Initialise hidden unit activation to zero */
    NNCode38Acts[1+u] = 0.0;

    /* Accumulate weighted sum from inputs */
    for ( i=0; i < 1; ++i )
      NNCode38Acts[1+u] += *w++ * NNCode38Acts[0+i];

    /* Subtract threshold */
    NNCode38Acts[1+u] -= *t++;

    /* Now apply the logistic activation function, 1 / ( 1 + e^-x ).
     * Deal with overflow and underflow
     */
    if ( NNCode38Acts[1+u] > 100.0 )
       NNCode38Acts[1+u] = 1.0;
    else if ( NNCode38Acts[1+u] < -100.0 )
      NNCode38Acts[1+u] = 0.0;
    else
      NNCode38Acts[1+u] = 1.0 / ( 1.0 + exp( - NNCode38Acts[1+u] ) );
  }

  /*
   * Process layer 2.
   */

  /* For each unit in turn */
  for ( u=0; u < 1; ++u )
  {
    /*
     * First, calculate post-synaptic potentials, storing
     * these in the NNCode38Acts array.
     */

    /* Initialise hidden unit activation to zero */
    NNCode38Acts[22+u] = 0.0;

    /* Accumulate weighted sum from inputs */
    for ( i=0; i < 21; ++i )
      NNCode38Acts[22+u] += *w++ * NNCode38Acts[1+i];

    /* Subtract threshold */
    NNCode38Acts[22+u] -= *t++;

    /* Now calculate negative exponential of PSP
     */
    if ( NNCode38Acts[22+u] > 100.0 )
       NNCode38Acts[22+u] = 0.0;
    else
      NNCode38Acts[22+u] = exp( -NNCode38Acts[22+u] );
  }

  /* Type of output required - selected by outputType parameter */
  switch ( outputType )
  {
    /* The usual type is to generate the output variables */
    case 0:


      /* Post-process output 0, two-state nominal output */
      if ( NNCode38Acts[22] >= 0.05449452669633785 )
        outputs[0] = 2.0;
      else
        outputs[0] = 1.0;
      break;

    /* type 1 is activation of output neurons */
    case 1:
      for ( i=0; i < 1; ++i )
        outputs[i] = NNCode38Acts[22+i];
      break;

    /* type 2 is codebook vector of winning node (lowest actn) 1st hidden layer */
    case 2:
      {
        int winner=0;
        for ( i=1; i < 21; ++i )
          if ( NNCode38Acts[1+i] < NNCode38Acts[1+winner] )
            winner=i;

        for ( i=0; i < 1; ++i )
          outputs[i] = NNCode38Weights[1*winner+i];
      }
      break;

    /* type 3 indicates winning node (lowest actn) in 1st hidden layer */
    case 3:
      {
        int winner=0;
        for ( i=1; i < 21; ++i )
          if ( NNCode38Acts[1+i] < NNCode38Acts[1+winner] )
            winner=i;

        outputs[0] = winner;
      }
      break;
  }
}
 
alsu:

Сложно сказать насчет правильности... зависит от ситуации

По вашему примеру:

Этот случай означает, что первая сеть на всех входах говорит "не знаю", а вторая на тех же входах "класс -1". Если данные одни и те же, а различия только в инициализации весов, то скорее всего, дело в сильной перемешанности классов ввиду чего сетки не могут толково разобрать закономерность обучения и в результате действуют "наобум". Говоря о том, каким образом это может происходить, я допускаю, что если в сети (наверное это так) использованы нейроны со смещением, то сетка просто обнуляет веса всех информационных входов и оставляет себе для анализа только bias. "Анализ", естественно, получается лишь номинальный, сеть работает по принципу страуса - она просто не видит входов. Для того, чтобы это подтвердить или опровергнуть, надо увидеть матрицы обученной сети.

И еще: в FANN действительно применяется bias-смещение в каждом слое, кроме входящего...

Но в описании пакета NN программы "Статистика 6" я не нашел ничего похожего на bias.

Для новичка в НС все эти разности реально выносят мозг...

 

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


 

Великолепно!!

Значения весов и порогов в виде диаграммы.

И совсем другой взгляд. Спасибо.

 
lasso:

Вот сгенерированный "Статистикой" код MLP НС:

Добрый день!

Могли бы Вы подсказать в двух словах, можно ли с помощью программиста научиться компилировать dll-файл из C-файла с нейронной сетью, сгенерированного Statistica? Я имею в виду, чтобы один раз объяснили процедуру, чтобы потом делать самому по схеме. Просто уровень программирования на Basic в школе, а НС-модель для работы форех вырисовывается, но нужно регулярно сеть обновлять - читай новый dll генерировать. В коде MQL каждый раз ее корректировать - это как то сложновато.

 
alexeymosc:

Добрый день!

можно ли с помощью программиста научиться компилировать dll-файл из C-файла с нейронной сетью, сгенерированного Statistica?

Доброй ночи!

Думаю нет, исключение только в том случае, если только этот программист не работает в самой компании "Статистика" ))

alexeymosc:

В коде MQL каждый раз ее корректировать - это как то сложновато.

А Какой тип НС вы используете в Статистика ?

Если Вы что то корректируете руками, значит есть алгоритм, вот его и надо автоматизировать....

...............................

Выше мне рекомендовали использовать ГА, и как раз сегодня с помощью библиотеки joo (UGALib) удалось получить желаемый и стабильный результат.

Теперь буду это дело перетаскивать на 4-ку...

Андрею (автору) низкий поклон. Очень перспективное и гибкое направление.

.....................

Может стоит копнуть в эту сторону?

Причина обращения: