Реализация сети Хэмминга

4 Май
2012

Написал простую реализацию нейронной сети Хэмминга, вдруг пригодится кому-то. Внешне на сеть это не похоже, т.к. я не использую в данном случае понятия нейронных сетей — нейроны, синапсы, аксоны… Но и затрат меньше. Велосипед. Функция распознавания возвращает не массив выходов, а только номер активного.


Предыстория


… Тут бабуля и говорит: «внучек, плохо ноне видеть я стала, Сиси мертвый, Мейсон мутный, а Круз башкир». Открылись старые душевные раны мои, а тело всею волосатостию своей приступило к быстрому седению, Сизиф – никто, а я записал своей бабушке все 2137 серии на VHS.
Не кручинься бабушка, что-нибудь да придумаю. И на третью секунду моих бесконечных размышлений открылся разум мой мыслям, что витают вокруг, и проникла в чело моё идея — ИНС. Будет тебе узнавание да распознавание ликов ясных героев нетленных Барбары и Санты. Дело было, учился я в ПТУ сельском и поймал я раз Хэмминга дикого, пригрозив Кубейсиком своим. И вот настал мой звездный час – порадовать бабусю – это святое, ведь Хэмминг помог бы ей распознавать старых знакомых, показывая лапкой на бабушкин вопрос.
Давно уж сломан старый меч мой деревянный Кубейсик, но на стене, стыдливо прикрыв вуалью пыли ржавые веснушки, расположился силуэт меча железного – Сипипишки. Настало время твое, о, друг мой позабытый. Снял его я со стены, да пыль протер…
Хэмминги – существа пугливые, даже деревяшек боятся, чего уж говорить про железо, в успехе дела ратного своего я не сомневался. Вышел я в чистый гугл, в лицо дул 50-мегабитный теплый ветер, и бахрома запросов вилась по краям моего знамени.
И нашел я своего Хэмминга, наглый попался – не убегал, но и к себе не подпускал, гонял его я в поле часик, пока он не сдался. Связал я его силой мысли, да разглядывать стал – три уха у него, да четыре глаза – а ног и вовсе семь! Что за дивное создание, подумал я, мешается ему все это, да взял и вырубил мечом железным – ни капли крови, вот ведь чудо. Мой Хэмминг стал тощенький и жалобный, но не брыкался, вот тогда его я и отвел к бабуле – теперь газеты читать с пяти метров может. И такое бывает.
А вот и фотокарточка Хэмминга бабулиного:

#include <deque>

class net
{   std::deque<float*> w;    // весовые коэффициенты (== это образцам)
    const unsigned     n;    // количество входов сети
    
    float activation(float v) const
    {   return v>n?n:v<0?0:v;
    }
public:
    net(unsigned numInputs):n(numInputs){}
    ~net(void)
    {   for(unsigned i(0); i<w.size();) delete [] w[i++];
    }
    unsigned learnImage(const float* const image)
    {   w.push_back( (float*)memcpy( new float[n],image, sizeof(float)*n) );
        return w.size();
    }
    unsigned recognizeImage(const float* const image) const
    {   float*  axons( (float*)memset(new float[w.size()],0,sizeof(float)*w.size()) );
        float   sum1(.0), sum2(.0), e(0.95f/w.size());
        unsigned i,j;

        for(i=0; i < w.size(); ++i)    // цикл инициализации сети
        {   for(j=0; j < n; ++j)
                axons[i] += image[j]*w[i][j];
            sum1 += axons[i] = activation(0.5f*(axons[i]+float(n) ) );
        }
                
        while( sum2 != sum1 )        // цикл пока выходы сети изменяются
        {   sum1 = 0.0f * ( sum2 = sum1 );
            for(i=0; i < w.size(); ++i)
                sum1 += axons[i] = activation( axons[i]-e*(sum2-axons[i]) );
        }
        for(i=w.size(); i!=-1u && !axons[i--];);    // поиск активного аксона сети 
        delete [] axons;
        return i;
    }
/*  // аналогично recognizeImage, только, судя по алгоритму,
    // можно обойтись только измерением максимального выхода
    // если максимальных > 1, то однозначного ответа сеть не даст
    unsigned recognizeImageFast(const float* const image) const
    {   float sumMax(-1e+37f);  // максимальная сумма на выходе 
        unsigned iMax(-1);        // индекс максимального совпадения образов
        for(unsigned i=0; i < w.size(); ++i)    // цикл инициализации сети
        {   float   sum1(0.0f);
        for(unsigned j=0; j < n; ++j)
                sum1 += image[j]*w[i][j];
            sum1 = activation(0.5f*(sum1+float(n)));
            if (sum1 > sumMax)
            {    sumMax = sum1;
                iMax = i;
            }
            else if( sum1 == sumMax )
            {    iMax = -1;                
            }
        }
        return iMax;
    }
*/
};

int _tmain(int argc, _TCHAR* argv[])
{  // входы можно сделать и целочисленными, роли играть не будет
    float a1[4][15] = {{1.,1.,1.,  1.,-1.,-1.,  1.,-1.,-1.,  1.,-1.,-1.,  1.,1.,1.},// символ С
                        {1.,1.,1.,  1.,-1.,-1.,  1.,1.,-1.,   1.,-1.,-1.,  1.,1.,1.}, // Символ E
                        {1.,1.,1.,  1.,-1.,1.,   1.,-1.,1.,   1.,-1.,1.,   1.,1.,1.}, // Символ О
                        {1.,1.,1.,  1.,-1.,1.,   1.,-1.,1.,   1.,-1.,1.,   1.,1.,1.}  // искаженный
                      };

    net n(15);
    n.learnImage( a1[0] );
    n.learnImage( a1[1] );    
    n.learnImage( a1[2] );
    return n.recognizeImage( a1[3] );
}

По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх