W poniższym artykule wykażę bezsensowność używania głębokiego uczenia (ang. deep learning) czy sieci neuronowych (ang. neural network) do rozpoznawania obrazów na przykładzie rozpoznawania pisma odręcznego ze zbioru znaków MNIST i udowodnię to w praktyce

Wykażę także, że do rozpoznawania odręcznie pisanych cyfr – czy szerzej obrazu – nie jest konieczne uczenie systemu za pomocą dziesiątek tysięcy próbek. Wystarczy jedna lub najwyżej kilka, a dodatkowo nie będzie miało znaczenia, jakiej wielkości jest zarówno próbka służąca do uczenia systemu, jak i ta do badania jego skuteczności. Nie będą też miały znaczenia wyśrodkowanie, wielkość, kąt obrotu czy grubość pisanych linii, co ma kolosalne znaczenie w metodach rozpoznawania obrazu opartych na uczeniu maszynowym czy deep learning.

Robot zamiast patyka

Jak wiemy, każdy obraz w komputerze składa się z pojedynczych punktów (Max Planck mówił, że cały nasz świat składa się z pikseli), które połączone w odpowiedni sposób tworzą obraz. Tak samo jest ze znakami tworzącymi cyfry w bazie danych znaków MNIST.

Zbiór znaków MNIST i jego klasyfikacja jest swego rodzaju abecadłem dla każdego początkującego studenta czy osoby rozpoczynającej zabawę z głębokim uczeniem czy sieciami neuronowymi.

Zbiór ten został skompletowany przez Yanna LeCuna i zawiera 70 tysięcy obrazów w rozdzielczości 28×28 pikseli w 255 odcieniach szarości. Przyjęto, że 60 tysięcy obiektów stanowi zbiór treningowy, a 10 tysięcy są to elementy ze zbioru testowego. Obraz (w tym wypadku cyfra od 0 do 9) reprezentowany jest jako macierz 2D o wymiarach 28×28, w której wartości 0-255 reprezentują odcień szarości piksela. Łatwiejszą formą do przetwarzania przez algorytmy uczenia maszynowego jest postać wektora, którą otrzymujemy, odczytując wartości pikseli z obrazu wiersz po wierszu. Stąd otrzymamy 784-wymiarowy wektor (28×28=784) reprezentujący jeden obrazek z cyfrą. Z tego wynika, że cały zbiór treningowy to macierz o wymiarach 60 000×784.

Teraz tylko wystarczy użyć dostępnych w chmurze narzędzi typu TensorFlow, pobrać kilka plików w Pythonie, poczytać o wielu mądrych metodach uczenia sieci, kupić o tym kilka książek albo po prostu pobrać gotowca, co robi większość, i stworzyć swoją pierwszą sieć neuronową.

Wow, do jednego znaku składającego się z 28 linii po 28 punktów, specjalnie przygotowanego do rozpoznawania – czyli odpowiednio wycentrowanego, wyskalowanego w idealnej rozdzielczości – tęgie głowy wymyśliły, że skoro nasz ludzki mózg składający się z neuronów potrafi to odczytać, to stworzymy minielektroniczny mózg ze sztucznych neuronów, który też to odczyta. I udało się! Wyniki są prawie idealne, bliskie 100 proc., ale…

Używanie sieci neuronowych do rozpoznawania cyfr jest jak zastąpienie patyka służącego do pisania cyfr na piasku na plaży wyspecjalizowanym robotem wybierającym z plaży po jednym ziarnku piasku w celu otrzymania tego samego wzoru!

Czy myślicie, że nasz mózg, patrząc na cyfrę, tnie ją na paski, piksele, wektory i analizuje punkt po punkcie? Jeżeli przyjmiemy wyliczenia dr. Rogera Clarka, że rozdzielczość naszego wzroku to 576 megapikseli (tak naprawdę nie więcej niż 20 megapikseli w centrum patrzenia), to naprawdę nie ma takiego napoju energetycznego, który wspomoże nasz mózg w takiej pracy.

Co więcej – czy na tym ma polegać uczenie? Czy my musimy zobaczyć 60 tysięcy znaków, aby się ich nauczyć, czy może nauczycielka w szkole podstawowej zapisała taki znak raz i kazała zapamiętać?

Czy jeżeli pokaże wam jeden raz pewien znak, np.:

