29 listopada 2018

SSN - Perceptron w asm x64 - część II - rozpoznawanie kształtów

W drugiej części cyklu zbuduję bardzo prostą sieć neuronową, której celem jest odnalezienie określonego kształtu w obrazie. Sieci neuronowe, oparte na perceptronach, dobrze sprawdzają się w zadaniach, gdzie wynik może być podany w przybliżeniu. Jeśli w obrazie poszukujemy określonego kształtu, sieć perceptronów powinna go odnaleźć i wskazać z akceptowalną dokładnością. W przykładzie posłużę się kwadratem podzielonym na 9 komórek (3x3), w którym każda z nich może przyjąć barwę szarą lub białą. Zadaniem sieci będzie odnalezienie szarego kwadratu o rozmiarze 2x2 komórki. Posługujemy się dwoma barwami oraz 9 komórkami, dlatego ilość wszystkich możliwości to 2^9 czyli 512. Jak widać na poniższym obrazku, kwadrat 2x2 może powstać w 4 wariantach. Sprawdzę na ile można zbliżyć się do tej liczby, wykorzystując tylko 4 neurony.


W programie nie będziemy posługiwali się tablicą symulującą kwadrat i komórki, a liczbą z zakresu 0-511, którą można opisać na 9 bitach, z których każdy będzie odpowiednikiem jednej komórki. I tak dla przykładu:
wartość   0 = 000 000 000 - czyli wszystkie komórki w kolorze białym,
wartość 123 = 001 111 011 - komórki 3, 4, 5, 6, 8, 9 w kolorze szarym,
wartość 511 = 111 111 111 - wszystkie komórki w kolorze szarym
Jeśli wiemy już czego szukamy, możemy opisać poszukiwane kwadraty w postaci liczbowej bo:
kwadrat 1 to 110 110 000 czyli liczba 432,
kwadrat 2 to 011 011 000 czyli liczba 216,
kwadrat 3 to 000 110 110 czyli liczba 54,
kwadrat 4 to 000 011 011 czyli liczba 27
Sieć powinna wskazać liczby 27, 54, 216, 432 jako jedno z rozwiązań. Wybrałem 3 podstawowe warunki, które muszą być spełnione aby zbliżyć się do rozwiązania.

Warunek 1 - w poprawnym rozwiązaniu, szare muszą być 4 komórki. Aby zachować separowalność liniową zbiorów, wykorzystam dwa neurony. Dzieje się tak dlatego, że neurony zawsze będą aktywne po osiągnięciu wartości wzbudzenia i tak:
neuron nr 1 - aktywny jeśli w kolorze szarym będą co najmniej 4 komórki (czyli 4, 5, 6, 7, 8, 9)
neuron nr 2 - aktywny jeśli w kolorze białym będzie co najmniej 5 komórek (czyli 5, 6, 7, 8, 9)
Dzięki takiemu rozwiązaniu, aktywacja obu neuronów jednocześnie, jest możliwa tylko jeśli będą 4 pola szare i 5 pól białych. Oczywiście można było rozwiązać problem przy pomocy jednego neuronu wykorzystując "identyczność" jako funkcję aktywującą, ale nie chciałem iść na łatwiznę i skorzystałem z progowej (bipolarnej) funkcji aktywującej.

Warunek 2 - istnieje zależność pomiędzy położeniem kwadratów i wielokrotnym wykorzystaniem komórek, można to opisać jednym neuronem:
neuron nr 3 - tutaj warto się zastanowić, bo poszczególne komórki w czterech prawidłowych rozwiązaniach powtarzają się. I tak, komórka 5 będzie szara we wszystkich rozwiązaniach, komórki 2, 4, 6, 8 będą szare w dwóch poprawnych rozwiązaniach, a komórki 1, 3, 7, 9 będą szare tylko w jednym rozwiązaniu. Wiedząc to, możemy dobrać odpowiednio wagi dla poszczególnych wejść neuronu. Przyjąłem, że:
wejścia 1, 3, 7, 9 - będą miały wagę 1,
wejścia 2, 4, 6, 8 - będą miały wagę 2,
wejście 5 - będzie miało wagę 4,

