Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> выводит NAN. почему? реализую ИНС 
:(
    Опции темы
wowka19
Дата 27.5.2012, 00:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



Необходимо реализовать искусственную нейронную сеть Когнитрон (К. Фукушима).
Сомневаюсь, очень сомневаюсь, что это у меня получилось, но проверить не получается так как программа выводит NAN.
Помогите определить, в чем проблема.

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

Код

#include <iostream>

class Pair
{
public:
    long double u;
    long double v;
    long double a1;
    long double a2;
    long double a3;
    long double b;

    Pair(){u = v = a1 = a2 = a3 = b = 0.0;}
};

Pair layer[3][9];

const double q = 12.0;
const double q0 = 2.0;

void calculate_inhibitory_out(unsigned short j)
{
    layer[j][0].v = (layer[j][0].u + layer[j][1].u) / 2;
    layer[j][8].v = (layer[j][7].u + layer[j][8].u) / 2;
    for (int i = 1; i < 8; ++i)
    {
        layer[j][i].v = (layer[j][i-1].u + layer[j][i].u + layer[j][i+1].u) / 3;
    }
}

void calculate_excitatory_out(unsigned short j)
{
    double E, I;
    // для крайних нейронов
    E = layer[j][0].a1 * layer[j-1][0].u + layer[j][0].a2 * layer[j-1][1].u;
    I = layer[j][0].b * layer[j-1][0].v + layer[j+1][0].b * layer[j][0].v;             /* ! якобы с латеральным торможением */
    layer[j][0].u = (1 + E) / (1 + I) - 1;
    if (layer[j][0].u < 0) layer[j][0].u = 0.0;

    E = layer[j][8].a1 * layer[j-1][7].u + layer[j][8].a2 * layer[j-1][8].u;
    I = layer[j][8].b * layer[j-1][8].v + layer[j+1][8].b * layer[j][8].v;       /* ! якобы с латеральным торможением */
    layer[j][8].u = (1 + E) / (1 + I) - 1;
    if (layer[j][8].u < 0) layer[j][8].u = 0.0;

    // для остальных нейронов
    for (int i = 1; i < 8; ++i)
    {
        E = layer[j][i].a1 * layer[j-1][i-1].u + layer[j][i].a2 * layer[j-1][i].u + layer[j][i].a3 * layer[j-1][i+1].u;
        I = layer[j][i].b * layer[j-1][i].v + layer[j+1][i].b * layer[j][i].v;    /* ! якобы с латеральным торможением */
        layer[j][i].u = (1 + E) / (1 + I) - 1;
        if (layer[j][i].u < 0) layer[j][i].u = 0.0;
    }
}

// возвращает победителя или 0 если такового нет
unsigned short winner(const double n1, const double n2, const double n3)
{
    if (n1 > n2)
    {
        if (n1 > n3)
            return 1;
        else
        {
            if (n1 != n3)
                return 3;
            else
                return 0;
        }
    }
    else
    {
        if (n1 != n2)
        {
            if (n2 > n3)
                return 2;
            else
            {
                if (n2 != n3)
                    return 3;
                else
                    return 0;
            }
        }
        else
        {
            if (n3 > n1)
                return 3;
            else
                return 0;
        }
    }
}

void calculate_weight(unsigned short j)
{
    // считаем веса синапсов от предыдущего слоя (только для "умных" нейронов в каждой области конкуренции)
    unsigned short temp;
    // для первой области конкуренции
    if ((temp = winner(layer[j][0].u, layer[j][1].u, layer[j][2].u)) != 0)
    { // победитель есть
        if (temp == 1)
        { // крайний
            layer[j][0].a1 += q * layer[j-1][0].u / 2;
            layer[j][0].a2 += q * layer[j-1][1].u / 2;
            layer[j][0].b  += q * (layer[j][0].a1 * layer[j-1][0].u + layer[j][0].a2 * layer[j-1][1].u) / (2 * layer[j-1][0].v);
        }
        else
        { // не крайний
            layer[j][temp-1].a1 += q * layer[j-1][temp-2].u / 3;
            layer[j][temp-1].a2 += q * layer[j-1][temp-1].u / 3;
            layer[j][temp-1].a3 += q * layer[j-1][temp].u / 3;
            layer[j][temp-1].b  += q * (layer[j][temp-1].a1 * layer[j-1][temp-2].u + layer[j][temp-1].a2 * layer[j-1][temp-1].u + layer[j][temp-1].a3 * layer[j-1][temp].u) / (2 * layer[j-1][temp-1].v);
        }
    }
    else
    { // победителя нет
        // первый (крайний)
        layer[j][0].a1 += q0 * layer[j-1][0].u / 2;
        layer[j][0].a2 += q0 * layer[j-1][1].u / 2;
        layer[j][0].b  += q0 * layer[j-1][0].v;
        // второй
        layer[j][1].a1 += q0 * layer[j-1][0].u / 3;
        layer[j][1].a2 += q0 * layer[j-1][1].u / 3;
        layer[j][1].a3 += q0 * layer[j-1][2].u / 3;
        layer[j][1].b  += q0 * layer[j-1][1].v;
        // третий
        layer[j][2].a1 += q0 * layer[j-1][1].u / 3;
        layer[j][2].a2 += q0 * layer[j-1][2].u / 3;
        layer[j][2].a3 += q0 * layer[j-1][3].u / 3;
        layer[j][2].b  += q0 * layer[j-1][2].v;
    }
    // от второй до предпоследней области конкуренции
    for (int i = 1; i < 6; ++i)
    {
        if ((temp = winner(layer[j][i].u, layer[j][i+1].u, layer[j][i+2].u)) != 0)
        { // победитель есть
            layer[j][i+temp-1].a1 += q * layer[j-1][i+temp-2].u / 3;
            layer[j][i+temp-1].a2 += q * layer[j-1][i+temp-1].u / 3;
            layer[j][i+temp-1].a3 += q * layer[j-1][i+temp].u / 3;
            layer[j][i+temp-1].b  += q * (layer[j][i+temp-1].a1 * layer[j-1][i+temp-2].u + layer[j][i+temp-1].a2 * layer[j-1][i+temp-1].u + layer[j][i+temp-1].a3 * layer[j-1][i+temp].u) / (2 * layer[j-1][i+temp-1].v);
        }
        else
        { // победителя нет
            layer[j][i].a1 += q0 * layer[j-1][i-1].u / 3;
            layer[j][i].a2 += q0 * layer[j-1][i].u / 3;
            layer[j][i].a3 += q0 * layer[j-1][i+1].u / 3;
            layer[j][i].b  += q0 * layer[j-1][i].v;

            layer[j][i+1].a1 += q0 * layer[j-1][i].u / 3;
            layer[j][i+1].a2 += q0 * layer[j-1][i+1].u / 3;
            layer[j][i+1].a3 += q0 * layer[j-1][i+2].u / 3;
            layer[j][i+1].b  += q0 * layer[j-1][i+1].v;

            layer[j][i+2].a1 += q0 * layer[j-1][i+1].u / 3;
            layer[j][i+2].a2 += q0 * layer[j-1][i+2].u / 3;
            layer[j][i+2].a3 += q0 * layer[j-1][i+3].u / 3;
            layer[j][i+2].b  += q0 * layer[j-1][i+2].v;
        }
    }
    // для последней области конкуренции
    if ((temp = winner(layer[j][6].u, layer[j][7].u, layer[j][8].u)) != 0)
    { // победитель есть
        if (temp == 3)
        { // крайний
            layer[j][8].a1 += q * layer[j-1][7].u / 2;
            layer[j][8].a2 += q * layer[j-1][8].u / 2;
            layer[j][8].b  += q * (layer[j][8].a1 * layer[j-1][7].u + layer[j][8].a2 * layer[j-1][8].u) / (2 * layer[j-1][8].v);
        }
        else
        { // не крайний
            layer[j][temp+5].a1 += q * layer[j-1][temp+4].u / 3;
            layer[j][temp+5].a2 += q * layer[j-1][temp+5].u / 3;
            layer[j][temp+5].a3 += q * layer[j-1][temp+6].u / 3;
            layer[j][temp+5].b  += q * (layer[j][temp+5].a1 * layer[j-1][temp+4].u + layer[j][temp+5].a2 * layer[j-1][temp+5].u + layer[j][temp+5].a3 * layer[j-1][temp+6].u) / (2 * layer[j-1][temp+5].v);
        }
    }
    else
    { // победителя нет
        // седьмой
        layer[j][6].a1 += q0 * layer[j-1][5].u / 3;
        layer[j][6].a2 += q0 * layer[j-1][6].u / 3;
        layer[j][6].a3 += q0 * layer[j-1][7].u / 3;
        layer[j][6].b  += q0 * layer[j-1][6].v;
        // восьмой
        layer[j][7].a1 += q0 * layer[j-1][6].u / 3;
        layer[j][7].a2 += q0 * layer[j-1][7].u / 3;
        layer[j][7].a3 += q0 * layer[j-1][8].u / 3;
        layer[j][7].b  += q0 * layer[j-1][7].v;
        // девятый (крайний)
        layer[j][8].a1 += q0 * layer[j-1][7].u / 2;
        layer[j][8].a2 += q0 * layer[j-1][8].u / 2;
        layer[j][8].b  += q0 * layer[j-1][8].v;
    }
}

const double * cognitron(const double * const input)
{
    // инициализация значений возбуждающих нейронов первого слоя
    for (int i = 0; i < 9; ++i)
    {
        layer[0][i].u = input[i];
    }

    // инициализация значений тормозящих нейронов первого слоя
    calculate_inhibitory_out(0);

    // считаем веса синапсов от первого слоя (только для "умных" нейронов в каждой области конкуренции)
    calculate_weight(1);

    // считаем выход возбуждающих нейронов второго слоя
    calculate_excitatory_out(1);

    // считаем выходы тормозящих нейронов второго слоя
    calculate_inhibitory_out(1);

    // считаем веса синапсов от второго слоя (только для "умных" нейронов в каждой области конкуренции)
    calculate_weight(2);

    calculate_excitatory_out(2);

    calculate_inhibitory_out(2);
    return 0;
}

int main()
{
    const double in1[] = {1,2,3,7,5,6,7,8,9};
    const double in2[] = {6,3,4,5,8,6,5,2,0};

    cognitron(in1);
    for (int i = 0; i < 9; ++i)
        std::cout << layer[2][i].a1 << " ";

    std::cout << "\n";
    cognitron(in2);
    for (int i = 0; i < 9; ++i)
        std::cout << layer[2][i].a1 << " ";

    std::cout << "\n";
    cognitron(in1);
    for (int i = 0; i < 9; ++i)
        std::cout << layer[2][i].a1 << " ";

    std::cout << "\n";
    cognitron(in2);
    for (int i = 0; i < 9; ++i)
        std::cout << layer[2][i].a1 << " ";

    std::cout << "\n";
    cognitron(in1);
    for (int i = 0; i < 9; ++i)
        std::cout << layer[2][i].a1 << " ";

    std::cout << "\n";
    cognitron(in2);
    for (int i = 0; i < 9; ++i)
        std::cout << layer[2][i].a1 << " ";
    return 0;
}



PM MAIL   Вверх
mes
Дата 27.5.2012, 09:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата

К операциям, приводящим к появлению NaN в качестве ответа, относятся:

  • все математические операции, содержащие NaN в качестве одного из операндов;
  • деление ноля на ноль;
  • деление бесконечности на бесконечность;
  • умножение ноля на бесконечность;
  • сложение бесконечности с бесконечностью противоположного знака;
  • вычисление квадратного корня отрицательного числа[1];
  • логарифмирование отрицательного числа.




--------------------
PM MAIL WWW   Вверх
W4FhLF
Дата 27.5.2012, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



wowka19, используйте assert (http://www.cplusplus.com/reference/clibrary/cassert/assert/) и isfinite (http://en.cppreference.com/w/cpp/numeric/math/isfinite) из стандартной библиотеки для того, чтобы локализовать место, где появляется NaN. Т.е. поставьте побольше этих проверок в коде и запустите программу в дебаг-режиме.


Цитата(mes @  27.5.2012,  09:10 Найти цитируемый пост)
вычисление квадратного корня отрицательного числа[1];
логарифмирование отрицательного числа.


Результатом является комплексное число.
Ну это так, занудствую)



--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
mes
Дата 27.5.2012, 12:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(W4FhLF @  27.5.2012,  10:22 Найти цитируемый пост)
Результатом является комплексное число.
Ну это так, занудствую)

