Rozpoznawanie pisma ręcznego przy pomocy sieci neuronowej Kohonena

Podobne dokumenty
Instrukcja realizacji ćwiczenia

8. Neuron z ciągłą funkcją aktywacji.

Lekcja 5: Sieć Kohonena i sieć ART

IMPLEMENTACJA SIECI NEURONOWYCH MLP Z WALIDACJĄ KRZYŻOWĄ

Algorytmy decyzyjne będące alternatywą dla sieci neuronowych

Zastosowanie metod eksploracji danych Data Mining w badaniach ekonomicznych SAS Enterprise Miner. rok akademicki 2014/2015

S O M SELF-ORGANIZING MAPS. Przemysław Szczepańczyk Łukasz Myszor

Sztuczna Inteligencja Tematy projektów Sieci Neuronowe

Programowanie strukturalne i obiektowe. Funkcje

Język ludzki kod maszynowy

1 Podstawy c++ w pigułce.

METODY INŻYNIERII WIEDZY KNOWLEDGE ENGINEERING AND DATA MINING

Uczenie się pojedynczego neuronu. Jeśli zastosowana zostanie funkcja bipolarna s y: y=-1 gdy z<0 y=1 gdy z>=0. Wówczas: W 1 x 1 + w 2 x 2 + = 0

Podstawy Programowania C++

Sztuczne sieci neuronowe. Krzysztof A. Cyran POLITECHNIKA ŚLĄSKA Instytut Informatyki, p. 335

Konstrukcje warunkowe Pętle

Najprostsze modele sieci z rekurencją. sieci Hopfielda; sieci uczone regułą Hebba; sieć Hamminga;

ANALIZA I INDEKSOWANIE MULTIMEDIÓW (AIM)

Oprogramowanie Systemów Obrazowania SIECI NEURONOWE

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

5.4. Tworzymy formularze

System wizyjny OMRON Xpectia FZx

Pętle. Dodał Administrator niedziela, 14 marzec :27

Elementy Sztucznej Inteligencji. Sztuczne sieci neuronowe cz. 2

Informatyka II. Laboratorium Aplikacja okienkowa

Zastosowania sieci neuronowych

Metody Sztucznej Inteligencji II

Podstawy Programowania Podstawowa składnia języka C++

Obliczenia inteligentne Zadanie 4

Asocjacyjna reprezentacja danych i wnioskowanie

Sieć Hopfielda. Sieci rekurencyjne. Ewa Adamus. ZUT Wydział Informatyki Instytut Sztucznej Inteligencji i Metod Matematycznych.

Strategia "dziel i zwyciężaj"

Uczenie sieci typu MLP

Algorytm wstecznej propagacji błędów dla sieci RBF Michał Bereta

1 Podstawy c++ w pigułce.

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Podstawy programowania skrót z wykładów:

SIECI KOHONENA UCZENIE BEZ NAUCZYCIELA JOANNA GRABSKA-CHRZĄSTOWSKA

Zagadnienia optymalizacji i aproksymacji. Sieci neuronowe.

Sieć przesyłająca żetony CP (counter propagation)

Układy VLSI Bramki 1.0

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

4. Funkcje. Przykłady

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 3

I. Podstawy języka C powtórka

Podstawy sztucznej inteligencji

Budowa i generowanie planszy

Zastosowania sieci neuronowych

Rekurencja (rekursja)

Przykładowa dostępna aplikacja w Visual Studio - krok po kroku

Zadanie 1. Zmiana systemów. Zadanie 2. Szyfr Cezara. Zadanie 3. Czy liczba jest doskonała. Zadanie 4. Rozkład liczby na czynniki pierwsze Zadanie 5.

Wstęp do sieci neuronowych, wykład 07 Uczenie nienadzorowane.

Metody systemowe i decyzyjne w informatyce

Wstęp do sieci neuronowych, wykład 02 Perceptrony c.d. Maszyna liniowa.

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

METODY INŻYNIERII WIEDZY

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Optymalizacja systemów

METODY INŻYNIERII WIEDZY

Lokalizacja jest to położenie geograficzne zajmowane przez aparat. Miejsce, w którym zainstalowane jest to urządzenie.