Warunek 3 - w każdym prawidłowym rozwiązaniu skrajne komórki 1, 3, 7, 9 muszą być koloru szarego. Ten warunek będzie sprawdzany w neuronie 4, dla którego wybrane komórki otrzymają odpowiednie wagi.

W każdym z neuronów wejściami będą poszczególne komórki - czyli będzie 9 wejść.
neuron nr 1 - wagi wszystkich wejść będą ustawione na 1, dopełnienie będzie wynosiło 0, a wartością aktywującą neuron będzie każda liczba >= 4,
neuron nr 2 - wagi wszystkich wejść będą ustawione na 1, dopełnienie będzie wynosiło 0, a wartością aktywującą neuron będzie każda liczba >= 5,
neuron nr 3 - wagi wejść będą ustawione w zależności od częstotliwości występowania komórek w prawidłowych rozwiązaniach, a wartością aktywującą neuron będzie każda liczba >= 9,
neuron nr 4 - wagi wejść będą ustawione w zależności od położenia komórki - skrajne są ważniejsze, a wartością aktywującą neuron będzie każda liczba >= 1

Ta prosta sieć neuronowa, spełniająca wymienione warunki, a zbudowana z 4 neuronów, wskazała 24 rozwiązania z 512 możliwych. Sieć nie posiada elementu uczącego, który dobierałby wagi do określonych wzorców. Wagi dobieramy samodzielnie realizując 3 wymienione warunki. Postać graficzna i liczbowa rozwiązań zaproponowanych przez sieć:

027 - 000 011 011
030 - 000 011 110
051 - 000 110 011
054 - 000 110 110
057 - 000 111 001
060 - 000 111 100
090 - 001 011 010
114 - 001 110 010
120 - 001 111 000
147 - 010 010 011
150 - 010 010 110
153 - 010 011 001
156 - 010 011 100
177 - 010 110 001
180 - 010 110 100
210 - 011 010 010
216 - 011 011 000
240 - 011 110 000
282 - 100 011 010
306 - 100 110 010
312 - 100 111 000
402 - 110 010 010
408 - 110 011 000
432 - 110 110 000

Sieć nie wykonuje skomplikowanych operacji, ale ze względu na ilość wejść w neuronach, kodu jest sporo. Dodatkowo, aby dowolnie manipulować wejściami neuronów, jest trochę nadmiarowego kodu obsługującego dopełnienie (bias).

OPTION DOTNAME
option casemap:none

.DATA
output           dw   512 dup(0)    ; bufor z próbkami, które aktywowały wyjście sieci,
                                    ; ma rozmiar 1024 bajtów, bo 512 próbek pomnożone przez 
                                    ; 16 bitów (word). Wykorzystujemy 9 bitów ale rejestry są
                                    ; 8, 16, 32, 64 i 128 - bitowe dlatego 16 bitów.
weight_n1_1      db   1             ; wagi wejść dla neuronu pierwszego
weight_n1_2      db   1
weight_n1_3      db   1
weight_n1_4      db   1
weight_n1_5      db   1
weight_n1_6      db   1
weight_n1_7      db   1
weight_n1_8      db   1
weight_n1_9      db   1
weight_n2_1      db   1             ; wagi wejść dla neuronu drugiego
weight_n2_2      db   1
weight_n2_3      db   1
weight_n2_4      db   1
weight_n2_5      db   1
weight_n2_6      db   1
weight_n2_7      db   1
weight_n2_8      db   1
weight_n2_9      db   1
weight_n3_1      db   1             ; wagi wejść dla neuronu trzeciego, są zależne od tego
weight_n3_2      db   2             ; jak często dana komórka jest wykorzystywane w 
weight_n3_3      db   1             ; prawidłowych rozwiązaniach. dlatego:
weight_n3_4      db   2             ; wejścia 1, 3, 7, 9 - mają wagę 1,
weight_n3_5      db   4             ; wejścia 2, 4, 6, 8 - mają wagę 2,
weight_n3_6      db   2             ; wejście 5 - ma wagę 4
weight_n3_7      db   1
weight_n3_8      db   2
weight_n3_9      db   1
weight_n4_1      db   1             ; wagi dla neuronu czwartego są zależne od położenia komórki
weight_n4_2      db   0             ; wejścia 1, 3, 7, 9 mają większą wagę, bo neuron
weight_n4_3      db   1             ; bada czy próbka wykorzystuje skrajne komórki
weight_n4_4      db   0
weight_n4_5      db   0
weight_n4_6      db   0
weight_n4_7      db   1
weight_n4_8      db   0
weight_n4_9      db   1