там должна быть пометка : на библиотеках без поддержки комплексных чисел smile
что к сути проблемы тс никакого отношения не имеет.. и загрязнять лишними деталями потому не имеет смысла.. smile



--------------------
PM MAIL WWW   Вверх
wowka19
Дата 27.5.2012, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



В моем случае это скорее всего деления 0 на 0. Но я не могу найти это место так как в отладчик не видит глобальный массив Pair layer[3][9].
Работаю в Eclipse.

PM MAIL   Вверх
borisbn
Дата 27.5.2012, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(wowka19 @  27.5.2012,  00:01 Найти цитируемый пост)
layer[j][0].u = (1 + E) / (1 + I) - 1;

Цитата(wowka19 @  27.5.2012,  00:01 Найти цитируемый пост)
layer[j][8].u = (1 + E) / (1 + I) - 1;

Цитата(wowka19 @  27.5.2012,  00:01 Найти цитируемый пост)
layer[j][i].u = (1 + E) / (1 + I) - 1;

Цитата(wowka19 @  27.5.2012,  00:01 Найти цитируемый пост)
layer[j][0].b  += q * (layer[j][0].a1 * layer[j-1][0].u + layer[j][0].a2 * layer[j-1][1].u) / (2 * layer[j-1][0].v);

Цитата(wowka19 @  27.5.2012,  00:01 Найти цитируемый пост)
layer[j][temp-1].b  += q * (layer[j][temp-1].a1 * layer[j-1][temp-2].u + layer[j][temp-1].a2 * layer[j-1][temp-1].u + layer[j][temp-1].a3 * layer[j-1][temp].u) / (2 * layer[j-1][temp-1].v);

