مؤتمر Google I / O هو التفاف! تابع جلسات TensorFlow اعرض الجلسات

الشبكات العصبية المتكررة (RNN) مع Keras

عرض على TensorFlow.org تشغيل في Google Colab عرض المصدر على جيثب تحميل دفتر

مقدمة

الشبكات العصبية المتكررة (RNN) هي فئة من الشبكات العصبية القوية لنمذجة بيانات التسلسل مثل السلاسل الزمنية أو اللغة الطبيعية.

تخطيطي، طبقة RNN يستخدم for حلقة لتكرار عبر timesteps من سلسلة، مع الحفاظ على الحالة الداخلية أن تشفير المعلومات حول timesteps شهدت حتى الآن.

تم تصميم Keras RNN API مع التركيز على:

  • سهولة الاستخدام: المدمج في 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

طبقات ال RNN المدمجة: مثال بسيط

هناك ثلاث طبقات RNN مضمنة في Keras:

  1. keras.layers.SimpleRNN ، وRNN بالكامل متصلة حيث الإخراج من خطوة زمنية السابق هو لتغذية خطوة زمنية المقبل.

  2. keras.layers.GRU ، اقترحت لأول مرة في تشو وآخرون، 2014 .

  3. keras.layers.LSTM ، اقترحت لأول مرة في Hochreiter وشميدهوبر، 1997 .

في أوائل عام 2015 ، كان لدى Keras أول تطبيقات Python مفتوحة المصدر قابلة لإعادة الاستخدام لـ 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
_________________________________________________________________

تدعم شبكات RNN المدمجة عددًا من الميزات المفيدة:

  • التسرب المتكرر، عن طريق dropout و recurrent_dropout الحجج
  • القدرة على معالجة تسلسل المدخلات في الاتجاه المعاكس، عبر go_backwards حجة
  • حلقة الفتح (والذي يمكن أن يؤدي إلى تسريع كبير عند معالجة سلاسل قصيرة على CPU)، عن طريق unroll حجة
  • ...و اكثر.

لمزيد من المعلومات، راجع وثائق API RNN .

النواتج والدول

بشكل افتراضي ، يحتوي إخراج طبقة RNN على متجه واحد لكل عينة. هذا المتجه هو خرج خلية RNN المطابق لآخر خطوة زمنية ، ويحتوي على معلومات حول تسلسل الإدخال بأكمله. شكل هذا الناتج هو (batch_size, units) حيث units يتوافق مع units مرت حجة لمنشئ الطبقة.

ويمكن للRNN طبقة أيضا إرجاع سلسلة كاملة من المخرجات لكل عينة (ناقلات واحد لكل خطوة زمنية لكل عينة)، إذا قمت بتعيين 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 آخر . يستخدم هذا الإعداد بشكل شائع في نموذج التسلسل إلى التسلسل الخاص بجهاز فك التشفير ، حيث يتم استخدام الحالة النهائية لجهاز التشفير كحالة أولية لجهاز فك التشفير.

لتكوين طبقة RNN للعودة الدولة الداخلية، تعيين return_state المعلمة إلى True عند إنشاء طبقة. علما بأن LSTM ديه 2 التنسورات الدولة، ولكن 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
__________________________________________________________________________________________________

طبقات RNN وخلايا RNN

بالإضافة إلى طبقات RNN المضمنة ، توفر واجهة برمجة تطبيقات RNN أيضًا واجهات برمجة تطبيقات على مستوى الخلية. على عكس طبقات RNN ، التي تعالج مجموعات كاملة من تسلسلات الإدخال ، تعالج خلية RNN خطوة زمنية واحدة فقط.

الخلية هي من الداخل for حلقة من طبقة RNN. التفاف خلية داخل keras.layers.RNN طبقة يمنحك طبقة قادرة على معالجة دفعات من متواليات، على سبيل المثال RNN(LSTMCell(10)) .

رياضيا، RNN(LSTMCell(10)) تنتج نفس النتيجة مثل LSTM(10) . في الواقع ، كان تنفيذ هذه الطبقة في TF v1.x مجرد إنشاء خلية RNN المقابلة وتغليفها في طبقة RNN. ومع ذلك باستخدام المدمج في GRU و LSTM طبقات تمكين استخدام CuDNN وقد تشاهد أداء أفضل.

هناك ثلاث خلايا RNN مضمنة ، كل منها تتوافق مع طبقة RNN المطابقة.

التجريد الخلية، جنبا إلى جنب مع عامة keras.layers.RNN الطبقة، تجعل من السهل جدا لتنفيذ مخصص أبنية RNN لالبحوث الخاصة بك.

الحالة الشاملة

عند معالجة سلاسل طويلة جدا (ربما انهائية)، قد ترغب في استخدام نمط statefulness عبر دفعة واحدة.