Implementacja filtru Canny ego

P R Z E T W A R Z A N I E S Y G N A Ł Ó W B I O M E T R Y C Z N Y C H

Wstęp do sieci neuronowych, wykład 02 Perceptrony c.d. Maszyna liniowa.

METODY INŻYNIERII WIEDZY KNOWLEDGE ENGINEERING AND DATA MINING

wagi cyfry pozycje

Wstęp do sieci neuronowych, wykład 04. Skierowane sieci neuronowe. Algorytmy konstrukcyjne dla sieci skierowanych

Podstawy programowania. Wykład Pętle. Tablice. Krzysztof Banaś Podstawy programowania 1

Inteligentne systemy przeciw atakom sieciowym

Programowanie dynamiczne

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

Sztuczne sieci neuronowe i sztuczna immunologia jako klasyfikatory danych. Dariusz Badura Letnia Szkoła Instytutu Matematyki 2010

13. Równania różniczkowe - portrety fazowe

Zadanie 1. Suma silni (11 pkt)

Czym jest wykrywanie kolizji. Elementarne metody detekcji kolizji. Trochę praktyki: Jak przygotować Visual Studio 2010 do pracy z XNA pod Windows

Automatyczna klasyfikacja zespołów QRS

Klasa 2 INFORMATYKA. dla szkół ponadgimnazjalnych zakres rozszerzony. Założone osiągnięcia ucznia wymagania edukacyjne na. poszczególne oceny

Złożoność obliczeniowa zadania, zestaw 2

Java Podstawy. Michał Bereta

Analiza algorytmów zadania podstawowe

Instytut Fizyki Politechniki Łódzkiej Laboratorium Metod Analizy Danych Doświadczalnych Ćwiczenie 3 Generator liczb losowych o rozkładzie Rayleigha.

Sztuczne sieci neuronowe Ćwiczenia. Piotr Fulmański, Marta Grzanek

KRYPTOGRAFIA I OCHRONA DANYCH PROJEKT

1. Informatyka - dyscyplina naukowa i techniczna zajmująca się przetwarzaniem informacji.

Księgarnia internetowa Lubię to!» Nasza społeczność

Sieci Kohonena Grupowanie

Algorytmy i struktury danych. Drzewa: BST, kopce. Letnie Warsztaty Matematyczno-Informatyczne

Temat: Sieci neuronowe oraz technologia CUDA

dokumentacja Edytor Bazy Zmiennych Edytor Bazy Zmiennych Podręcznik użytkownika

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

ZACHODNIOPOMORSKI UNIWERSYTET TECHNOLOGICZNY W SZCZECINIE

Krok 1: Wzorzec księgowania faktury sprzedaży

Rozdział 1 Sztuczne sieci neuronowe. Materiały do zajęć dydaktycznych - na podstawie dokumentacji programu Matlab opracował Dariusz Grzesiak

Ćwiczenie: JavaScript Cookies (3x45 minut)

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

- Narzędzie Windows Forms. - Przykładowe aplikacje. Wyższa Metody Szkoła programowania Techniczno Ekonomiczna 1 w Świdnicy

Definicje. Algorytm to:

ĆWICZENIE 5: Sztuczne sieci neuronowe

Transkrypt:

Rozpoznawanie pisma ręcznego przy pomocy sieci neuronowej Kohonena Automatyczne rozpoznawanie pisma ręcznego jest problemem bardzo trudnym i od wielu lat nie do końca jeszcze rozwiązanym. Złożoność tego zagadnienia potęguje przede wszystkim fakt, iż dany znak może być napisany różnymi charakterami pisma, więc litery za każdym razem wyglądają nieco inaczej. Łączy je jednak pewne podobieństwo do znaku określanego jako wzorzec. W niniejszym artykule przedstawię próbę rozwiązania tego problemu przy pomocy sieci neuronowej Kohonena. Sieć Kohonena W 1982 roku fiński uczony Teuvo Kohonen zaproponował sieć neuronową liniową, w której występuje czynnik konkurencji, a uczenie odbywa się bez nadzoru. Rysunek 1 przedstawia schemat budowy omawianej sieci. Rysunek 1. Topologia sieci Kohonena. Informacja, którą chcemy poddać przetwarzaniu, podawana jest na wejście sieci. Następnie sygnały te ulegają przemnożeniu przez współczynniki wagowe - inne dla każdego neuronu. Na wyjściu otrzymujemy zestaw neuronów, których pobudzenie uzależnione jest od stopnia zgodności sygnału wejściowego z wewnętrznym wzorcem sieci. Sygnał wyjściowy danego neuronu jest więc tym silniejszy, im bardziej jego zestaw wartości wagowych przypomina wartości sygnału wejściowego. W sieci Kohonena liczy się tylko zwycięski neuron, czyli ten o największej wartości wyjściowej. Jego uznaje się za reprezentanta danej klasy zjawiska (np. 5 neuron rozpoznaje literę A).

