Wartości wejściowe mnożone są przez wagi i sumowane, co prowadzi do
ostatecznej binarnej decyzji na wyjściu.
Inicjalizacja Klasy
(__init__)
Aby przetestować ten model matematyczny od podstaw, zbudujemy go korzystając z języka Python w
formie obiektowej (OOP).
Definicja klasy: Tworzymy obiekt nowej klasy. Użycie
Perceptron() w kodzie zainicjuje nową instancję naszego neuronu.
💡 Po ludzku: Budujemy fabrykę produkującą nasze
matematyczne neurony. Każde wywołanie tej komendy tworzy dla nas jeden, niezależny
obwód decyzyjny.
Konstruktor: Wywoływany podczas tworzenia obiektu. Parametr
lr (Learning Rate, współczynnik uczenia) określa wielkość korekty podjętej
podczas błędu klasyfikacji, natomiast
epochs (epoki) odpowiada za liczbę pełnych
przejść przez zbiór danych treningowych.
💡 Po ludzku: Konfigurujemy maszynę startową. Ustalamy,
jak wielkie kroki ma stawiać podczas poprawiania swoich błędów (lr) i ile razy ma
przeczytać całą księgę z danymi treningowymi od deski do deski (epoki).
Inicjalizacja wag: Tworzymy wektor trzech wag, losując
wartości z przedziału od -0.5 do 0.5. Pozycja
self.w[0] reprezentuje tzw.
bias, przesunięcie funkcji ułatwiające generalizację z modelem liniowym.
💡 Po ludzku: Ponieważ neuron nie umie na początku
niczego, przydzielamy mu losowe liczby do sprawdzania ważności danych wejściowych.
Bias to stały próg startowy, od którego zaczynamy kalkulacje.
Trzy wylosowane wartości początkowe (w tym bias W0), które w trakcie nauki
ulegną odpowiedniej korekcie.
Proces predykcji
(predict)
Funkcja decyzyjna neuronu działa w oparciu o iloczyn skalarny wektora sygnałów oraz wektora wag.
Doklejenie jedynki dla biasu: Dodajemy wartość równą `1` na
początek wektora wejściowego układu. Przeprowadzamy ten zabieg matematyczny, aby
operacja mnożenia pierwszego elementu przez wagę W0 zawsze zwracała czystą i
niezmanipulowaną wartość przesunięcia (Biasu).
💡 Po ludzku: Pierwsza waga (bias) potrzebuje partnera do
mnożenia, aby program się nie wyłożył. Doklejamy wirtualną jedynkę do danych
wejściowych, by wynik mnożenia z biasem pozostał bez zmian.
Iloczyn skalarny: Używamy funkcji NumPy `dot`. Funkcja oblicza
sumę iloczynów poszczególnych zmiennych wejściowych (np:
S = W0*1 + W1*x1 + W2*x2). Zmienna
s wyznacza łączny
potencjał wygenerowany przez perceptron.
💡 Po ludzku: Tu dzieje się matematyczna magia pod spodem.
Mnożymy wszystkie dane przez ich ważność i dodajemy to wszystko do jednego wielkiego
wiadra. Wynik to ogólna siła przekonania naszego modelu.
Funkcja krokowa: Ostateczna kwalifikacja sygnału. Jeśli
zgromadzony potencjał 's' osiągnie co najmniej pułap zera, funkcja oddaje wartość 1
(klasa z aktywacją). Poniżej zera zwracane jest 0.
💡 Po ludzku: Surowy wyrok. Jeśli siła przekonania wyszła
na plusie lub wynosi zero, odsyłamy "1" (czyli sukces, aktywacja). Jeśli wartość
wyszła ujemna, zamykamy obwód i odsyłamy "0".
Potencjał sumy w tym wzorcu rośnie do momentu przekroczenia wartości
zerowej, zwracając ostateczną aktywację binarną.
Trening Klasyfikatora
(fit)
Aby wagi dostosowały się do rzeczywistego środowiska zadania, inicjujemy pętlę uczenia
nadzorowanego.
W wywołaniu podajemy macierz cech próbek w parametrze (X) oraz
historyczne prawidłowe etykiety próbki (y). Sieć powtórzy wyliczanie wielokrotnie
poprzez iterację ustaloną w liczbie podanej jako `epochs`. W tej samej przestrzeni
zerowany jest także wskaźnik kumulacji błędów dla aktualnie przetwarzanej epoki uczenia.
💡 Po ludzku: Uruchamiamy tryb nauki na błędach.
Przekazujemy modelowi zadania (X) i od razu odpowiedzi do nich (y). Nakazujemy mu
rozwiązać ten sam zestaw zadań wielokrotnie, na początku każdej tury resetując
licznik potknięć do zera.
Wewnętrzna pętla odczytuje każdy przypadek X z zestawienia, w tym
samym momencie wyciągając etykietę idealną przyciskiem
zip() do zmiennej
yd (desired). Perceptron odczytuje dany zbiór zmiennych wejściowych do
y_pred używając uprzednio utworzonej metody `predict()`.
💡 Po ludzku: Wyciągamy z worka po jednym konkretnym
zadaniu na raz i jedną poprawną do niego odpowiedź. Model analizuje zadanie swoimi
wylosowanymi wagami i wypluwa zgadywankę (swój przewidziany wynik).
Kalkulacja Błędu
(Reguła uczenia)
Implementacja fundamentalnej zasady różnicowej na bazie korekt Hebbianowskich z logiką
modyfikacji wag w zależności od popełnionego błędu klasyfikacji.
Obliczenie Straty: Otrzymana formuła to odejmowanie etykiety
przewidzianej od tej poprawnej. Kiedy wartość oczekiwanej aktywacji to (1), a sieć
mylnie zwróciła (0), mamy różnicę
1. Brak aktywacji gdzie w teorii miała zajść
zwiastuje błąd
-1. Jeśli predykcje się zgadzają wartość błędu sprowadza się do
0.
💡 Po ludzku: Sprawdzamy klucz odpowiedzi. Odejmujemy
wynik modelu od prawdziwej odpowiedzi z arkusza. Jeśli model trafił, różnica to
zero. Jeśli przestrzelił lub zaniżył wynik, błąd to plus jeden albo minus jeden. To
jednoznaczny drogowskaz dla matematyki.
Aktualizacja Wagi: Wektor wag modyfikujemy przy pomocy
współczynnika ułatwiającego stabilność zbiegania (Learning Rate) przemnożonego przez
uprzednio obliczony błąd oraz sam wektor parametrów z przestrzeni próbki. Sieć
dynamicznie przybliża granicę do obszaru optymalnego podziału.
💡 Po ludzku: Tutaj obwód dokonuje nauki. Mając błąd,
model używa go jako siły pociągowej, dodaje do swoich obecnych wag mały ułamek (krok
nauki) powiązany z popełnioną pomyłką. Linie cięcia na wykresie przesuwają się
minimalnie na odpowiednie miejsce.
Sumujemy odnotowane błędy. Zastosowane zdanie logiczne na pętlę
zatrzyma iterację funkcji `fit` przedwcześnie w sytuacji osiągnięcia zerowej tolerancji
błędu przez perceptron we wszystkie podane testy. Używana jest komenda
break.
💡 Po ludzku: Śledzimy, ile w ogóle było błędów w całym
przejściu przez dokumentację. Jeśli sieć ani razu się nie pomyliła, przerywamy naukę
natychmiast, żeby zaoszczędzić zasoby procesora, model uznał się za przygotowanego.
W: 0.12 ➔ W: 0.52 !
Błąd predykcyjny spowodował modyfikację pierwotnego ułamka przestrzeni
liniowej aby obniżyć lub zwiększyć istotność parametru sieci.
Ewaluacja Dokładności
(evaluate)
W celu weryfikacji rzetelności wytrenowanego wcześniej systemu decyzyjnego, podajemy nową próbę
danych ewaluacyjnych bez dostarczania możliwości modyfikacji wag.
Funkcja odwołująca się do ewaluacji post-procesowej na nowej próbie
`X` wraz z kluczami kontrolnymi `yd`. Ustawiamy bazową pulę wskaźników
correct na zero. Zmienne w perceptronie (self.w) już się nie zmieniają,
ponieważ ominięto polecenia aktualizacji wag obecne wcześniej.
💡 Po ludzku: Czas na egzamin końcowy. Pokazujemy
programowi nowe przykłady, których nigdy w życiu nie widział. Tym razem blokujemy mu
możliwość poprawiania błędów i włączamy tryb czystego śledzenia poprawnych trafień.
Sieciowy algorytm wyprowadza binarną asercję z użyciem metody
`predict`. Kod potwierdza zgodność przez `==` podbijając pole pomyślności. Funkcja
len() przelicza liczbę próbek, aby wygenerować wskaźnik ostatecznej
pewności ewaluacji na strumień wskaźników procentowych (miara `Accuracy`).
💡 Po ludzku: Każda trafiona zgadywanka modelu dodaje
jeden punkt do puli nagród. Na sam koniec dzielimy zdobyte punkty przez ilość
wszystkich pytań, otrzymując chłodny wskaźnik jego skuteczności w formacie ułamkowym
lub procentowym.
📈
Interaktywna
Granica Decyzyjna (Perceptron)
Dopasuj wagi (W1, W2) i Bias, aby linia
oddzieliła
czerwone punkty od niebieskich.
Problemy Modelu Liniowego
(Bramka XOR)
Za pomocą perceptronu da się wymodelować bramki matematyczne z klasycznymi granicami cięcia
(takie jak AND czy OR). Prawdziwym problemem dla prostej funkcji stała się nieresponsywność na
bramkę Alternatywy Wykluczającej XOR.
Aktywacja w problemie XOR następuje tylko w obrębach wektorowych
odwróconych par (1, 0) i (0, 1), jednak gaśnie podczas powtórzeń tych samych stanów.
Architektura perceptronu zawiodła matematycznie, stąd powód stosowania sieci złożonej z
rzędów i warstw perceptronów w architekturach MLP.
💡 Po ludzku: Problem XOR polega na tym, że poprawne
odpowiedzi układają się po skosie (jak dwa rogi szachownicy). Jedna absolutnie
prosta kreska perceptronu nie potrafi przeciąć planszy tak, aby złapać w swoją
siatkę poprawne punkty, omijając pozostałe. To ściana nie do przebicia dla tego
konkretnego algorytmu.
Bezpośrednia, osamotniona linia percepcyjna nie potrafi odpowiednio
przeciąć koordynatów na macierzy wyrysowanych XOR aby pozycjonować prawidłowo odpowiednią
klasę.
Gotowe klasyfikatory
(Scikit-Learn)
Środowiska analityczne posługują się obecnie zoptymalizowanymi rozwiązaniami bibliotecznymi jak
np. Scikit-Learn. Pozwala to na przyspieszone badania algorytmu bez koniczności pisania
architektury w pętli operacyjnej własnoręcznie dla każdego przypadku.
Funkcja z zakresu uczenia maszynowego pozwalająca wygenerować w pełni
sztuczny zbiór danych o żądanej liczebności i wymiarowości wektorów wejściowych.
Dołączany
random_state wymusza wyliczenie powtarzalnej struktury układu.
💡 Po ludzku: Zamiast szukać prawdziwych pacjentów czy
zbiorów danych w internecie, biblioteka sama wymyśla precyzyjne symulacje punktów
dla naszego algorytmu. Parametr powtarzalności pilnuje, by generowane obiekty za
każdym odpaleniem programu wyglądały tak samo i nie zaburzały naszych odczytów
testowych.
Wyciągnięcie wprost dedykowanej biblioteki SklearnPerceptron
odpowiadającej zdefiniowanym dotychczasowym zjawiskom programistycznym. W terminologii
Scikit-Learn parametr wagi oznaczany jest mianem
eta0 dla stopnia
zróżnicowania edukacyjnego sieci (`lr`) oraz argument
max_iter stanowiący
obudowę testową iteracji `epochs`.
💡 Po ludzku: Wykorzystujemy gotowy moduł, tworzony przez
dziesiątki inżynierów przez wiele lat. Argumenty pod spodem robią dokładnie to samo,
co pisaliśmy wcześniej ręcznie, ale całość zamyka się w jednej wysoce wydajnej
linijce gotowej do użycia w przemyśle analitycznym.
Zbudowany Skrypt (Python): 19.0ms
Scikit-Learn (C++ Wrapper): 0.4ms
Zanotowana różnica czasu kompilacji dzięki ujęciu silnika matematycznego
niższego poziomu na zasadzie interfejsu C powiązanego ze stosem Python.
Eksperyment Diagnostyczny
(Confusion Matrix)
Zaimportujemy złożony wielowymiarowy zbiór wariantów medycznych raka piersi i wytestujemy
skuteczność zachowując wirtualną Macierz Błędu (Confusion Matrix).
stratify=y: Argument zabezpiecza poprawność balansu danych
weryfikacyjnych wymuszając sprawiedliwe zachowanie procentowe w przypadku
testu.
early_stopping: Sieć wyposażono w zatrzymanie wyliczeń pętli, jeśli
funkcja wyłapie symptomy stagnacji, uchroni to sieć przed przeuczeniem (Overfit).
💡 Po ludzku: Podzielenie danych medycznych musi być
uczciwe, nie chcemy by w puli treningowej wylądowali przypadkiem sami zdrowi ludzie.
Parametr startify rygorystycznie o to dba. Przerwanie uczenia to z kolei gwizdek
bezpieczeństwa ucinający naukę, gdy badany model przestaje łapać pojęcie, aby
zaniechać marnowania czasu kompilacji serwerów.
Podział skuteczności opartej dotychczasowo na proporcji "Accuracy"
przełożony na zaawansowaną macierz 2x2, precyzującą, jakie typy błędów algorytm wywołuje
najczęściej.
💡 Po ludzku: Sam fakt, że trafiliśmy w 90 procentach to
za mało dla medycyny. Macierz dekonstruuje tę wartość i dokładnie oskarża model z
jakich konkretnych pomyłek wynika brakujący ułamek sprawności testu.
TP / Czułość
(Znalezione Pozytywne: 41)
FP / Błąd 1 Rodz.
(Podniesiony Alarm Błędny: 5)
FN / Błąd 2 Rodz.
(Ominięte zagrożenie: 1)
TN / Specyficzność
(Prawidłowe zaprzeczenie: 67)
Pole "FN" generuje w przypadku
medycyny najbardziej dotkliwy błąd ze względu na odesłanie chorego pacjenta w
przeświadczeniu pełnego zdrowia przez system.
Interaktywny Model Perceptronu
Zaimportowaliśmy gotowe historyczne wagi prosto z wytrenowanego skryptu Python na podstawie
prostego testu warunków wyjścia na przejażdżkę rowerem.
Wzór Oceny = Bias (-0.4100) + Łączne parametry aktywnych cech W[n].
Quiz końcowy
🎓 Sprawdź swoją wiedzę
Pytania z modułu. Wybierz poprawną odpowiedź.
1. Przykładowe pytanie?
Poprawna odpowiedź
Błędna odpowiedź