केरासो के साथ आवर्तक तंत्रिका नेटवर्क (RNN)

TensorFlow.org पर देखें Google Colab में चलाएं GitHub पर स्रोत देखें नोटबुक डाउनलोड करें

परिचय

आवर्तक तंत्रिका नेटवर्क (RNN) तंत्रिका नेटवर्क का एक वर्ग है जो मॉडलिंग अनुक्रम डेटा जैसे समय श्रृंखला या प्राकृतिक भाषा के लिए शक्तिशाली है।

रेखाचित्र के रूप में, एक RNN परत एक का उपयोग करता है for एक दृश्य के timesteps पर पुनरावृति करने पाश, जबकि एक आंतरिक स्थिति है कि timesteps के बारे में encodes जानकारी अब तक देखा गया है बनाए रखने।

केरस आरएनएन एपीआई को इस पर ध्यान देने के लिए डिज़ाइन किया गया है:

  • उपयोग में आसान: निर्मित keras.layers.RNN , keras.layers.LSTM , keras.layers.GRU परतों आप के लिए जल्दी से सक्षम मुश्किल विन्यास विकल्प बनाने के लिए बिना आवर्तक मॉडल का निर्माण।

  • अनुकूलन की आसानी: आप अपने खुद के RNN सेल परत (के भीतरी भाग को परिभाषित कर सकते for कस्टम व्यवहार के साथ लूप), और सामान्य के साथ उपयोग keras.layers.RNN परत ( for पाश में ही)। यह आपको न्यूनतम कोड के साथ लचीले तरीके से विभिन्न शोध विचारों को जल्दी से प्रोटोटाइप करने की अनुमति देता है।

सेट अप

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

अंतर्निहित आरएनएन परतें: एक सरल उदाहरण

केरस में तीन अंतर्निहित आरएनएन परतें हैं:

  1. keras.layers.SimpleRNN , एक पूरी तरह जुड़ा RNN जहां पिछले timestep से उत्पादन अगले timestep को खिलाया जा रहा है।

  2. keras.layers.GRU , पहले में प्रस्तावित चो एट अल।, 2014

  3. keras.layers.LSTM , पहले में प्रस्तावित Hochreiter और Schmidhuber, 1997

2015 की शुरुआत में, केरस के पास LSTM और GRU का पहला पुन: प्रयोज्य ओपन-सोर्स पायथन कार्यान्वयन था।

यहाँ एक का एक सरल उदाहरण है Sequential मॉडल है कि पूर्णांकों की प्रक्रिया दृश्यों, 64-आयामी वेक्टर में प्रत्येक पूर्णांक एम्बेड करता है, तो एक का उपयोग कर वैक्टर के अनुक्रम प्रक्रियाओं LSTM परत।

model = keras.Sequential()
# Add an Embedding layer expecting input vocab of size 1000, and
# output embedding dimension of size 64.
model.add(layers.Embedding(input_dim=1000, output_dim=64))

# Add a LSTM layer with 128 internal units.
model.add(layers.LSTM(128))

# Add a Dense layer with 10 units.
model.add(layers.Dense(10))

model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, None, 64)          64000     
_________________________________________________________________
lstm (LSTM)                  (None, 128)               98816     
_________________________________________________________________
dense (Dense)                (None, 10)                1290      
=================================================================
Total params: 164,106
Trainable params: 164,106
Non-trainable params: 0
_________________________________________________________________

अंतर्निहित आरएनएन कई उपयोगी सुविधाओं का समर्थन करते हैं:

  • बार-बार छोड़ने वालों की, के माध्यम से dropout और recurrent_dropout तर्क
  • रिवर्स में एक इनपुट अनुक्रम प्रक्रिया की क्षमता, के माध्यम से go_backwards तर्क
  • लूप unrolling (जो जब CPU पर कम दृश्यों प्रसंस्करण एक बड़ी speedup के लिए नेतृत्व कर सकते हैं), के माध्यम से unroll तर्क
  • ...और अधिक।

अधिक जानकारी के लिए, RNN API दस्तावेज़

आउटपुट और राज्य