Cały proces uczenia sieci polega na takim doborze wartości wag neuronów, aby sieć, jako całość, prawidłowo realizowała postawione przed nią zadania. Na początku uczenia wszystkie wagi inicjalizowane są w sposób losowy. Następnie na wejścia sieci podawane są sygnały reprezentujące daną klasę badanego zjawiska, po czym sprawdza się, który neuron ma największe pobudzenie. Neuron ten uznaje się za zwycięzcę i jego, wraz z neuronami należącymi do jego sąsiedztwa, poddaje się procesowi uczenia, czyli modyfikuje się ich zestawy wartości wagowych. Najsilniej zmieniane są wagi zwycięskiego neuronu, natomiast wagi neuronów sąsiednich zmieniane są słabiej. Rozmiar sąsiedztwa określa projektant sieci. Nie może być to wartość zbyt duża, a w szczególnym przypadku może przyjmować wartość zerową. Warto w tym miejscu zauważyć, że nawet słaba początkowa skłonność jakiegoś neuronu do rozpoznawania danej klasy obiektów może zostać wychwycona i wzmocniona podczas procesu uczenia. Zatem wagi zwycięskiego neuronu aktualizuje się w taki sposób, aby reagował on na przedstawioną mu prezentację jeszcze silniej. Umacnia on w ten sposób swoją zwycięską pozycję. Proces ten zachodzi do momentu, aż kolejne prezentacje nie powodują zmian wartości wagowych w znaczący sposób. Uznaje się wtedy, że neuron osiągnął punkt stabilny. Wagi te modyfikuje się w taki sposób, aby po każdej kolejnej prezentacji zestaw wartości wagowych lekko przesunąć w kierunku zestawu wartości wejściowych. Efekt ten można uzyskać poprzez odjęcie od wektora wejściowego wektora wag, a następnie część tej różnicy dodać do aktualnego wektora wag. Definicję tą ilustruje poniższy wzór. w i+1 = w i + (x - w i ) gdzie: w i+1 - wektor wag w (i+1)-ej (tj. bieżącej) prezentacji, w i - wektor wag w i-tej (tj. poprzedniej) prezentacji, x - wektor wartości wejściowych, - współczynnik proporcjonalności, zwykle mniejszy od 1. Aby opis algorytmu uczenia sieci był pełny, należy omówić jeszcze jeden bardzo ważny proces. Zauważmy, że podczas uczenia sieci może dojść do bardzo niekorzystnego zjawiska polegającego na tym, że niektóre neurony mogą wykazywać nadaktywność, czyli będą zwyciężać dla więcej niż jednego zestawu wejściowego. Inne zaś neurony mogą żadnej rywalizacji nie wygrać. Powodowałoby to nadmierne przeciążanie neuronów uczących się, co w konsekwencji prowadziłoby do złej pracy sieci. Dlatego opracowano mechanizm nazwany forsowaniem zwycięzcy, który rozwiązuje ten problem. Najogólniej polega on na wyszukaniu wśród neuronów, które jeszcze nie zwyciężyły w żadnym zestawie uczącym, neuronu o największej aktywacji. Ten właśnie neuron poddaje się uczeniu. Trzeba dodać, że powyższy algorytm uczenia sieci Kohonena przyniesie prawidłowe rezultaty, jeśli wartości wejściowe oraz wagi będą znormalizowane. Wartości wejściowe muszą więc należeć do przedziału [-1, 1] oraz długość wektora wejściowego musi być taka sama - najczęściej równa 1. Wektory wag, podobnie jak wejścia, muszą zostać zredukowane do jednostkowej długości.

