Rozwiązywanie podstawowego równania matematycznego za pomocą RNN [z przykładem kodowania]

Opublikowany: 2020-12-07

Jeśli życie daje ci RNN, zrób kalkulator

Recurrent Neural Network to jedna z klasycznych sztucznych sieci neuronowych, w których połączenia między węzłami tworzą sekwencyjnie skierowany graf. Sieci RNN są znane z aplikacji takich jak rozpoznawanie mowy, rozpoznawanie pisma ręcznego itp. ze względu na ich wewnętrzną pamięć stanu do przetwarzania sekwencji o zmiennej długości.

RNN są dalej klasyfikowane na dwa typy. Pierwszy z nich to skończony impuls, którego sieć neuronowa ma postać skierowanego grafu acyklicznego, w którym jeden węzeł może być połączony z jednym lub kilkoma węzłami, które są przed nim bez widocznego cyklu w sieci. Inny to impuls nieskończony, którego sieć neuronowa ma postać ukierunkowanego, cyklicznego grafu, którego nie można rozwinąć w sieć neuronową ze sprzężeniem do przodu.

Spis treści

Co zrobimy?

Zbudujmy model, który przewiduje wynik wyrażenia arytmetycznego. Na przykład, jeśli wprowadzę '11+88', to model powinien przewidzieć następne słowo w sekwencji jako '99'. Dane wejściowe i wyjściowe są sekwencją znaków, ponieważ RNN zajmuje się danymi sekwencyjnymi.

Teraz projektowanie architektury modelu wygląda jak proste zadanie w porównaniu z gromadzeniem zestawu danych. Generowanie danych lub gromadzenie zestawu danych jest żmudnym zadaniem, ponieważ modele sztucznej inteligencji głodu danych wymagają sporej ilości danych w celu uzyskania akceptowalnej dokładności.

Tak więc ten model można wdrożyć w 6 podstawowych krokach:

  1. Generowanie danych
  2. Budowanie modelu
  3. Wektoryzacja i dewektoryzacja danych
  4. Tworzenie zbioru danych
  5. Trening modelki
  6. Testowanie modelu

Zanim zagłębimy się w implementację modelu, po prostu zaimportujmy wszystkie wymagane biblioteki.

importuj numer jako np

importuj tensorflow jako tf

z tensorflow.keras.models import Sequential

z tensorflow.keras.layers importuj Dense, Dropout, SimpleRNN, RepeatVector, TimeDistributed

from tensorflow.keras.callbacks import EarlyStopping, LambdaCallback

z importu termcolor kolorowe

1. Generowanie danych

Zdefiniujmy ciąg znaków zawierający wszystkie znaki potrzebne do napisania podstawowego równania arytmetycznego. Tak więc łańcuch składa się ze wszystkich znaków od 0 do 9 i wszystkich operatorów arytmetycznych, takich jak /, *, +, -, .(dziesiętny).

Nie możemy bezpośrednio wprowadzić danych liczbowych do naszego modelu, musimy przekazać dane w postaci tensorów. Przekształcenie ciągu w danych na zakodowany w jednym czasie wektor zapewni nam zoptymalizowaną wydajność modelu. Jeden gorący wektor zakodowany jest tablicą o długości takiej samej jak długość naszego łańcucha znaków, każdy jeden gorący wektor ma jedynki tylko w odpowiednim indeksie znaku obecnym w każdym łańcuchu.

Na przykład, powiedzmy, że nasz ciąg znaków to „0123456789”, a jeśli chcemy zakodować ciąg taki jak „12”, to jeden gorący wektor będzie miał postać [ [0,1,0,0,0,0,0,0 ,0,0], [0,0,1,0,0,0,0,0,0,0]]. Aby to zrobić, musimy stworzyć dwa słowniki z jednym indeksem jako kluczami i znakami jako wartościami, a drugim jako odwrotnie.

char_string = ' 0123456789/*+-. '

liczba_znaków = dł. ( ciąg_znaków )

character_to_index = dict ((c, i) for i, c in enumerate (char_string))

index_to_character = dict ((i, c) for i, c in enumerate (char_string))

Napiszmy teraz funkcję, która zwraca losowe równanie arytmetyczne wraz z wynikiem tego równania.