عادةً ، تتم إعادة تعيين الحالة الداخلية لطبقة RNN في كل مرة ترى فيها دفعة جديدة (أي يُفترض أن تكون كل عينة تراها الطبقة مستقلة عن الماضي). ستحتفظ الطبقة بالحالة فقط أثناء معالجة عينة معينة.

إذا كان لديك تسلسلات طويلة جدًا ، فمن المفيد تقسيمها إلى تسلسلات أقصر ، وتغذية هذه التسلسلات الأقصر بالتسلسل في طبقة RNN دون إعادة ضبط حالة الطبقة. بهذه الطريقة ، يمكن للطبقة الاحتفاظ بمعلومات حول التسلسل بأكمله ، على الرغم من أنها ترى فقط تسلسلًا فرعيًا واحدًا في كل مرة.

يمكنك القيام بذلك عن طريق وضع 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 State

لا يتم تضمين الدول المسجلة للطبقة RNN في layer.weights() . إذا كنت ترغب في إعادة استخدام الدولة من طبقة RNN، يمكنك استرداد قيمة الدول التي layer.states واستخدامه بمثابة الحالة الأولية لطبقة جديدة عن طريق API وظيفية 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)

RNNs ثنائية الاتجاه

بالنسبة للتسلسلات غير المتسلسلة الزمنية (مثل النصوص) ، غالبًا ما يكون نموذج RNN قادرًا على الأداء بشكل أفضل إذا لم يكن فقط يعالج التسلسل من البداية إلى النهاية ، ولكن أيضًا إلى الخلف. على سبيل المثال ، للتنبؤ بالكلمة التالية في الجملة ، من المفيد غالبًا أن يكون لديك سياق حول الكلمة ، وليس فقط الكلمات التي تسبقها.

يوفر Keras على API السهل بالنسبة لك لبناء مثل 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 ، يرجى مراجعة مستندات API .

تحسين الأداء ونواة CuDNN

في TensorFlow 2.0 ، تم تحديث طبقات LSTM و GRU المدمجة للاستفادة من نواة CuDNN افتراضيًا عند توفر وحدة معالجة الرسومات. مع هذا التغيير، السابقة keras.layers.CuDNNLSTM/CuDNNGRU تم إهمال طبقات، ويمكنك بناء النموذج الخاص بك دون الحاجة إلى القلق حول الأجهزة فستعمل على.

منذ يتم بناء نواة CuDNN مع افتراضات معينة، وهذا يعني أن طبقة لا تكون قادرا على استخدام نواة CuDNN إذا قمت بتغيير الإعدادات الافتراضية للLSTM أو GRU طبقات المضمنة. على سبيل المثال:

  • تغيير activation وظيفة من tanh إلى شيء آخر.
  • تغيير recurrent_activation وظيفة من sigmoid إلى شيء آخر.
  • باستخدام recurrent_dropout > 0.
  • وضع unroll إلى True، الذي القوات LSTM / GRU لتتحلل الداخلية tf.while_loop إلى بسطه 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 الشرح أدناه هو مجرد تجبر وضع الجهاز. سيعمل النموذج على وحدة المعالجة المركزية بشكل افتراضي في حالة عدم توفر وحدة معالجة الرسومات.

لا داعي للقلق بشأن الأجهزة التي تعمل عليها بعد الآن. أليس هذا رائعًا؟

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

بي إن جي

RNNs مع إدخال قائمة / ديكت ، أو مدخلات متداخلة

تسمح الهياكل المتداخلة للمنفذين بتضمين المزيد من المعلومات خلال فترة زمنية واحدة. على سبيل المثال ، يمكن أن يحتوي إطار الفيديو على إدخال صوت وفيديو في نفس الوقت. يمكن أن يكون شكل البيانات في هذه الحالة:

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

في مثال آخر ، يمكن أن تحتوي بيانات الكتابة اليدوية على إحداثيات x و y للوضع الحالي للقلم ، بالإضافة إلى معلومات الضغط. لذلك يمكن أن يكون تمثيل البيانات:

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

يوفر الكود التالي مثالاً على كيفية بناء خلية RNN مخصصة تقبل مثل هذه المدخلات المنظمة.

حدد خلية مخصصة تدعم الإدخال / الإخراج المتداخل

انظر جعل طبقات جديدة ونماذج عن طريق إن شاء subclasses ترث حصول على تفاصيل حول كتابة الطبقات الخاصة بك.

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}

بناء نموذج RNN مع المدخلات / المخرجات المتداخلة

دعونا نبني نموذجا 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 سوف طبقة التعامل مع تسلسل التكرار بالنسبة لك. إنها طريقة قوية بشكل لا يصدق لنمذجة أنواع جديدة من RNNs بسرعة (مثل متغير LSTM).

لمزيد من المعلومات، يرجى زيارة مستندات API .