Realizacja rozpoznawania pisma ręcznego Aby obraz litery można było przetworzyć w sieci neuronowej, musimy najpierw zamienić go na postać binarną. Rysunek 2 przedstawia sposób w jaki się to dokonuje. Rysunek 2. Binaryzacja obrazu litery. Na obraz litery (Rysunek 2a) nałożona jest siatka prostokątna (Rysunek 2b). Następnie pola, przez które przechodzi kreska litery, są zaczerniane, a pozostałe pola pozostają białe. W ten sposób powstaje obraz binarny (Rysunek 2c). Taki obraz możemy wprowadzić na wejście sieci neuronowej. Jeśli sieć neuronowa ma tyle neuronów wejściowych ile pikseli posiada binarny obraz litery, wtedy każdemu pikselowi możemy przypisać wartość liczbową i podać ją na poszczególne neurony wejściowe sieci. W naszym przykładowym projekcie, który jest ilustracją omawianego tematu, przyjmujemy, że rozmiar siatki dzielącej literę na poszczególne piksele, wynosi 5 pikseli szerokości i 7 pikseli wysokości. Daje to łącznie 35 pikseli zapisanego w postaci binarnej znaku. Liczba ta wyznacza ilość neuronów wejściowych sieci Kohonena, którą użyjemy w przykładzie. Z kolei ilość neuronów wyjściowych ustalamy na 26, ponieważ chcemy, aby tyle właśnie liter sieć rozpoznawała. Będą to wszystkie litery alfabetu łacińskiego. Każdy neuron wyjściowy będzie reprezentował jedną literę. Jego pobudzenie oznaczać będzie rozpoznanie odpowiadającej mu litery. Natomiast to, który neuron będzie odpowiadał za jaką literę, sieć ustali sama podczas procesu uczenia. Dla zilustrowania omawianych w artykule zagadnień stworzyłem program działający w systemie Windows. Program napisany jest w języku C/C++ i wykorzystuje funkcje API Windows. Do plików źródłowych dołączony jest również plik projektu dla kompilatora MS Visual C++ oraz skompilowana wersja programu pismo. Źródła programu można także skompilować wykorzystując jeden z darmowych kompilatorów dla platformy Windows (np. Borland C++ 5.5).

Opis programu pismo Program pismo składa się z jednego okna. Możemy go zobaczyć na rysunku 3. Rysunek 3. Okno główne programu pismo. Podczas uruchamiania programu wczytywany jest plik data.txt, zawierający zbiór uczący dla sieci neuronowej. Składają się na niego wzorce poszczególnych liter. Użytkownik ma możliwość modyfikacji tego zbioru. Może on w tym celu zaznaczyć przycisk Wzorce, a następnie wybrać na liście żądaną literę. Następnie, w górnej części okna programu, na oknietablicy narysować literę. Po naciśnięciu na przycisk Zapisz wzorzec zaznaczonej na liście litery zostanie uaktualniony według znaku narysowanego przez użytkownika. Wybierając opcję Rozpoznawanie przechodzimy do trybu rozpoznawania pisma. Ważną czynnością, którą musimy wykonać na poczatku, jest uczenie sieci. Dokonujemy tego naciskając na przycisk Trenuj sieć. Po tej czynności możemy narysować literę na okienku-tablicy. Po wciśnięciu

przycisku Rozpoznaj otrzymamy wynik przetwarzania sieci Kohonena. Pod okienkiem, gdzie rysujemy literę, widoczny jest napis informujący nas, jaką literę program rozpoznał. Binaryzacja obrazu litery Wspomnieliśmy już, że narysowaną literę należy zamienić na obraz binarny. Dokonujemy tego przy pomocy kodu z Listingu 1. Listing 1. Binaryzacja obrazu litery for(i=0; i<cxclient; i++) if(!isvlineclear(hdc, i)) downsampleleft = i; break; for(i=cxclient; i>0; i--) if(!isvlineclear(hdc, i)) downsampleright = i; break; for(i=0; i<cyclient; i++) if(!ishlineclear(hdc, i)) downsampletop = i; break; for(i=cxclient; i>0; i--) if(!ishlineclear(hdc, i)) downsamplebottom = i; break; // próbkowanie widthrect = (downsampleright - downsampleleft)/downsample_width; heightrect = (downsamplebottom - downsampletop)/downsample_height; idx=0; for(i=0; i<downsample_height; i++) for(j=0; j<downsample_width; j++)