dzielenie def (n, d):

zwróć n / d , jeśli d != 0 inaczej 0

def datagen ():

random1 = np.random.randint(niski = 0 ,wysoki = 100 )

random2 = np.random.randint(niski = 0 ,wysoki = 100 )

op = np.losowy.randint(niski = 0 , wysoki = 4 )

jeśli op == 1 :

arit = str (losowo1) + ' + ' + str (losowo2)

res = str (losowy1 + losowy2)

elif op == 1 :

arit = str (losowo1) + ' ' + str (losowo2)

res = str (losowo1 losowo2)

elif op == 2 :

arit = str (losowo1) + ' * ' + str (losowo2)

res = str (losowo1 * losowo2)

jeszcze :

arit = str (losowo1) + ' / ' + str (losowo2)

res = str ( round (dzielenie(losowe1, losowe2), 2 ))

zwróć arytmę, res

Przeczytaj także: Ciekawe pomysły na projekty sieci neuronowych

2. Budowanie modelu

Model będzie miał enkoder i dekoder. Enkoder jest prostym modelem RNN z kształtem wejściowym jako (Brak,liczba_znaków) i 128 ukrytymi jednostkami. Powodem, dla którego wybieramy ukryte jednostki jako 32,64,128 itd., jest lepsza wydajność CPU lub GPU z ukrytymi jednostkami jako mocami 2.

Nasz koder będzie w pełni połączoną siecią, a dane wyjściowe będą przesyłane z powrotem do sieci, tak działa RNN. Warstwa RNN domyślnie używa aktywacji „tanh”, nie zamierzamy jej zmieniać, ponieważ najlepiej pasuje do kodera. Wynik tej warstwy będzie pojedynczym wektorem i aby uzyskać pojedynczy wektor całego wyniku, użyjemy warstwy RepeatVector() z wymaganą liczbą razy jako parametrem.

Teraz wektor wyjściowy będzie miał podaną esencję danych wejściowych i ten wektor zostanie wprowadzony do dekodera.

Dekoder składa się z prostej warstwy RNN, która wygeneruje sekwencję wyjściową, ponieważ potrzebujemy warstwy RNN, aby zwróciła przewidywaną sekwencję, którą oznaczymy „return_sequences” jako True. Przypisując „return_sequences” jako True, warstwa RNN zwróci przewidywaną sekwencję dla każdego kroku czasowego (od wielu do wielu RNN).

Wynik tej warstwy RNN jest podawany do warstwy Dense z liczbą ukrytych jednostek „num_chars” i użyjemy aktywacji softmax, ponieważ potrzebujemy prawdopodobieństwa każdego znaku. Zanim wdrożymy warstwę Dense, musimy skrócić tę warstwę do warstwy TimeDistributed, ponieważ musimy wdrożyć warstwę Dense dla danych wyjściowych każdego kroku czasowego.

ukryte_jednostki = 128

max_time_steps = 5 #zakodujemy dane wyjściowe tak, aby miały 5 znaków

def model ():

model = sekwencyjny()

model.add(SimpleRNN(ukryte_jednostki, input_shape = ( Brak , liczba_znaków)))

model.add (Powtarzaj Wektor (maks.czas_kroków))

model.add(SimpleRNN(ukryte_jednostki, zwracane_sekwencje = Prawda ))

model.add(TimeDistributed(Dense(liczba_znaków, aktywacja = ' softmax ' )))

model zwrotu

model = model()

model.podsumowanie()

model.compile(loss = ' categorical_crossentropy ' , Optimizer = ' adam ' , metrics = [ ' dokładność ' ])

Architektura modelu będzie taka, jak pokazano powyżej

Musisz przeczytać: samouczek dotyczący sieci neuronowych

3. Wektoryzacja i dewektoryzacja danych

Zdefiniujmy funkcje wektoryzacji i dewektoryzacji danych.

Oto funkcja wektoryzacji wyrażenia arytmetycznego i wyniku razem.

def wektorize (arith, res):

x = np. zera ((maksymalne_kroki_czasu, liczba_znaków))

y = np. zera ((maksymalne_kroki_czasu, liczba_znaków))

x_remaining = max_time_steps len (arith)