Цитата(wowka19 @  27.5.2012,  00:01 Найти цитируемый пост)
layer[j][i+temp-1].b  += q * (layer[j][i+temp-1].a1 * layer[j-1][i+temp-2].u + layer[j][i+temp-1].a2 * layer[j-1][i+temp-1].u + layer[j][i+temp-1].a3 * layer[j-1][i+temp].u) / (2 * layer[j-1][i+temp-1].v);

Цитата(wowka19 @  27.5.2012,  00:01 Найти цитируемый пост)
layer[j][8].b  += q * (layer[j][8].a1 * layer[j-1][7].u + layer[j][8].a2 * layer[j-1][8].u) / (2 * layer[j-1][8].v);

Цитата(wowka19 @  27.5.2012,  00:01 Найти цитируемый пост)
layer[j][temp+5].b  += q * (layer[j][temp+5].a1 * layer[j-1][temp+4].u + layer[j][temp+5].a2 * layer[j-1][temp+5].u + layer[j][temp+5].a3 * layer[j-1][temp+6].u) / (2 * layer[j-1][temp+5].v);


у тебя всего 8 мест, где производится деление. поставь перед каждым из них проверку на 0.
Код
double denorm = ...;
assert ( fabs( denorm ) > 1e-22 );



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
wowka19
Дата 27.5.2012, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



