article banner (priority)

Sztuczna inteligencja w Pythonie

Innym istotnym zastosowaniem danych jest uczenie maszynowe. Jest to obszar sztucznej inteligencji poświęcony algorytmom, które poprawiają swoje działanie dzięki dostarczonym danym. Łatwiej nam to będzie jednak zrozumieć, kiedy zobaczymy kilka przykładów.

Przykłady użycia sztucznej inteligencji

Sztuczna inteligencja często kojarzy się z grami, czyli granie z tak zwanym "komputerem". Przy tworzeniu takich algorytmów rzeczywiście często wykorzystuje się uczenie maszynowe. Często na początek zapisuje się odpowiednią liczbę rozgrywek między ludźmi i uczy się algorytm tak, by zachowywał się możliwie podobnie. Następnie można symulować gry między różnymi algorytmami i uczyć je na podstawie ostatecznych zwycięstw lub przegranych. Tak uczone algorytmy potrafią stać się znacznie lepsze niż ludzie. Już w 1997 roku sztuczna inteligencja pokonała arcymistrza szachowego Garriego Kasparowa. W 2016 komputer pokonał mistrza świata w Go. Nawet w grze DOTA 2, algorytmy uczące się prześcignęły mistrzów świata.

Bardzo przydatnym zastosowaniem uczenia maszynowego jest rozpoznawanie obrazu. Jeśli otworzysz na telefonie Android aplikację Google Assistant, włączysz tryb kamery i skierujesz na druk, to rozpozna ona napisany tam tekst. W przeszłości często wykorzystywałem tę funkcjonalność za granicą do przetłumaczenia menu w restauracji. Algorytmy uczą się rozpoznawać pismo dzięki wielu przykładom. Podobnie rozpoznawanie obrazu wykorzystywane jest w wielu innych dziedzinach. Na przykład są algorytmy nauczone, by rozpoznawać zmiany nowotworowe na podstawie obrazu z ultrasonografii lub tomografii komputerowej. Niektóre potrafią rozpoznawać takie zmiany na wcześniejszym etapie i ze statystycznie większą dokładnością niż lekarze. W końcu uczyły się na znacznie większej liczbie przykładów, analizują każdy piksel i nigdy nie są zmęczone. W coraz większej więc liczbie szpitali na świecie wykorzystuje się je jako wsparcie dla lekarzy.

W firmach bardzo często wykorzystuje się uczenie maszynowe do przewidywania przyszłych wyników sprzedażowych. Tu do uczenia służą przede wszystkim dane o samej firmie. Niektóre firmy wykorzystują jednak także dane na temat sytuacji ekonomicznej obszaru, prognozy dla innych firm i wiele więcej.

Przykładowy projekt

W naszym projekcie będziemy uczyć algorytm rozpoznawać cyfry napisane ręcznie. Takie rozpoznawanie mogłoby się przydać na poczcie, do rozczytania kodu pocztowego wpisanego w kratki. Wykorzystamy do tego bardzo popularny algorytm, zwany siecią neuronową. Można na niego patrzeć jak na czarną skrzynkę, do której dostarczamy przykłady wraz z informacją o spodziewanej odpowiedzi, po czym każemy tej sieci się uczyć. Po tym procesie sieć powinna dobrze odpowiadać zapytana o dostarczone jej przykłady, ale jeśli dobrze uogólniła dostarczoną wiedzę, powinna móc także dobrze zaklasyfikować1 przykłady, których nie widziała wcześniej.

Wykorzystamy implementację tego algorytmu z pakietu sklearn (należy go zainstalować). Jeśli chodzi o zdjęcia pisma, to wykorzystamy zbiór dostarczony razem z tym samym pakietem.

from sklearn import datasets

digits = datasets.load_digits()

Ten zbiór liczb zawiera 1797 liczb. Nie jest to dużo, gdyż współczesne algorytmy uczą się na wielokrotnie większych zbiorach. Także rozdzielczość tych obrazków jest nie najlepsza. Stanowić więc będzie to pewne wyzwanie.