to rozpoznacie ten poniżej jako inny?

Oczywiście jest troszkę inny, ale gdy obok niego mamy określony zbiór – np. cyfr – i ten znak, to każdy ten znak rozpozna, mimo że widzi go pierwszy raz. Nie będzie też miał problemów z jego narysowaniem po chwili w innym miejscu.

I teraz najważniejsze – jak zapamiętujemy ten znak? Piksel po pikselu, 784 punkty? A co, gdyby to był znak w rozdzielczości 256 na 256 punktów, czyli takiej, jaką ma zwykła ikonka na naszym domowym komputerze, składający się z 65 536 punktów?

Nie, nasz mózg jest wspaniały, jeżeli chodzi o upraszczanie wszelkich danych, jakie do niego dochodzą, a tym bardziej, jeśli to są tak ogromne dane jak dane o obrazie.

Pomyślmy przez chwilę, jak słowami opisalibyśmy ten znak komuś innemu, a otrzymamy od razu jedną z metod uproszczonego zapamiętywania – pewnie opiszemy to mniej więcej tak: dwa odcinki, poziomy i pionowy, pierwszy odcinek jest poziomy, a na jego końcu pod kątem 90 stopni styka się z odcinkiem pionowym.

Zauważmy, że do opisu znaku wystarczą w tym przypadku praktycznie cztery informacje , a nie informacja o 784 punktach w 255 odcieniach szarości. Co więcej, tak zapisana informacja jest niezależna od wielkości znaku.

Dokładnie takiej samej metody możemy użyć do zapamiętywania każdego znaku, cyfry, ale i przedmiotu na obrazie – niezależnie od tego, czy przedmiot będzie w przestrzeni dwu- czy trójwymiarowej (w dużym uproszczeniu, gdyż rozpoznawanie obrazu w przestrzeni 2D czy nawet 3D wymaga dodatkowych czynności – ale to temat na osobny artykuł).

Odchudzanie cyfr

Powtórzmy więc: na czym polega ta prosta metoda?

Zapamiętujemy:

  1. punkty startu
  2. kąt startu
  3. typ odcinka
  4. kąt wygięcia odcinka
  5. kąt połączenia odcinka.

Jak widać, według mnie ludzki mózg zapamiętuje po prostu podstawowe kształty i sposób ich połączenia. Wykrywamy łatwo linie proste, koła, łuki mniej lub bardziej wygięte i ich wzajemne położenie czy połączenie.

Zobaczmy na przykładzie cyfry 6 (polecam też zobaczyć wszystko na dołączonym poniżej filmie):

Cyfrę 6 możemy rozpoznać na kilka sposobów – tak naprawdę składa się z kilku odcinków połączonych ze sobą zawsze pod dodatnim kątem albo z kilku odcinków tworzących na dole koło, albo z jednego odcinka tworzącego swoistego ślimaka, w tym wypadku zakreślającego 476 stopni od początku na górze do końca na dole.

Taka metoda ma też dodatkową zaletę: nie ma znaczenia, czy obraz jest obrócony o praktycznie dowolny kąt, nie ma znaczenia grubość linii, nie ma znaczenia wielkość obrazu czy jego położenie, czyli wszystko to, co wpływa bardzo negatywnie na efekty przy metodach głębokiego uczenia.
Przecież ten sam znak narysowany pod kątem 45 stopni wszystkie opisane powyżej parametry ma identyczne.

Uważny czytelnik pewnie od razu wychwyci: a co z cyfrą 6 i 9? – do pewnego kąta cyfra 6 jest szóstką, ale pod pewnym kątem jest już dziewiątką.

Zobaczcie na dołączonym filmie, jak wielkie problemy z rozpoznawaniem mają standardowe metody oparte na głębokim uczeniu, gdy napiszemy cyfry pod kątem. Pamiętajmy też, że zestaw znaków MNIST jest już specjalnie przygotowany, znaki są odpowiednio wyskalowane, wycentrowane, zawsze w identycznej rozdzielczości 28×28 itd.

Adres filmu na Youtube: https://youtu.be/do9PM2PtW0M

Jak to się robi w praktyce.
Źródło: Artur Majtczak / YouTube

W tym miejscu sprawniejsi programiści zwrócą pewnie uwagę na jeden wielki problem.