bias_n1_1        db   0             ; uzupełnienie dla wejść wszystkich neuronów
bias_n1_2        db   0             ; wszędzie 0, ale dodałem gdyby ktoś chciał
bias_n1_3        db   0             ; testować inne rozwiązania
bias_n1_4        db   0
bias_n1_5        db   0
bias_n1_6        db   0
bias_n1_7        db   0
bias_n1_8        db   0
bias_n1_9        db   0
bias_n2_1        db   0
bias_n2_2        db   0
bias_n2_3        db   0
bias_n2_4        db   0
bias_n2_5        db   0
bias_n2_6        db   0
bias_n2_7        db   0
bias_n2_8        db   0
bias_n2_9        db   0
bias_n3_1        db   0
bias_n3_2        db   0
bias_n3_3        db   0
bias_n3_4        db   0
bias_n3_5        db   0
bias_n3_6        db   0
bias_n3_7        db   0
bias_n3_8        db   0
bias_n3_9        db   0
bias_n4_1        db   0
bias_n4_2        db   0
bias_n4_3        db   0
bias_n4_4        db   0
bias_n4_5        db   0
bias_n4_6        db   0
bias_n4_7        db   0
bias_n4_8        db   0
bias_n4_9        db   0

input_n1_1       db   0            ; ustalamy wejścia neuronu 1 na kolor biały
input_n1_2       db   0            ; bo szukamy szarych komórek
input_n1_3       db   0
input_n1_4       db   0
input_n1_5       db   0
input_n1_6       db   0
input_n1_7       db   0
input_n1_8       db   0
input_n1_9       db   0
input_n2_1       db   1            ; ustalamy wejścia neuronu 2 na kolor szary
input_n2_2       db   1            ; bo szukamy białych komórek
input_n2_3       db   1
input_n2_4       db   1
input_n2_5       db   1
input_n2_6       db   1
input_n2_7       db   1
input_n2_8       db   1
input_n2_9       db   1
input_n3_1       db   0            ; ustalamy wejścia neuronu 3 na kolor biały
input_n3_2       db   0            ; bo szukamy szarych komórek
input_n3_3       db   0
input_n3_4       db   0
input_n3_5       db   0
input_n3_6       db   0
input_n3_7       db   0
input_n3_8       db   0
input_n3_9       db   0
input_n4_1       db   0            ; ustalamy wejścia neuronu 4 na kolor biały
input_n4_2       db   0            ; bo szukamy szarych komórek
input_n4_3       db   0
input_n4_4       db   0
input_n4_5       db   0
input_n4_6       db   0
input_n4_7       db   0
input_n4_8       db   0
input_n4_9       db   0

.CODE
start:
main   PROC
   xor      r12, r12                   ; rejestr zliczający ilość aktywnych neuronów dla próbki
   xor      r13, r13                   ; rejestr zliczający ilość poprawnych próbek
   xor      rdx, rdx                   ; rejestr z kolejnymi próbkami
   lea      r14, output                ; adres z buforem dla poprawnych rozwiązań
@set_input_1:   
   test     dx, 0000000000000001b      ; testujemy pierwszą komórkę z próbki
   jz       @set_input_2               ; jeśli nie szara to przechodzimy do kolejnej
   mov      BYTE PTR [input_n1_1], 1   ; jeśli szara to ustawiamy wejście 1 neuronów
   mov      BYTE PTR [input_n2_1], 0
   mov      BYTE PTR [input_n3_1], 1
   mov      BYTE PTR [input_n4_1], 1