डिफ़ॉल्ट रूप से, आरएनएन परत के आउटपुट में प्रति नमूना एक एकल वेक्टर होता है। यह वेक्टर पिछले टाइमस्टेप के अनुरूप आरएनएन सेल आउटपुट है, जिसमें संपूर्ण इनपुट अनुक्रम के बारे में जानकारी होती है। इस उत्पादन के आकार है (batch_size, units) जहां units से मेल खाती units तर्क परत की निर्माता को पारित कर दिया।

एक RNN परत भी प्रत्येक नमूना (नमूना प्रति timestep प्रति एक वेक्टर) के लिए आउटपुट का पूरा अनुक्रम लौट सकते हैं, यदि आप सेट return_sequences=True । इस उत्पादन के आकार है (batch_size, timesteps, units)

model = keras.Sequential()
model.add(layers.Embedding(input_dim=1000, output_dim=64))

# The output of GRU will be a 3D tensor of shape (batch_size, timesteps, 256)
model.add(layers.GRU(256, return_sequences=True))

# The output of SimpleRNN will be a 2D tensor of shape (batch_size, 128)
model.add(layers.SimpleRNN(128))

model.add(layers.Dense(10))

model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (None, None, 64)          64000     
_________________________________________________________________
gru (GRU)                    (None, None, 256)         247296    
_________________________________________________________________
simple_rnn (SimpleRNN)       (None, 128)               49280     
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 361,866
Trainable params: 361,866
Non-trainable params: 0
_________________________________________________________________

इसके अलावा, एक आरएनएन परत अपनी अंतिम आंतरिक स्थिति (ओं) को वापस कर सकती है। लौटे राज्यों बाद में RNN निष्पादन को फिर से शुरू करने के लिए, या इस्तेमाल किया जा सकता है एक और RNN प्रारंभ करने में । यह सेटिंग आमतौर पर एन्कोडर-डिकोडर अनुक्रम-से-अनुक्रम मॉडल में उपयोग की जाती है, जहां एन्कोडर की अंतिम स्थिति को डिकोडर की प्रारंभिक स्थिति के रूप में उपयोग किया जाता है।

इसकी आंतरिक स्थिति पर लौटने के लिए एक RNN परत कॉन्फ़िगर करने के लिए सेट return_state पैरामीटर True जब परत बनाने। ध्यान दें कि LSTM 2 राज्य tensors है, लेकिन GRU केवल एक ही है।

परत की प्रारंभिक अवस्था कॉन्फ़िगर करने के लिए, बस अतिरिक्त कीवर्ड तर्क के साथ परत फोन initial_state । ध्यान दें कि राज्य के आकार को परत के इकाई आकार से मेल खाना चाहिए, जैसा कि नीचे दिए गए उदाहरण में है।

encoder_vocab = 1000
decoder_vocab = 2000

encoder_input = layers.Input(shape=(None,))
encoder_embedded = layers.Embedding(input_dim=encoder_vocab, output_dim=64)(
    encoder_input
)

# Return states in addition to output
output, state_h, state_c = layers.LSTM(64, return_state=True, name="encoder")(
    encoder_embedded
)
encoder_state = [state_h, state_c]

decoder_input = layers.Input(shape=(None,))
decoder_embedded = layers.Embedding(input_dim=decoder_vocab, output_dim=64)(
    decoder_input
)

# Pass the 2 states to a new LSTM layer, as initial state
decoder_output = layers.LSTM(64, name="decoder")(
    decoder_embedded, initial_state=encoder_state
)
output = layers.Dense(10)(decoder_output)