Pierwsze liczby z naszego zbioru.

Zanim podejdziemy do nauki, musimy dokonać pewnego przekształcenia obrazków. Aktualnie każdy z obrazków reprezentowany jest jako lista w liście2. Zamienimy ją po prostu na listę reprezentującą kolejne piksele.

n_samples = len(digits.images)  # 1797
data = digits.images.reshape((n_samples, -1))

Gdy już nauczymy naszą sieć, będziemy chcieli sprawdzić, jak radzi sobie ona z rozpoznawaniem liczb, których wcześniej nie widziała. Potrzebujemy więc odłożyć część liczb na bok. Dane wykorzystywane do nauki nazywane są uczącymi i będą miały końcówkę _train. Te wykorzystywane do sprawdzania nazywane są testowymi i będą miały końcówkę _test. Zmienna X reprezentuje przykłady, czyli w naszym przypadku obrazki, a y reprezentuje odpowiedzi. Do rozdzielenia naszych danych na zbiory uczący i testowy, możemy wykorzystać funkcję train_test_split. Do zbioru testowego odłożymy 30% (czyli 0.3) przykładów.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    data, digits.target, test_size=0.3
)

Wreszcie czas utworzyć naszą sieć neuronową i nauczyć ją przykładów uczących. Wykorzystamy klasyczną sieć neuronową zwaną Perceptronem wielowarstwowym (Multi-Layer Perceptron, czyli MLP). Do nauczenia wykorzystuje się funkcję fit. Uczenie potrafi być czasochłonne. Dla dużych sieci i zbiorów danych potrafi to zająć całe godziny (czego doświadczyłem przy okazji swojej pracy magisterskiej). Tutaj jednak mamy zarówno małą sieć, jak i mały zbiór danych, więc powinno to zająć tylko chwilę.

from sklearn.neural_network import MLPClassifier

clf = MLPClassifier(hidden_layer_sizes=(100, 100))
clf.fit(X_train, y_train)

clf to skrót od "classifier", czyli klasyfikator, a więc algorytm przyporządkowujący elementy do kategorii (w naszym przypadku kategoriami są różne liczby).

Zacznijmy od zbadania, czy rzeczywiście nasza sieć nauczyła się zbioru uczącego. Poprośmy ją o rozpoznanie przykładów ze zbioru uczącego. Gdy porównujemy wyniki ze zbiorem uczącym, to dostajemy 100% dokładności.

# y_train_pred i y_train to tablice z numpy
# porównanie również zwraca tablicę
y_train_pred = clf.predict(X_train)
print((y_train_pred == y_train).mean())  # 1.0

Prawdziwym testem jest jednak liczba poprawnych odpowiedzi ze zbioru, którego nie poznał. Zobaczymy, jak z nim sobie poradzi.

y_test_pred = clf.predict(X_test)
print((y_test_pred == y_test).mean())  # 0.988

Pomylił się tylko w 1.2% przypadków. To naprawdę dobry wynik, zważywszy na jakość obrazków i niewielką ilość danych uczących. Mam spore wątpliwości, czy człowiek poradziłby sobie lepiej. Poniżej dołączam kilka losowych liter, wraz z odpowiedziami udzielonymi przez nasz algorytm.

Zakończenie

Uczenie maszynowe jest oczywiście ogromnym tematem. Warto jednak poznać jego możliwości oraz metody, gdyż staje się coraz istotniejsze w naszym życiu i może mieć ogromny wpływ na naszą przyszłość.

1:

Zaklasyfikować czyli przypisać do kategorii, a więc w tym przypadku rozpoznać cyfrę.

2:

Obrazek 2-wymiarowy można wyobrazić sobie jako ogromną tabelę, gdzie każda z wartości określa intensywność koloru w danym miejscu. Jest to częsty format opisu obrazka.