@set_input_2:
   test     dx, 0000000000000010b      ; testujemy drugą komórkę z próbki
   jz       @set_input_3               ; jeśli nie szara to przechodzimy do kolejnej
   mov      BYTE PTR [input_n1_2], 1   ; jeśli szara to ustawiamy wejście 2 neuronów
   mov      BYTE PTR [input_n2_2], 0
   mov      BYTE PTR [input_n3_2], 1
   mov      BYTE PTR [input_n4_2], 1
@set_input_3:
   test     dx, 0000000000000100b      ; testujemy trzecią komórkę z próbki
   jz       @set_input_4               ; jeśli nie szara to przechodzimy do kolejnej
   mov      BYTE PTR [input_n1_3], 1   ; jeśli szara to ustawiamy wejście 3 neuronów
   mov      BYTE PTR [input_n2_3], 0
   mov      BYTE PTR [input_n3_3], 1
   mov      BYTE PTR [input_n4_3], 1
@set_input_4:
   test     dx, 0000000000001000b      ; testujemy czwartą komórkę z próbki
   jz       @set_input_5               ; jeśli nie szara to przechodzimy do kolejnej
   mov      BYTE PTR [input_n1_4], 1   ; jeśli szara to ustawiamy wejście 4 neuronów
   mov      BYTE PTR [input_n2_4], 0
   mov      BYTE PTR [input_n3_4], 1
   mov      BYTE PTR [input_n4_4], 1
@set_input_5:   
   test     dx, 0000000000010000b      ; testujemy piątą komórkę z próbki
   jz       @set_input_6               ; jeśli nie szara to przechodzimy do kolejnej
   mov      BYTE PTR [input_n1_5], 1   ; jeśli szara to ustawiamy wejście 5 neuronów
   mov      BYTE PTR [input_n2_5], 0
   mov      BYTE PTR [input_n3_5], 1   
   mov      BYTE PTR [input_n4_5], 1
@set_input_6:   
   test     dx, 0000000000100000b      ; testujemy szóstą komórkę z próbki
   jz       @set_input_7               ; jeśli nie szara to przechodzimy do kolejnej
   mov      BYTE PTR [input_n1_6], 1   ; jeśli szara to ustawiamy wejście 6 neuronów
   mov      BYTE PTR [input_n2_6], 0
   mov      BYTE PTR [input_n3_6], 1
   mov      BYTE PTR [input_n4_6], 1
@set_input_7:
   test     dx, 0000000001000000b      ; testujemy siódmą komórkę z próbki
   jz       @set_input_8               ; jeśli nie szara to przechodzimy do kolejnej
   mov      BYTE PTR [input_n1_7], 1   ; jeśli szara to ustawiamy wejście 7 neuronów
   mov      BYTE PTR [input_n2_7], 0
   mov      BYTE PTR [input_n3_7], 1
   mov      BYTE PTR [input_n4_7], 1
@set_input_8:
   test     dx, 0000000010000000b      ; testujemy ósmą komórkę z próbki
   jz       @set_input_9               ; jeśli nie szara to przechodzimy do kolejnej
   mov      BYTE PTR [input_n1_8], 1   ; jeśli szara to ustawiamy wejście 8 neuronów
   mov      BYTE PTR [input_n2_8], 0
   mov      BYTE PTR [input_n3_8], 1
   mov      BYTE PTR [input_n4_8], 1
@set_input_9:
   test     dx, 0000000100000000b      ; testujemy dziewiątą komórkę z próbki
   jz       @neuron1                   ; jeśli nie szara to przechodzimy do kolejnej
   mov      BYTE PTR [input_n1_9], 1   ; jeśli szara to ustawiamy wejście 9 neuronów
   mov      BYTE PTR [input_n2_9], 0
   mov      BYTE PTR [input_n3_9], 1
   mov      BYTE PTR [input_n4_9], 1
   