y_remaining = max_time_steps len (res)

dla i, c w enumerate (arith):

x[x_pozostałe + i, znak_do_indeksu[c]] = 1

dla i w zakresie (x_remaining):

x[i, znak_do_indeksu[ ' 0 ' ]] = 1

dla i, c w enumerate (res):

y[y_pozostałe + i, znak_do_indeksu[c]] = 1

dla i w zakresie (y_remaining):

y[i, znak_do_indeksowania[ ' 0 ' ]] = 1

zwróć x, y

Podobnie jest tutaj funkcja dewektoryzacji łańcucha. Ponieważ wynik, który otrzymujemy, jest wektorem prawdopodobieństw, użyjemy np.argmax() do wybrania postaci o największym prawdopodobieństwie. Teraz słownik index_to_character jest używany do śledzenia znaku w tym indeksie.

def devectorize (wejście):

res = [indeks_do_znaku[np.argmax(vec)] for i, vec in enumerate ( input )]

return ' ' .join(res)

Teraz ograniczenie, które mamy z funkcją 'devectorize' jest takie, że wypełnia ona końcowe znaki zerami. Na przykład, jeśli wektor wejściowy to ('1-20', '-19'), to dewektoryzowany wynik będzie ('01-20', '00-19'). Musimy zadbać o te dodatkowe wypełnione zera. Napiszmy funkcję do usuwania łańcucha.

def stripping (wejście):

flaga = Fałsz

wyjście = ' '

dla c na wejściu :

jeśli nie flaga i c == ' 0 ' :

kontyntynuj

if c == ' + ' lub c == ' ' lub c == ' * ' lub c == ' / ' lub c == ' . ' :

flaga = Fałsz

jeszcze :

flaga = prawda

wyjście += c

wyjście powrotne

4. Tworzenie zbioru danych

Teraz, gdy skończyliśmy definiować funkcję do generowania danych, użyjmy tej funkcji i stwórzmy zbiór danych z wieloma takimi parami (wyrażenie arytmetyczne, wynik).

def create_dataset (liczba_równań):

x_train = np. zera ((liczba_równań, max_time_steps, liczba_znaków))

y_train = np. zera ((liczba_równań, max_time_steps, liczba_znaków))

dla i w zakresie (liczba_równań):

e, l = gen danych()

x, y = wektoryzuj (e, l)

x_train[i] = x

y_train[i] = y

zwróć x_train, y_train

5. Trening modelki

Stwórzmy zestaw danych składający się z 50 000 próbek, co jest wystarczającą liczbą do wytrenowania naszego modelu głodu danych, użyjemy 25% tych danych do walidacji. Utwórzmy również wywołanie zwrotne dla inteligentnego przerwania treningu, jeśli dokładność pozostanie niezmieniona przez 8 epok. Można to osiągnąć, ustawiając parametr cierpliwości na 8.

x_train, y_train = utwórz_zestaw danych ( 50000 )

simple_logger = LambdaCallback(

on_epoch_end = lambda e, l: print ( ' {:.2f} ' .format(l[ ' val_accuracy ' ]), end = ' _ ' )

)

Early_stopping = EarlyStopping(monitor = ' val_loss ' , cierpliwość = 8 )

model.fit(x_train, y_train, epochs = 100 , validation_split = 0.25 , verbose = 0 ,

wywołania zwrotne = [simple_logger, early_stopping])

6. Testowanie modelu

Teraz przetestujmy nasz model, tworząc zbiór danych o rozmiarze 30.

x_test, y_test = utwórz_zestaw danych(liczba_równań = 20 )

preds = model.predict(x_test)

full_seq_acc = 0

for i, pred in enumerate (preds):

pred_str = stripping(devectorize(pred))

y_test_str = stripping(devectorize(y_test[i]))

x_test_str = stripping(devectorize(x_test[i]))

col = ' zielony ' if pred_str == y_test_str else ' czerwony '

full_seq_acc += 1 / len (preds) * int (pred_str == y_test_str)

outstring = ' Dane wejściowe: {}, Dane wyjściowe: {}, Predykcja: {} ' .format(x_test_str, y_test_str, pred_str)

nadruk (kolorowy(łańcuch, kolor))