model = keras.Model([encoder_input, decoder_input], output)
model.summary()
Model: "model"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, None)]       0                                            
__________________________________________________________________________________________________
input_2 (InputLayer)            [(None, None)]       0                                            
__________________________________________________________________________________________________
embedding_2 (Embedding)         (None, None, 64)     64000       input_1[0][0]                    
__________________________________________________________________________________________________
embedding_3 (Embedding)         (None, None, 64)     128000      input_2[0][0]                    
__________________________________________________________________________________________________
encoder (LSTM)                  [(None, 64), (None,  33024       embedding_2[0][0]                
__________________________________________________________________________________________________
decoder (LSTM)                  (None, 64)           33024       embedding_3[0][0]                
                                                                 encoder[0][1]                    
                                                                 encoder[0][2]                    
__________________________________________________________________________________________________
dense_2 (Dense)                 (None, 10)           650         decoder[0][0]                    
==================================================================================================
Total params: 258,698
Trainable params: 258,698
Non-trainable params: 0
__________________________________________________________________________________________________

आरएनएन परतें और आरएनएन कोशिकाएं

अंतर्निहित आरएनएन परतों के अलावा, आरएनएन एपीआई सेल-स्तरीय एपीआई भी प्रदान करता है। आरएनएन परतों के विपरीत, जो इनपुट अनुक्रमों के पूरे बैच को संसाधित करता है, आरएनएन सेल केवल एक टाइमस्टेप को संसाधित करता है।

सेल के अंदर है for एक RNN परत के पाश। एक के अंदर एक सेल रैपिंग keras.layers.RNN परत आप एक परत दृश्यों के बैच प्रसंस्करण में सक्षम है, जैसे देता है RNN(LSTMCell(10))

गणित के अनुसार, RNN(LSTMCell(10)) के रूप में एक ही परिणाम का उत्पादन LSTM(10) । वास्तव में, TF v1.x में इस परत का कार्यान्वयन केवल संबंधित RNN सेल बना रहा था और इसे RNN परत में लपेट रहा था। हालांकि का उपयोग कर निर्मित GRU और LSTM परतों और CuDNN का उपयोग सक्षम आप बेहतर प्रदर्शन देख सकते हैं।

तीन अंतर्निहित आरएनएन कोशिकाएं हैं, जिनमें से प्रत्येक मिलान आरएनएन परत के अनुरूप हैं।

सेल अमूर्त, सामान्य के साथ एक साथ keras.layers.RNN वर्ग, यह बहुत आसान अपने शोध के लिए कस्टम RNN आर्किटेक्चर लागू करने के लिए बनाते हैं।

क्रॉस-बैच स्टेटफुलनेस

बहुत लंबे दृश्यों संसाधित करते समय (संभवतः अनंत), आप क्रॉस-बैच statefulness के पैटर्न का उपयोग कर सकते हैं।

आम तौर पर, आरएनएन परत की आंतरिक स्थिति को हर बार एक नया बैच देखने पर रीसेट किया जाता है (यानी परत द्वारा देखा गया प्रत्येक नमूना अतीत से स्वतंत्र माना जाता है)। परत किसी दिए गए नमूने को संसाधित करते समय केवल एक स्थिति बनाए रखेगी।

यदि आपके पास बहुत लंबे अनुक्रम हैं, तो उन्हें छोटे अनुक्रमों में तोड़ना और परत की स्थिति को रीसेट किए बिना इन छोटे अनुक्रमों को क्रमिक रूप से आरएनएन परत में फीड करना उपयोगी है। इस तरह, परत अनुक्रम की संपूर्णता के बारे में जानकारी रख सकती है, भले ही वह एक समय में केवल एक उप-अनुक्रम देख रही हो।

आप की स्थापना करके ऐसा कर सकते हैं stateful=True निर्माता में।

आप एक दृश्य है, तो s = [t0, t1, ... t1546, t1547] , आप इसे जैसे भागों में विभाजित होगा

s1 = [t0, t1, ... t100]
s2 = [t101, ... t201]
...
s16 = [t1501, ... t1547]

फिर आप इसे इसके माध्यम से संसाधित करेंगे:

lstm_layer = layers.LSTM(64, stateful=True)
for s in sub_sequences:
  output = lstm_layer(s)

आप राज्य को साफ करना चाहते हैं, तो आप उपयोग कर सकते हैं layer.reset_states()

यहाँ एक पूरा उदाहरण है:

paragraph1 = np.random.random((20, 10, 50)).astype(np.float32)
paragraph2 = np.random.random((20, 10, 50)).astype(np.float32)
paragraph3 = np.random.random((20, 10, 50)).astype(np.float32)

lstm_layer = layers.LSTM(64, stateful=True)
output = lstm_layer(paragraph1)
output = lstm_layer(paragraph2)
output = lstm_layer(paragraph3)

# reset_states() will reset the cached state to the original initial_state.
# If no initial_state was provided, zero-states will be used by default.
lstm_layer.reset_states()

आरएनएन राज्य पुन: उपयोग

RNN परत की दर्ज की गई राज्यों में शामिल नहीं हैं layer.weights() यदि आप एक RNN परत से राज्य का पुन: उपयोग करना चाहते हैं, तो आप द्वारा राज्यों मान प्राप्त कर सकता layer.states और ऐसा लगता है Keras कार्यात्मक एपीआई के माध्यम से एक नई परत के लिए प्रारंभिक अवस्था के रूप में उपयोग new_layer(inputs, initial_state=layer.states) , या मॉडल उपवर्ग।

कृपया यह भी ध्यान दें कि इस मामले में अनुक्रमिक मॉडल का उपयोग नहीं किया जा सकता है क्योंकि यह केवल एकल इनपुट और आउटपुट के साथ परतों का समर्थन करता है, प्रारंभिक स्थिति का अतिरिक्त इनपुट यहां उपयोग करना असंभव बनाता है।

paragraph1 = np.random.random((20, 10, 50)).astype(np.float32)
paragraph2 = np.random.random((20, 10, 50)).astype(np.float32)
paragraph3 = np.random.random((20, 10, 50)).astype(np.float32)

lstm_layer = layers.LSTM(64, stateful=True)
output = lstm_layer(paragraph1)
output = lstm_layer(paragraph2)

existing_state = lstm_layer.states

new_lstm_layer = layers.LSTM(64)
new_output = new_lstm_layer(paragraph3, initial_state=existing_state)

द्विदिश आरएनएन

समय श्रृंखला (जैसे पाठ) के अलावा अन्य अनुक्रमों के लिए, अक्सर ऐसा होता है कि एक आरएनएन मॉडल बेहतर प्रदर्शन कर सकता है यदि यह न केवल शुरू से अंत तक अनुक्रम को संसाधित करता है, बल्कि पीछे की ओर भी। उदाहरण के लिए, एक वाक्य में अगले शब्द की भविष्यवाणी करने के लिए, शब्द के चारों ओर संदर्भ होना अक्सर उपयोगी होता है, न कि केवल इसके पहले आने वाले शब्दों के लिए।

: Keras एक आसान एपीआई आप इस तरह के द्विदिश RNNs का निर्माण करने के लिए प्रदान करता है keras.layers.Bidirectional आवरण।

model = keras.Sequential()

model.add(
    layers.Bidirectional(layers.LSTM(64, return_sequences=True), input_shape=(5, 10))
)
model.add(layers.Bidirectional(layers.LSTM(32)))
model.add(layers.Dense(10))

model.summary()
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
bidirectional (Bidirectional (None, 5, 128)            38400     
_________________________________________________________________
bidirectional_1 (Bidirection (None, 64)                41216     
_________________________________________________________________
dense_3 (Dense)              (None, 10)                650       
=================================================================
Total params: 80,266
Trainable params: 80,266
Non-trainable params: 0
_________________________________________________________________

हुड के अंतर्गत, Bidirectional RNN परत में पारित कॉपी जाएगा, और फ्लिप go_backwards नई-नई कॉपी परत के क्षेत्र, इतना है कि यह उलटे क्रम में आदानों पर कार्रवाई करेंगे।

के उत्पादन में Bidirectional RNN डिफ़ॉल्ट, आगे परत उत्पादन के संयोजन और पिछड़े परत उत्पादन से हो जाएगा। आप एक अलग विलय व्यवहार, जैसे संयोजन की जरूरत है, बदल merge_mode में पैरामीटर Bidirectional आवरण निर्माता। के बारे में अधिक जानकारी के लिए Bidirectional , कृपया जांच करें एपीआई डॉक्स

प्रदर्शन अनुकूलन और CuDNN गुठली

TensorFlow 2.0 में, अंतर्निहित LSTM और GRU परतों को GPU उपलब्ध होने पर डिफ़ॉल्ट रूप से CuDNN कर्नेल का लाभ उठाने के लिए अद्यतन किया गया है। इस बदलाव के साथ, पूर्व keras.layers.CuDNNLSTM/CuDNNGRU परतों पदावनत किया गया है, और आप हार्डवेयर उस पर चलेंगे के बारे में चिंता किए बिना अपने मॉडल बना सकते हैं।

चूंकि CuDNN गिरी कुछ मान्यताओं के साथ बनाया गया है, इस का मतलब है परत नहीं CuDNN गिरी उपयोग करने में सक्षम है, तो आप में निर्मित LSTM या GRU परतों की चूक बदल किया जाएगा। जैसे:

  • बदल रहा है activation से समारोह tanh कुछ और करने के लिए।
  • बदल रहा है recurrent_activation से समारोह sigmoid कुछ और करने के लिए।
  • का उपयोग करते हुए recurrent_dropout > 0।
  • स्थापना unroll यह सच है, जो बलों LSTM / GRU भीतरी विघटित करने के लिए tf.while_loop एक unrolled में for पाश।
  • स्थापना use_bias गलत पर।
  • जब इनपुट डेटा सख्ती से सही गद्देदार नहीं होता है तो मास्किंग का उपयोग करना (यदि मास्क सख्ती से सही गद्देदार डेटा से मेल खाता है, तो अभी भी CuDNN का उपयोग किया जा सकता है। यह सबसे आम मामला है)।

बाधाओं की विस्तृत सूची के लिए, कृपया के लिए दस्तावेज़ देखें LSTM और GRU परतों।

उपलब्ध होने पर CuDNN कर्नेल का उपयोग करना

आइए प्रदर्शन अंतर प्रदर्शित करने के लिए एक सरल LSTM मॉडल बनाएं।

हम इनपुट अनुक्रम के रूप में MNIST अंकों की पंक्तियों के अनुक्रम का उपयोग करेंगे (पिक्सेल की प्रत्येक पंक्ति को टाइमस्टेप के रूप में मानते हुए), और हम अंकों के लेबल की भविष्यवाणी करेंगे।

batch_size = 64
# Each MNIST image batch is a tensor of shape (batch_size, 28, 28).
# Each input sequence will be of size (28, 28) (height is treated like time).
input_dim = 28

units = 64
output_size = 10  # labels are from 0 to 9

# Build the RNN model
def build_model(allow_cudnn_kernel=True):
    # CuDNN is only available at the layer level, and not at the cell level.
    # This means `LSTM(units)` will use the CuDNN kernel,
    # while RNN(LSTMCell(units)) will run on non-CuDNN kernel.
    if allow_cudnn_kernel:
        # The LSTM layer with default options uses CuDNN.
        lstm_layer = keras.layers.LSTM(units, input_shape=(None, input_dim))
    else:
        # Wrapping a LSTMCell in a RNN layer will not use CuDNN.
        lstm_layer = keras.layers.RNN(
            keras.layers.LSTMCell(units), input_shape=(None, input_dim)
        )
    model = keras.models.Sequential(
        [
            lstm_layer,
            keras.layers.BatchNormalization(),
            keras.layers.Dense(output_size),
        ]
    )
    return model

आइए MNIST डेटासेट लोड करें:

mnist = keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
sample, sample_label = x_train[0], y_train[0]

आइए एक मॉडल उदाहरण बनाएं और इसे प्रशिक्षित करें।

हम चुनें sparse_categorical_crossentropy मॉडल के लिए नुकसान समारोह के रूप में। मॉडल के उत्पादन के आकार है [batch_size, 10] । मॉडल के लिए लक्ष्य एक पूर्णांक वेक्टर है, प्रत्येक पूर्णांक 0 से 9 की सीमा में है।

model = build_model(allow_cudnn_kernel=True)

model.compile(
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    optimizer="sgd",
    metrics=["accuracy"],
)


model.fit(
    x_train, y_train, validation_data=(x_test, y_test), batch_size=batch_size, epochs=1
)
938/938 [==============================] - 6s 5ms/step - loss: 0.9510 - accuracy: 0.7029 - val_loss: 0.5633 - val_accuracy: 0.8209
<keras.callbacks.History at 0x7fc9942efad0>

अब, आइए एक मॉडल से तुलना करें जो CuDNN कर्नेल का उपयोग नहीं करता है:

noncudnn_model = build_model(allow_cudnn_kernel=False)
noncudnn_model.set_weights(model.get_weights())
noncudnn_model.compile(
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    optimizer="sgd",
    metrics=["accuracy"],
)
noncudnn_model.fit(
    x_train, y_train, validation_data=(x_test, y_test), batch_size=batch_size, epochs=1
)
938/938 [==============================] - 34s 35ms/step - loss: 0.3894 - accuracy: 0.8846 - val_loss: 0.5677 - val_accuracy: 0.8045
<keras.callbacks.History at 0x7fc945fa2650>

NVIDIA GPU और CuDNN स्थापित मशीन पर चलते समय, CuDNN के साथ बनाया गया मॉडल नियमित TensorFlow कर्नेल का उपयोग करने वाले मॉडल की तुलना में प्रशिक्षित करने के लिए बहुत तेज़ होता है।

उसी CuDNN- सक्षम मॉडल का उपयोग केवल CPU वातावरण में अनुमान चलाने के लिए भी किया जा सकता है। tf.device नीचे एनोटेशन सिर्फ डिवाइस नियुक्ति मजबूर कर रहा है। यदि कोई GPU उपलब्ध नहीं है तो मॉडल डिफ़ॉल्ट रूप से CPU पर चलेगा।

आपको बस उस हार्डवेयर के बारे में चिंता करने की ज़रूरत नहीं है जिस पर आप अब चल रहे हैं। क्या यह बहुत अच्छा नहीं है?

import matplotlib.pyplot as plt

with tf.device("CPU:0"):
    cpu_model = build_model(allow_cudnn_kernel=True)
    cpu_model.set_weights(model.get_weights())
    result = tf.argmax(cpu_model.predict_on_batch(tf.expand_dims(sample, 0)), axis=1)
    print(
        "Predicted result is: %s, target result is: %s" % (result.numpy(), sample_label)
    )
    plt.imshow(sample, cmap=plt.get_cmap("gray"))
Predicted result is: [3], target result is: 5

पीएनजी

सूची / निर्देश इनपुट, या नेस्टेड इनपुट के साथ आरएनएन

नेस्टेड संरचनाएं कार्यान्वयनकर्ताओं को एक ही समय में अधिक जानकारी शामिल करने की अनुमति देती हैं। उदाहरण के लिए, एक वीडियो फ्रेम में एक ही समय में ऑडियो और वीडियो इनपुट हो सकता है। इस मामले में डेटा आकार हो सकता है:

[batch, timestep, {"video": [height, width, channel], "audio": [frequency]}]

एक अन्य उदाहरण में, हस्तलेखन डेटा में पेन की वर्तमान स्थिति के साथ-साथ दबाव की जानकारी के लिए निर्देशांक x और y दोनों हो सकते हैं। तो डेटा प्रतिनिधित्व हो सकता है:

[batch, timestep, {"location": [x, y], "pressure": [force]}]

निम्नलिखित कोड एक कस्टम आरएनएन सेल बनाने का एक उदाहरण प्रदान करता है जो इस तरह के संरचित इनपुट को स्वीकार करता है।

नेस्टेड इनपुट/आउटपुट का समर्थन करने वाले कस्टम सेल को परिभाषित करें

देखें उपवर्गीकरण के माध्यम से नई परतें और मॉडल बनाना अपनी खुद की परतों लिखने पर जानकारी के लिए।

class NestedCell(keras.layers.Layer):
    def __init__(self, unit_1, unit_2, unit_3, **kwargs):
        self.unit_1 = unit_1
        self.unit_2 = unit_2
        self.unit_3 = unit_3
        self.state_size = [tf.TensorShape([unit_1]), tf.TensorShape([unit_2, unit_3])]
        self.output_size = [tf.TensorShape([unit_1]), tf.TensorShape([unit_2, unit_3])]
        super(NestedCell, self).__init__(**kwargs)

    def build(self, input_shapes):
        # expect input_shape to contain 2 items, [(batch, i1), (batch, i2, i3)]
        i1 = input_shapes[0][1]
        i2 = input_shapes[1][1]
        i3 = input_shapes[1][2]

        self.kernel_1 = self.add_weight(
            shape=(i1, self.unit_1), initializer="uniform", name="kernel_1"
        )
        self.kernel_2_3 = self.add_weight(
            shape=(i2, i3, self.unit_2, self.unit_3),
            initializer="uniform",
            name="kernel_2_3",
        )

    def call(self, inputs, states):
        # inputs should be in [(batch, input_1), (batch, input_2, input_3)]
        # state should be in shape [(batch, unit_1), (batch, unit_2, unit_3)]
        input_1, input_2 = tf.nest.flatten(inputs)
        s1, s2 = states

        output_1 = tf.matmul(input_1, self.kernel_1)
        output_2_3 = tf.einsum("bij,ijkl->bkl", input_2, self.kernel_2_3)
        state_1 = s1 + output_1
        state_2_3 = s2 + output_2_3

        output = (output_1, output_2_3)
        new_states = (state_1, state_2_3)

        return output, new_states

    def get_config(self):
        return {"unit_1": self.unit_1, "unit_2": unit_2, "unit_3": self.unit_3}

नेस्टेड इनपुट/आउटपुट के साथ एक आरएनएन मॉडल बनाएं

आइए निर्माण एक Keras मॉडल एक का उपयोग करता है keras.layers.RNN परत और हम बस परिभाषित कस्टम सेल।

unit_1 = 10
unit_2 = 20
unit_3 = 30

i1 = 32
i2 = 64
i3 = 32
batch_size = 64
num_batches = 10
timestep = 50

cell = NestedCell(unit_1, unit_2, unit_3)
rnn = keras.layers.RNN(cell)

input_1 = keras.Input((None, i1))
input_2 = keras.Input((None, i2, i3))

outputs = rnn((input_1, input_2))

model = keras.models.Model([input_1, input_2], outputs)

model.compile(optimizer="adam", loss="mse", metrics=["accuracy"])

बेतरतीब ढंग से उत्पन्न डेटा के साथ मॉडल को प्रशिक्षित करें

चूंकि इस मॉडल के लिए कोई अच्छा उम्मीदवार डेटासेट नहीं है, इसलिए हम प्रदर्शन के लिए यादृच्छिक Numpy डेटा का उपयोग करते हैं।

input_1_data = np.random.random((batch_size * num_batches, timestep, i1))
input_2_data = np.random.random((batch_size * num_batches, timestep, i2, i3))
target_1_data = np.random.random((batch_size * num_batches, unit_1))
target_2_data = np.random.random((batch_size * num_batches, unit_2, unit_3))
input_data = [input_1_data, input_2_data]
target_data = [target_1_data, target_2_data]

model.fit(input_data, target_data, batch_size=batch_size)
10/10 [==============================] - 1s 26ms/step - loss: 0.7316 - rnn_1_loss: 0.2590 - rnn_1_1_loss: 0.4725 - rnn_1_accuracy: 0.1016 - rnn_1_1_accuracy: 0.0328
<keras.callbacks.History at 0x7fc5686e6f50>

Keras साथ keras.layers.RNN परत, आप केवल अनुक्रम में अलग-अलग चरण के लिए गणित तर्क को परिभाषित करने की उम्मीद कर रहे हैं, और keras.layers.RNN परत आप के लिए अनुक्रम यात्रा को संभाल लेंगे। यह नए प्रकार के आरएनएन (जैसे एलएसटीएम संस्करण) को शीघ्रता से प्रोटोटाइप करने का एक अविश्वसनीय रूप से शक्तिशाली तरीका है।

अधिक जानकारी के लिए, कृपया देखें एपीआई डॉक्स