@neuron1:
   xor      r8, r8                     ; wyjście neuronu, aktywne jeśli r8 >= 4
   xor      rax, rax                   ; stan wejściowy
   xor      rcx, rcx                   ; waga neuronu
   mov      cl, BYTE PTR [weight_n1_1]
   mov      al, BYTE PTR [input_n1_1]
   imul     cl
   add      al, BYTE PTR [bias_n1_1]
   add      r8, rax
   mov      cl, BYTE PTR [weight_n1_2]
   mov      al, BYTE PTR [input_n1_2]
   imul     cl
   add      al, BYTE PTR [bias_n1_2]
   add      r8, rax
   mov      cl, BYTE PTR [weight_n1_3]
   mov      al, BYTE PTR [input_n1_3]
   imul     cl
   add      al, BYTE PTR [bias_n1_3]
   add      r8, rax
   mov      cl, BYTE PTR [weight_n1_4]
   mov      al, BYTE PTR [input_n1_4]
   imul     cl
   add      al, BYTE PTR [bias_n1_4]
   add      r8, rax
   mov      cl, BYTE PTR [weight_n1_5]
   mov      al, BYTE PTR [input_n1_5]
   imul     cl
   add      al, BYTE PTR [bias_n1_5]
   add      r8, rax
   mov      cl, BYTE PTR [weight_n1_6]
   mov      al, BYTE PTR [input_n1_6]
   imul     cl
   add      al, BYTE PTR [bias_n1_6]
   add      r8, rax
   mov      cl, BYTE PTR [weight_n1_7]
   mov      al, BYTE PTR [input_n1_7]
   imul     cl
   add      al, BYTE PTR [bias_n1_7]
   add      r8, rax
   mov      cl, BYTE PTR [weight_n1_8]
   mov      al, BYTE PTR [input_n1_8]
   imul     cl
   add      al, BYTE PTR [bias_n1_8]
   add      r8, rax
   mov      cl, BYTE PTR [weight_n1_9]
   mov      al, BYTE PTR [input_n1_9]
   imul     cl
   add      al, BYTE PTR [bias_n1_9]
   add      r8, rax
   
@neuron2:
   xor      r9, r9;                    ; wyjście neuronu, aktywne jeśli r9 >= 5
   xor      rax, rax                   ; stan wejściowy
   xor      rcx, rcx                   ; waga neuronu
   mov      cl, BYTE PTR [weight_n2_1]
   mov      al, BYTE PTR [input_n2_1]
   imul     cl
   add      al, BYTE PTR [bias_n2_1]
   add      r9, rax
   mov      cl, BYTE PTR [weight_n2_2]
   mov      al, BYTE PTR [input_n2_2]
   imul     cl
   add      al, BYTE PTR [bias_n2_2]
   add      r9, rax
   mov      cl, BYTE PTR [weight_n2_3]
   mov      al, BYTE PTR [input_n2_3]
   imul     cl
   add      al, BYTE PTR [bias_n2_3]
   add      r9, rax
   mov      cl, BYTE PTR [weight_n2_4]
   mov      al, BYTE PTR [input_n2_4]
   imul     cl
   add      al, BYTE PTR [bias_n2_4]
   add      r9, rax
   mov      cl, BYTE PTR [weight_n2_5]
   mov      al, BYTE PTR [input_n2_5]
   imul     cl
   add      al, BYTE PTR [bias_n2_5]
   add      r9, rax
   mov      cl, BYTE PTR [weight_n2_6]
   mov      al, BYTE PTR [input_n2_6]
   imul     cl
   add      al, BYTE PTR [bias_n2_6]
   add      r9, rax
   mov      cl, BYTE PTR [weight_n2_7]
   mov      al, BYTE PTR [input_n2_7]
   imul     cl
   add      al, BYTE PTR [bias_n2_7]
   add      r9, rax
   mov      cl, BYTE PTR [weight_n2_8]
   mov      al, BYTE PTR [input_n2_8]
   imul     cl
   add      al, BYTE PTR [bias_n2_8]
   add      r9, rax
   mov      cl, BYTE PTR [weight_n2_9]
   mov      al, BYTE PTR [input_n2_9]
   imul     cl
   add      al, BYTE PTR [bias_n2_9]
   add      r9, rax
   