rect.left = downsampleleft + j*widthrect; rect.right = rect.left + widthrect; rect.top = downsampletop + i*heightrect; rect.bottom = rect.top + heightrect; if(isrectclear(hdc, rect)) sample[idx++] = MIN_INPUT; else sample[idx++] = MAX_INPUT; Najpierw ustalamy granice w jakich znajduje się badana przez nas litera. Lewą, prawą, górną oraz dolną granicę określają zmienne downsampleleft, downsampleright, downsampletop, downsamplebottom. Mając określony obszar w jakim znajduje się litera, dzielimy go na 5 kolumn i 7 rzędów. Otrzymujemy w ten sposób 35 prostokątów, w których badamy, czy przechodzi przez nie fragment litery. Jeśli przez dany prostokąt litera przechodzi, wtedy uznajemy go za czarny "piksel" i odpowiadającemu mu neuronowi nadajemy wartość wejściową 0,5. W przeciwnym przypadku neuronowi wejściowemu przypisujemy wartość -0,5. Listing 2 obrazuje, w jaki sposób zaimplementowane są funkcje: IsHLineClear, IsVLineClear, IsRectClear. Wszystkie one przy pomocy funkcji Windows GetPixel sprawdzają kolor pojedynczego piksela. Jeśli przynajmniej jeden piksel jest czarny, wtedy funkcje zwracają FALSE w przeciwnym przypadku TRUE. Listing 2. Implementacja funkcji IsHLineClear, IsVLineClear, IsRectClear BOOL IsHLineClear(HDC hdc, int line) int j; for(j=0; j<cxclient; j++) if(getpixel(hdc, j, line) == 0) return FALSE; return TRUE; BOOL IsVLineClear(HDC hdc, int line) int j; for(j=0; j<cyclient; j++) if(getpixel(hdc, line, j) == 0) return FALSE;

return TRUE; BOOL IsRectClear(HDC hdc, RECT rect) int i, j; for(i=rect.left; i<rect.right; i++) for(j=rect.top; j<rect.bottom; j++) if(getpixel(hdc, i, j) == 0) return FALSE; return TRUE; Rozpoznawanie litery Wiemy już, że aby zapewnić sieci Kohonena prawidłową pracę, należy jej dane wejściowe poddać normalizacji. Dokonujemy tego w sposób przedstawiony na listingu 3. Listing 3. Normalizacja danych wejściowych void Kohonen::NormalizeInput(double *input, double *normfac) double length; length = VectorLength(NUMBER_INPUT, input); if(length < 1.e-30) length = 1.e-30 ; *normfac = 1.0 / sqrt(length); double Kohonen::VectorLength (int n, double *vec ) double sum = 0.0; for (int i=0;i<n;i++ ) sum += vec[i] * vec[i]; return sum; Głównym celem procedury normalizacyjnej NormalizeInput jest wyliczenie wartości normfac używanej w dalszych obliczeniach. Funkcja VectorLength oblicza kwadrat długości wektora. Następnie możemy przyjrzeć się jak sieć wylicza zwycięski neuron podczas procesu rozpoznawania pisma. Funkcję Winner realizującą to zadanie możemy prześledzić na listingu 4.