c = a / b;

а чем в данном случае должен быть denorm: a, b или c ? или проверять нада оба (a и b)?
PM MAIL   Вверх
volatile
Дата 27.5.2012, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(wowka19 @  27.5.2012,  16:00 Найти цитируемый пост)
a, b или c ? 

b
PM MAIL   Вверх
wowka19
Дата 27.5.2012, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



а если использовать isnan для c?
можно ли полагаться на этот макрос?
PM MAIL   Вверх
borisbn
Дата 27.5.2012, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(wowka19 @  27.5.2012,  16:20 Найти цитируемый пост)
а если использовать isnan для c?

можно, но лучше не доводить до этого. не на каждой платформе/системе/компиляторе есть NaN. на какой-то деление на 0 может привести к снятию программы из задач, на какой-то - к прерыванию (если для него не предусмотрен обработчик, то и к зависанию системы).


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 27.5.2012, 20:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(borisbn @  27.5.2012,  18:40 Найти цитируемый пост)
. не на каждой платформе/системе/компиляторе есть NaN. на какой-то деление на 0 может привести к снятию программы из задач, на какой-то - к прерыванию (если для него не предусмотрен обработчик, то и к зависанию системы). 

Вы ничего не перепутали ? а именно целочисленную арифметику с  "плавающей"..



--------------------
PM MAIL WWW   Вверх
borisbn
Дата 27.5.2012, 20:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(mes @  27.5.2012,  20:05 Найти цитируемый пост)
Вы ничего не перепутали ?

думаю - нет. на некоторых платформах вообще нет плавающей арифметики и она эмулируется при помощи целочисленной.
и потом
Цитата
If the second operand of / or % is zero the behavior is undefined

п. 5.6 Multiplicative operators
а раз UB, то м.б. всё, что угодно. нет ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 27.5.2012, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



borisbn, вообщето насколько я знаю, на эту арифметику накладывается другой стандарт, который к стандарту языка отношения не имеет..
но этот вопрос к более просвeщенным smile



Это сообщение отредактировал(а) mes - 28.5.2012, 20:06


--------------------
PM MAIL WWW   Вверх
volatile
Дата 28.5.2012, 00:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(wowka19 @  27.5.2012,  16:20 Найти цитируемый пост)
а если использовать isnan для c?

При делении обычного числа на 0, имхо, вообще nan'а не будет.
Будет inf smile 
PM MAIL   Вверх
borisbn
Дата 28.5.2012, 08:42 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(mes @  27.5.2012,  21:05 Найти цитируемый пост)
 вообщето насколько я знаю, на эту арифметику накладывается другой стандарт, который к стандарту языка отношения не имеет..

Специально заинтересовался этим...
Оказалось, что чёткие ограничения со ссылкой на внешний стандарт IEC 60559 (о котором Вы и говорили) даёт только стандарт Си.
Си++ же (как обычно) "отвечает уклончиво"
Цитата
Treatment of division by zero, forming a remainder using a zero divisor, and all floating point exceptions vary among machines

Ни одной ссылки на внешний стандарт относительно floating point в Си++ нет.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0661 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.