@neuron3:
   xor      r10, r10                   ; wyjście neuronu, aktywne jeśli r10 >= 9
   xor      rax, rax                   ; stan wejściowy
   xor      rcx, rcx                   ; waga neuronu
   mov      cl, BYTE PTR [weight_n3_1]
   mov      al, BYTE PTR [input_n3_1]
   imul     cl
   add      al, BYTE PTR [bias_n3_1]
   add      r10, rax
   mov      cl, BYTE PTR [weight_n3_2]
   mov      al, BYTE PTR [input_n3_2]
   imul     cl
   add      al, BYTE PTR [bias_n3_2]
   add      r10, rax
   mov      cl, BYTE PTR [weight_n3_3]
   mov      al, BYTE PTR [input_n3_3]
   imul     cl
   add      al, BYTE PTR [bias_n3_3]
   add      r10, rax
   mov      cl, BYTE PTR [weight_n3_4]
   mov      al, BYTE PTR [input_n3_4]
   imul     cl
   add      al, BYTE PTR [bias_n3_4]
   add      r10, rax
   mov      cl, BYTE PTR [weight_n3_5]
   mov      al, BYTE PTR [input_n3_5]
   imul     cl
   add      al, BYTE PTR [bias_n3_5]
   add      r10, rax
   mov      cl, BYTE PTR [weight_n3_6]
   mov      al, BYTE PTR [input_n3_6]
   imul     cl
   add      al, BYTE PTR [bias_n3_6]
   add      r10, rax
   mov      cl, BYTE PTR [weight_n3_7]
   mov      al, BYTE PTR [input_n3_7]
   imul     cl
   add      al, BYTE PTR [bias_n3_7]
   add      r10, rax
   mov      cl, BYTE PTR [weight_n3_8]
   mov      al, BYTE PTR [input_n3_8]
   imul     cl
   add      al, BYTE PTR [bias_n3_8]
   add      r10, rax
   mov      cl, BYTE PTR [weight_n3_9]
   mov      al, BYTE PTR [input_n3_9]
   imul     cl
   add      al, BYTE PTR [bias_n3_9]
   add      r10, rax

@neuron4:
   xor      r11, r11                   ; wyjście neuronu, aktywne jeśli r11 >= 1
   xor      rax, rax                   ; stan wejściowy
   xor      rcx, rcx                   ; waga neuronu
   mov      cl, BYTE PTR [weight_n4_1]
   mov      al, BYTE PTR [input_n4_1]
   imul     cl
   add      al, BYTE PTR [bias_n4_1]
   add      r11, rax
   mov      cl, BYTE PTR [weight_n4_2]
   mov      al, BYTE PTR [input_n4_2]
   imul     cl
   add      al, BYTE PTR [bias_n4_2]
   add      r11, rax
   mov      cl, BYTE PTR [weight_n4_3]
   mov      al, BYTE PTR [input_n4_3]
   imul     cl
   add      al, BYTE PTR [bias_n4_3]
   add      r11, rax
   mov      cl, BYTE PTR [weight_n4_4]
   mov      al, BYTE PTR [input_n4_4]
   imul     cl
   add      al, BYTE PTR [bias_n4_4]
   add      r11, rax
   mov      cl, BYTE PTR [weight_n4_5]
   mov      al, BYTE PTR [input_n4_5]
   imul     cl
   add      al, BYTE PTR [bias_n4_5]
   add      r11, rax
   mov      cl, BYTE PTR [weight_n4_6]
   mov      al, BYTE PTR [input_n4_6]
   imul     cl
   add      al, BYTE PTR [bias_n4_6]
   add      r11, rax
   mov      cl, BYTE PTR [weight_n4_7]
   mov      al, BYTE PTR [input_n4_7]
   imul     cl
   add      al, BYTE PTR [bias_n4_7]
   add      r11, rax
   mov      cl, BYTE PTR [weight_n4_8]
   mov      al, BYTE PTR [input_n4_8]
   imul     cl
   add      al, BYTE PTR [bias_n4_8]
   add      r11, rax
   mov      cl, BYTE PTR [weight_n4_9]
   mov      al, BYTE PTR [input_n4_9]
   imul     cl
   add      al, BYTE PTR [bias_n4_9]
   add      r11, rax   