Listing 4. Funkcja obliczająca zwycięski neuron int Kohonen::Winner(double *input, double *normfac) int i, win=0; double biggest; double *optr; NormalizeInput(input, normfac); biggest = -1.E30; for (i=0; i<number_output; i++) optr = outputweights[i]; output[i] = dotproduct (NUMBER_INPUT, input, optr ) * (*normfac); output[i] = 0.5 * (output[i] + 1.0) ; if ( output[i] > biggest biggest = output[i] ; win = i ; if ( output[i] > 1.0 ) output[i] = 1.0; if ( output[i] < 0.0 ) output[i] = 0.0; return win ; Każdą wartość wyjściową output[i] wyliczamy przy pomocy funkcji dotproduct. Niezbędnymi parametrami są: wektor danych wejściowych, zestaw wag łączących neurony wejściowe z obliczanym i-tym neuronem wyjściowym oraz wartość normalizacyjna. Funkcja ta realizuje mnożenie wartości wejściowych przez odpowiednie wagi. Wykorzystywane tutaj zestawy wag sieci wyznaczane są w trakcie procesu uczenia. Uczenie sieci Główną procedurę uczącą, stanowiącą najważniejszy element prawidłowego funkcjonowania sieci neuronowej Kohonena, możemy prześledzić na listingu 5. Listing 5. Procedura uczenia sieci Kohonena BOOL Kohonen::Learn(TrainingSet *tptr) (...) nwts = NUMBER_INPUT * NUMBER_OUTPUT;< BR > rate = LEARN_RATE; Initialize(); best_err = 1.e30;

// główna pętla ucząca n_retry = 0; for (iter=0; ; iter++) EvaluateErrors(tptr, rate, won, &bigerr, correc); s_neterr = bigerr ; if (s_neterr < best_err) best_err = s_neterr ; CopyWeights(bestnet, this); winners = 0; for (i=0; i<number_output; i++ ) if (won[i]!= 0) winners++; if (bigerr < QUIT_ERROR) break ; if ((winners < NUMBER_OUTPUT) && (winners < tptr->ntrain)) ForceWin(tptr, won); continue; AdjustWeights(rate, won, &bigcorr, correc); if (bigcorr < 1.e-5) if (++n_retry > RETRIES) break; Initialize(); iter = -1; rate = LEARN_RATE; continue; if (rate > 0.01) rate *= REDUCTION; (...) Jest ona stosunkowo długa, dlatego Listing 5 zawiera jej najważniejsze fragmenty. W funkcji Initialize wszystkie wagi przyjmują wartości losowe po czym są normalizowane. Następnie w pętli dokonywane jest uczenie sieci. Pierwszą z funkcji jest EvaluateErrors. Jest ona miarą dostosowania aktualnych wag neuronu wyjściowego do rozpoznawania wzorca zawartego w danych wejściowych. Jeśli wagi te nie są jeszcze dostosowane, wtedy zmienna bigerr osiąga duże wartości. Z chwilą, gdy wagi w trakcie uczenia zmieniają się i są coraz bardziej dostosowane do prawidłowego rozpoznawania wzorca, zmienna bigerr zmniejsza się. Gdy osiągnie wartość mniejszą niż QUIT_ERROR uczenie danego neuronu uznajemy za zakończone. Następnie zliczamy ilość nauczonych już neuronów, po czym wywołujemy funkcję ForceWin. Wykonuje ona kolejno następujące czynności:

wybiera wzorzec wejściowy, który nie ma jeszcze "swojego" neuronu wyjściowego, dla wzorca z poprzedniego punktu wybierany jest neuron o największej aktywności - ale jest to neuron wybrany spośród tych, które dotychczas jeszcze nie zwyciężyły dla żadnego przypadku uczącego, dla neuronu z poprzedniego punktu modyfikowane są jego wagi. Końcowym etapem uczenia jest normalizacja wag, która wpływa dodatnio na proces rozpoznawania wzorców. Realizowana jest ona poprzez funkcję AdjustWeights. Do pełnego przestudiowania i analizy kodu realizującego działanie sieci neuronowej Kohonena odsyłam Czytelnika do kodów źródłowych programu pismo. Podsumowanie Zawarte w artykule kody źródłowe, przede wszystkim pliki Kohonen.h i Kohonen.cpp, są uniwersalne. Można je zastosować nie tylko do rozpoznawania znaków graficznych, ale także do wielu innych problemów (rozpoznawanie mowy, inne problemy klasyfikacji). Myślę że analiza kodu dołączonego do artykułu pozwoli lepiej zagłębić się w tajniki sieci neuronowej Kohonena.