print ( ' \n Pełna dokładność sekwencji: {:.3f} % ' .format( 100 * full_seq_acc))

Dane wyjściowe będą następujące

Widzimy, że dokładność jest tutaj trochę słaba, w każdym razie możemy ją zoptymalizować, modyfikując kilka hiperparametrów, takich jak liczba ukrytych jednostek, podział walidacji, liczba epok itp.

Wniosek

Zrozumieliśmy podstawowy przepływ pracy RNN, zrozumieliśmy, że RNN najlepiej nadają się do danych sekwencyjnych, wygenerowaliśmy zestaw danych losowych równań arytmetycznych, opracowaliśmy sekwencyjny model do przewidywania wyjścia podstawowego wyrażenia arytmetycznego, wytrenowaliśmy ten model za pomocą zestawu danych, który stworzyliśmy i ostatecznie przetestowaliśmy ten model z małym zestawem danych, którego model nigdy wcześniej nie widział.

Jeśli chcesz dowiedzieć się więcej o RNN, uczeniu maszynowym, sprawdź dyplom PG IIIT-B i upGrad w uczeniu maszynowym i sztucznej inteligencji, który jest przeznaczony dla pracujących profesjonalistów i oferuje ponad 450 godzin rygorystycznych szkoleń, ponad 30 studiów przypadków i zadań, Status absolwentów IIIT-B, ponad 5 praktycznych praktycznych projektów zwieńczenia i pomoc w pracy z najlepszymi firmami.

Jakie są rodzaje sieci neuronowych w uczeniu maszynowym?

W uczeniu maszynowym sztuczne sieci neuronowe są w zasadzie modelami obliczeniowymi, które zostały zaprojektowane tak, aby przypominały ludzki mózg. Istnieją różne rodzaje sztucznych sieci neuronowych, które wykorzystuje uczenie maszynowe w oparciu o obliczenia matematyczne, które należy osiągnąć. Te sieci neuronowe stanowią podzbiór różnych technik uczenia maszynowego, które na różne sposoby uczą się z danych. Niektóre z najczęściej używanych typów sieci neuronowych to – sieć neuronowa rekurencyjna – pamięć długotrwała, sieć neuronowa ze sprzężeniem do przodu – sztuczny neuron, sieć neuronowa z funkcją radialną, sieć neuronowa samoorganizująca się Kohonena, sieć neuronowa splotowa i sieć modułowa, pośród innych.

Jakie są zalety rekurencyjnej sieci neuronowej?

Rekurencyjne sieci neuronowe należą do najczęściej wykorzystywanych sztucznych sieci neuronowych w głębokim uczeniu i uczeniu maszynowym. W tego typu modelu sieci neuronowej wynik uzyskany z poprzedniego kroku jest podawany jako dane wejściowe do kolejnego kroku. Rekurencyjna sieć neuronowa ma kilka zalet, takich jak – może zachować każdy bit informacji w czasie, w tym poprzednie dane wejściowe, co czyni ją idealną do przewidywania szeregów czasowych. Ten typ jest najlepszym przykładem pamięci długo-krótkiej. Ponadto rekurencyjne sieci neuronowe zapewniają konstruktywne sąsiedztwo pikseli przy użyciu warstw splotowych.

W jaki sposób sieci neuronowe są wykorzystywane w rzeczywistych zastosowaniach?

Sztuczne sieci neuronowe są integralną częścią głębokiego uczenia, które ponownie jest superspecjalistyczną gałęzią uczenia maszynowego i sztucznej inteligencji. Sieci neuronowe są wykorzystywane w różnych branżach do osiągania różnych krytycznych celów. Niektóre z najciekawszych zastosowań sztucznych sieci neuronowych w świecie rzeczywistym obejmują prognozowanie giełdowe, rozpoznawanie twarzy, wysokowydajny autopilot i diagnostykę usterek w przemyśle lotniczym, analizę ataków zbrojnych i lokalizację obiektów w sektorze obronnym, przetwarzanie obrazu, m.in. odkrywanie leków i wykrywanie chorób w sektorze opieki zdrowotnej, weryfikacja podpisu, analiza pisma odręcznego, prognozowanie pogody i prognozowanie trendów w mediach społecznościowych.