@neuron1_check:
   cmp      r8, 4              ; sprawdzanie czy aktywować neuron 1
   jl       @neuron2_check
   inc      r12                ; jeśli aktywny to zwiększamy r12 o jeden
@neuron2_check:
   cmp      r9, 5              ; sprawdzanie czy aktywować neuron 2
   jl       @neuron3_check
   inc      r12                ; jeśli aktywny to zwiększamy r12 o jeden
@neuron3_check:
   cmp      r10, 9             ; sprawdzanie czy aktywować neuron 3
   jl       @neuron4_check
   inc      r12                ; jeśli aktywny to zwiększamy r12 o jeden
@neuron4_check:
   cmp      r11, 1             ; sprawdzanie czy aktywować neuron 4
   jl       @next_pattern
   inc      r12                ; jeśli aktywny to zwiększamy r12 o jeden
   cmp      r12, 4             ; jeśli cztery neurony aktywne do próbka jest ok.
   jnz      @next_pattern
   inc      r13                ; tutaj zliczamy próbki które sieć uznała z prawidłowe
   mov      WORD PTR [r14], dx ; zapisujemy próbkę do pamięci
   add      r14, 2             ; zwiększamy adres bufora z próbkami o kolejny WORD
   
@next_pattern:
   mov      BYTE PTR [input_n1_1], 0  ; przywracamy stan początkowy neuronów
   mov      BYTE PTR [input_n1_2], 0
   mov      BYTE PTR [input_n1_3], 0
   mov      BYTE PTR [input_n1_4], 0
   mov      BYTE PTR [input_n1_5], 0
   mov      BYTE PTR [input_n1_6], 0
   mov      BYTE PTR [input_n1_7], 0
   mov      BYTE PTR [input_n1_8], 0
   mov      BYTE PTR [input_n1_9], 0
   mov      BYTE PTR [input_n2_1], 1
   mov      BYTE PTR [input_n2_2], 1
   mov      BYTE PTR [input_n2_3], 1
   mov      BYTE PTR [input_n2_4], 1
   mov      BYTE PTR [input_n2_5], 1
   mov      BYTE PTR [input_n2_6], 1
   mov      BYTE PTR [input_n2_7], 1
   mov      BYTE PTR [input_n2_8], 1
   mov      BYTE PTR [input_n2_9], 1   
   mov      BYTE PTR [input_n3_1], 0
   mov      BYTE PTR [input_n3_2], 0
   mov      BYTE PTR [input_n3_3], 0
   mov      BYTE PTR [input_n3_4], 0
   mov      BYTE PTR [input_n3_5], 0
   mov      BYTE PTR [input_n3_6], 0
   mov      BYTE PTR [input_n3_7], 0
   mov      BYTE PTR [input_n3_8], 0
   mov      BYTE PTR [input_n3_9], 0
   mov      BYTE PTR [input_n4_1], 0
   mov      BYTE PTR [input_n4_2], 0
   mov      BYTE PTR [input_n4_3], 0
   mov      BYTE PTR [input_n4_4], 0
   mov      BYTE PTR [input_n4_5], 0
   mov      BYTE PTR [input_n4_6], 0
   mov      BYTE PTR [input_n4_7], 0
   mov      BYTE PTR [input_n4_8], 0
   mov      BYTE PTR [input_n4_9], 0   
   inc      dx                        ; przechodzimy do następnej próbki
   xor      r12, r12                  ; zerujemy licznik z aktywnymi neuronami
   cmp      rdx, 512                  ; sprawdzamy czy to już wszystkie próbki
   jnz      @set_input_1              ; jeśli nie to wracamy na początek
   ret                                ; zakończenie programu
main   ENDP
END

Brak komentarzy:

Prześlij komentarz