Ludzki mózg widzi po prostu całość, cały obraz, linie, koła – to proste, ale komputer widzi w jednym momencie właściwie tylko jeden punkt, jeden z tych 784 punktów, więc jak to oprogramować, jak wykryć te linie? Dodatkowym problemem jest to, że niektóre cyfry są pisane grubą czcionką, więc gdy widzimy jeden punkt, a obok niego wszędzie są też zamalowane punkty, to skąd wiadomo, w którą stronę jest linia?

Tak widzi komputer

Możemy użyć w przypadku znaków dwóch technik:

  1. Proste odchudzanie, aż otrzymamy linię grubości punktu (punkt to może być piksel, ale też mogą to być 4 piksele, w zależności od potrzeb);
  2. „metoda szybkiego wtrysku” – wyobrażamy sobie, że musimy zamalować daną cyfrę kolorem (taka funkcja fill), wpuszczamy w jednym punkcie farbę i patrzymy, gdzie może się rozprzestrzenić, ale tak, jakby była pod ciśnieniem, więc np. w cyfrze 8 na skrzyżowaniu nie rozlewa się na wszystkie strony, tylko przelatuje na przeciwną stronę „skrzyżowania” i leci dalej.

Po odchudzeniu, gdy mamy już jedną linię, łatwo wyodrębniamy proste, krzywe, kąty i to zapamiętujemy.

Samą metodę obmyśliłem ponad 20 lat temu, przed napisaniem tego artykułu postanowiłem napisać prosty programik sprawdzający, czy miałem rację. Po kilku dniach otrzymałem program, niedoskonały, bo nie robię przecież programu komercyjnego, ale wystarczający do potwierdzenia, że to działa i ma wykrywalność znaków ponad 97 proc., więc pewnie po kilku dniach pracy można by dojść i do 99 proc.

Abecadło programisty

Z drugiej strony można powiedzieć, że przecież metody opisywane wszędzie w internecie – te wykorzystujące sieci neuronowe – robią to z taką samą skutecznością, więc po co wyważać otwarte drzwi i robić to inaczej?

Tak i nie – ta metoda nie wymaga uczenia, superkomputerów, nie musi być to zestaw tylko 10 znaków, może ich być dowolna liczba, nie muszą być to znaki w formacie 28×28, tylko 450×725, a właściwie każdy znak może być w dowolnym, za każdym razem innym formacie, znaki mogą być obracane. Dodanie kolejnych znaków nie wymaga ponownego uczenia sieci, nie ma problemu, żeby taki algorytm rozpoznawał też dodatkowo znaki wydrukowane w prawie dowolnych czcionkach dostępnych na komputerze oczywiście bez potrzeby jakiegokolwiek dodatkowego ich uczenia.

Niektórzy pewnie zaraz odpowiedzą, że tak naprawdę chodzi tylko o pokazanie na MNIST sposobu uczenia sieci neuronowych, ale nie mogę się z tym zgodzić – to naprawdę nie ma sensu! Nie uczymy się przecież na zajęciach ZPT przybijania gwoździ kulą do rozbiórek domów.

Zostawcie już te znaki, bo kompletnie nie ma sensu używanie takich metod do rozpoznawania obrazu.

Wywalcie te wszystkie grube książki o deep learning, zostawcie to supernarzędzie w chmurach, usiądźcie do zwykłego obmyślania coraz lepszych algorytmów sami – czas na abecadło programisty.

Do napisania tego artykułu zostałem zmuszony, gdyż podczas pracy nad naszym projektem silnej sztucznej inteligencji SaraAI.com jestem ciągle zasypywany pytaniami, jakich używam metod głębokiego uczenia, jakich metod NLP, itd. – a gdy odpowiadam, że nie używam bezpośrednio praktycznie żadnych znanych metod, widzę tylko zdziwienie i powątpiewanie na twarzach rozmówców. Dlatego chciałem wykazać, że nie zawsze musimy się trzymać ogólnie przyjętej linii rozwiązywania problemów programistycznych. Możemy zrobić coś zupełnie inaczej, otrzymując dużo lepsze wyniki.


Artur Majtczak jest programistą, autorem i pomysłodawcą m.in. popularnego odtwarzacza ALLPlayer oraz twórcą sztucznej inteligencji Sara AI

Artykuł w pierwotnej wersji ukazał się na stronie https://www.saraai.com/blog. Tytuł i śródtytuły od redakcji