
يحتوي Keras على واجهات برمجة التطبيقات (APIs) لبناء بنية الشبكة العصبية بسرعة متتابعة ووظيفية. إذا كان الأول يسمح لك ببناء أبنية متسلسلة فقط للشبكات العصبية ، فعندئذٍ باستخدام واجهة برمجة التطبيقات الوظيفية ، يمكنك تحديد شبكة عصبية في شكل رسم بياني تعسفي موجه ، والذي يوفر فرصًا أكبر بكثير لبناء نماذج معقدة. هذه المقالة هي ترجمة لدليل وظائف API الوظيفية من موقع TensorFlow.
مقدمة
تتيح لك واجهة برمجة التطبيقات الوظيفية إنشاء نماذج بمرونة أكثر من واجهة برمجة تطبيقات Sequential ؛ حيث يمكنها معالجة النماذج باستخدام طوبولوجيا غير خطية ، ونماذج ذات طبقات شائعة ، ونماذج ذات مدخلات أو مخرجات متعددة.
يعتمد ذلك على حقيقة أن نموذج التعلم العميق هو عادة رسم بياني موجه (DAG) من الطبقات
API الوظيفية هي مجموعة من الأدوات
لرسم الطبقات .
النظر في النموذج التالي:
(المدخلات: 784 ناقلات الأبعاد)
↧
[طبقة كثيفة (64 عنصرًا ، تنشيط relu)]
↧
[طبقة كثيفة (64 عنصرًا ، تنشيط relu)]
↧
[طبقة كثيفة (10 عناصر ، تفعيل softmax)]
↧
(الإخراج: توزيع الاحتمالات على 10 فصول)
هذا رسم بياني بسيط مكون من 3 طبقات.
لإنشاء هذا النموذج باستخدام API Functional ، يجب أن تبدأ بإنشاء عقدة إدخال:
from tensorflow import keras inputs = keras.Input(shape=(784,))
نحن هنا نشير ببساطة إلى أبعاد بياناتنا: ناقلات الأبعاد 784. يرجى ملاحظة أن كمية البيانات يتم حذفها دائمًا ، ونشير فقط إلى بُعد كل عنصر. لإدخال الحجم المخصص للصور `(32 ، 32 ، 3)` ، نستخدم:
img_inputs = keras.Input(shape=(32, 32, 3))
تحتوي
inputs
على معلومات حول حجم ونوع البيانات التي تخطط لنقلها إلى النموذج الخاص بك:
inputs.shape
TensorShape([None, 784])
inputs.dtype
tf.float32
يمكنك إنشاء عقدة جديدة في الرسم البياني للطبقة عن طريق استدعاء الطبقة على كائن
inputs
هذا:
from tensorflow.keras import layers dense = layers.Dense(64, activation='relu') x = dense(inputs)
يشبه "استدعاء طبقة" رسم سهم من "الإدخال" في الطبقة التي أنشأناها. نحن "نمرر" المدخلات إلى الطبقة
dense
، ونحصل على
x
.
دعنا نضيف بعض الطبقات إلى الرسم البياني للطبقة لدينا:
x = layers.Dense(64, activation='relu')(x) outputs = layers.Dense(10, activation='softmax')(x)
الآن يمكننا إنشاء
Model
تحديد مدخلاته ومخرجاته في الرسم البياني للطبقة:
model = keras.Model(inputs=inputs, outputs=outputs)
دعنا ننظر مرة أخرى إلى عملية تعريف النموذج الكاملة:
inputs = keras.Input(shape=(784,), name='img') x = layers.Dense(64, activation='relu')(inputs) x = layers.Dense(64, activation='relu')(x) outputs = layers.Dense(10, activation='softmax')(x) model = keras.Model(inputs=inputs, outputs=outputs, name='mnist_model')
لنرى كيف يبدو ملخص النموذج:
model.summary()
Model: "mnist_model" _________________________________________________________________ Layer (type) Output Shape Param
يمكننا أيضًا رسم النموذج كرسم بياني:
keras.utils.plot_model(model, 'my_first_model.png')

واختياريًا اشتقاق أبعاد المدخلات والمخرجات لكل طبقة على الرسم البياني المبني:
keras.utils.plot_model(model, 'my_first_model_with_shape_info.png', show_shapes=True)

هذه الصورة والرمز الذي كتبناه متطابقان. في إصدار التعليمات البرمجية ، يتم استبدال أسهم الربط ببساطة عن طريق عمليات الاتصال.
"الرسم البياني للطبقة" هو صورة ذهنية بديهية للغاية لنموذج التعلم العميق ، وواجهة برمجة التطبيقات الوظيفية هي طريقة لإنشاء نماذج تعكس هذه الصورة الذهنية عن كثب.
التدريب والتقييم والاستنتاج
تعلم العمل وتقييمه واستخلاصه للنماذج المصممة باستخدام API الوظيفية تمامًا كما في النماذج التسلسلية.
النظر في عرض سريع.
نحن هنا نقوم بتحميل مجموعة بيانات الصور MNIST ، ونحولها إلى متجهات ، ونقوم بتدريب النموذج على البيانات (مع مراقبة جودة العمل في عينة الاختبار) ، وأخيراً نقوم بتقييم نموذجنا على بيانات الاختبار:
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() x_train = x_train.reshape(60000, 784).astype('float32') / 255 x_test = x_test.reshape(10000, 784).astype('float32') / 255 model.compile(loss='sparse_categorical_crossentropy', optimizer=keras.optimizers.RMSprop(), metrics=['accuracy']) history = model.fit(x_train, y_train, batch_size=64, epochs=5, validation_split=0.2) test_scores = model.evaluate(x_test, y_test, verbose=2) print('Test loss:', test_scores[0]) print('Test accuracy:', test_scores[1])
الادخار والتسلسل
يعمل حفظ النماذج المتسلسلة باستخدام واجهة برمجة التطبيقات الوظيفية وتسلسلها تمامًا كما هو الحال مع النماذج التسلسلية.
تتمثل الطريقة القياسية لحفظ النموذج الوظيفي في استدعاء
model.save(
) ، والذي يسمح لك بحفظ النموذج بأكمله في ملف واحد.
يمكنك فيما بعد استعادة نفس النموذج من هذا الملف ، حتى إذا لم يعد بإمكانك الوصول إلى الكود الذي أنشأ النموذج.
يتضمن هذا الملف:
- العمارة النموذجية
- الأوزان النموذجية (التي تم الحصول عليها أثناء التدريب)
- التكوين التدريب النموذجي (ما مرت في
compile
) - المُحسّن وحالته ، إذا كان (هذا يسمح لك باستئناف التدريب من حيث توقفت)
model.save('path_to_my_model.h5') del model
استخدام نفس طبقة الرسم البياني لتعريف نماذج متعددة
في API الوظيفية ، يتم إنشاء النماذج عن طريق تحديد بيانات المدخلات والمخرجات في رسم بياني للطبقة. هذا يعني أنه يمكن استخدام رسم بياني لطبقة واحدة لإنشاء عدة نماذج.
في المثال أدناه ، نستخدم نفس رصة الطبقة لإنشاء نموذجين:
نموذج
(encoder)
يحول الصور المدخلة إلى متجهات 16-الأبعاد ، ونموذج
(autoencoder)
للتدريب.
encoder_input = keras.Input(shape=(28, 28, 1), name='img') x = layers.Conv2D(16, 3, activation='relu')(encoder_input) x = layers.Conv2D(32, 3, activation='relu')(x) x = layers.MaxPooling2D(3)(x) x = layers.Conv2D(32, 3, activation='relu')(x) x = layers.Conv2D(16, 3, activation='relu')(x) encoder_output = layers.GlobalMaxPooling2D()(x) encoder = keras.Model(encoder_input, encoder_output, name='encoder') encoder.summary() x = layers.Reshape((4, 4, 1))(encoder_output) x = layers.Conv2DTranspose(16, 3, activation='relu')(x) x = layers.Conv2DTranspose(32, 3, activation='relu')(x) x = layers.UpSampling2D(3)(x) x = layers.Conv2DTranspose(16, 3, activation='relu')(x) decoder_output = layers.Conv2DTranspose(1, 3, activation='relu')(x) autoencoder = keras.Model(encoder_input, decoder_output, name='autoencoder') autoencoder.summary()
يرجى ملاحظة أننا نجعل بنية فك التشفير متماثلة تمامًا مع بنية الترميز ، حتى نحصل على بُعد بيانات المخرجات مثل بيانات الإدخال
(28, 28, 1)
. تكون طبقة
Conv2D
إلى طبقة
Conv2D
،
MaxPooling2D
طبقة
MaxPooling2D
هي الجزء الخلفي لطبقة
MaxPooling2D
.
يمكن استدعاء النماذج كطبقات
يمكنك استخدام أي نموذج كما لو كان طبقة ، أو
Input
على
Input
أو على إخراج طبقة أخرى.
لاحظ أنه من خلال استدعاء نموذج ، فأنت لا تعيد استخدام بنيته فحسب ، بل تعيد أيضًا استخدام أوزانه. دعونا نرى ذلك في العمل. فيما يلي نظرة أخرى على مثال لمشفّر تلقائي ، عند إنشاء نموذج مشفر ، يتم إنشاء نموذج وحدة فك ترميز ، ويتم توصيلهما في مكالمتين للحصول على طراز مشفر تلقائي:
encoder_input = keras.Input(shape=(28, 28, 1), name='original_img') x = layers.Conv2D(16, 3, activation='relu')(encoder_input) x = layers.Conv2D(32, 3, activation='relu')(x) x = layers.MaxPooling2D(3)(x) x = layers.Conv2D(32, 3, activation='relu')(x) x = layers.Conv2D(16, 3, activation='relu')(x) encoder_output = layers.GlobalMaxPooling2D()(x) encoder = keras.Model(encoder_input, encoder_output, name='encoder') encoder.summary() decoder_input = keras.Input(shape=(16,), name='encoded_img') x = layers.Reshape((4, 4, 1))(decoder_input) x = layers.Conv2DTranspose(16, 3, activation='relu')(x) x = layers.Conv2DTranspose(32, 3, activation='relu')(x) x = layers.UpSampling2D(3)(x) x = layers.Conv2DTranspose(16, 3, activation='relu')(x) decoder_output = layers.Conv2DTranspose(1, 3, activation='relu')(x) decoder = keras.Model(decoder_input, decoder_output, name='decoder') decoder.summary() autoencoder_input = keras.Input(shape=(28, 28, 1), name='img') encoded_img = encoder(autoencoder_input) decoded_img = decoder(encoded_img) autoencoder = keras.Model(autoencoder_input, decoded_img, name='autoencoder') autoencoder.summary()
كما ترون ، يمكن تداخل نموذج: يمكن أن يحتوي النموذج على نموذج فرعي (حيث يمكن اعتبار النموذج طبقة).
وهناك حالة الاستخدام المشترك لنماذج التعشيش هو
تجميع .
على سبيل المثال ، فيما يلي كيفية الجمع بين مجموعة من النماذج في نموذج واحد متوسط توقعاتهم:
def get_model(): inputs = keras.Input(shape=(128,)) outputs = layers.Dense(1, activation='sigmoid')(inputs) return keras.Model(inputs, outputs) model1 = get_model() model2 = get_model() model3 = get_model() inputs = keras.Input(shape=(128,)) y1 = model1(inputs) y2 = model2(inputs) y3 = model3(inputs) outputs = layers.average([y1, y2, y3]) ensemble_model = keras.Model(inputs=inputs, outputs=outputs)
معالجة طبولوجيا الرسم البياني المعقدة
نماذج متعددة المدخلات والمخرجات
تعمل API الوظيفية على تبسيط معالجة المدخلات والمخرجات المتعددة. لا يمكن القيام بذلك باستخدام API Sequential.
هنا مثال بسيط.
افترض أنك تقوم بإنشاء نظام لتصنيف طلبات العملاء حسب الأولوية وإرسالها إلى القسم المناسب.
سيتضمن النموذج الخاص بك 3 مدخلات:
- رأس التطبيق (إدخال النص)
- محتوى النص للتطبيق (إدخال النص)
- أي علامات تمت إضافتها بواسطة المستخدم (الإدخال القاطع)
سيكون لهذا النموذج 2 مخرجات:
- درجة الأولوية بين 0 و 1 (إخراج السيني السيني)
- القسم الذي يجب أن يعالج التطبيق (إخراج softmax فيما يتعلق بالعديد من الأقسام)
دعونا نبني نموذجًا في عدة أسطر باستخدام واجهة برمجة التطبيقات الوظيفية.
num_tags = 12
لنرسم رسم بياني نموذجي:
keras.utils.plot_model(model, 'multi_input_and_output_model.png', show_shapes=True)

عند تجميع هذا النموذج ، يمكننا تخصيص وظائف خسارة مختلفة لكل مخرجات.
يمكنك حتى تعيين أوزان مختلفة لكل دالة خسارة لتغيير مساهمتها في دالة فقدان التعلم الإجمالية.
model.compile(optimizer=keras.optimizers.RMSprop(1e-3), loss=['binary_crossentropy', 'categorical_crossentropy'], loss_weights=[1., 0.2])
نظرًا لأننا قدمنا أسماء لطبقات الإخراج لدينا ، يمكننا أيضًا تحديد وظائف الخسارة:
model.compile(optimizer=keras.optimizers.RMSprop(1e-3), loss={'priority': 'binary_crossentropy', 'department': 'categorical_crossentropy'}, loss_weights=[1., 0.2])
يمكننا تدريب النموذج من خلال تمرير قوائم صفائف Numpy لبيانات الإدخال والتسميات:
import numpy as np
عند الاتصال بما يتناسب مع كائن
Dataset
، إما أن يتم إرجاع مجموعة من القوائم مثل
([title_data, body_data, tags_data], [priority_targets, dept_targets])
، أو tuple من القواميس
({'title': title_data, 'body': body_data, 'tags': tags_data}, {'priority': priority_targets, 'department': dept_targets})
يجب أن
({'title': title_data, 'body': body_data, 'tags': tags_data}, {'priority': priority_targets, 'department': dept_targets})
.
نموذج التدريب resnet
بالإضافة إلى النماذج ذات المدخلات والمخرجات المتعددة ، تعمل واجهة برمجة التطبيقات الوظيفية (API) الوظيفية على تبسيط معالجة الطبولوجيا من خلال التوصيل غير الخطي ، أي النماذج التي لا يتم فيها توصيل الطبقات في سلسلة. لا يمكن تطبيق هذه النماذج أيضًا باستخدام API Sequential (كما يوحي الاسم).
حالة الاستخدام الشائعة لهذا هو الاتصالات المتبقية.
دعونا نبني نموذج تدريب ResNet لـ CIFAR10 لإظهار ذلك.
inputs = keras.Input(shape=(32, 32, 3), name='img') x = layers.Conv2D(32, 3, activation='relu')(inputs) x = layers.Conv2D(64, 3, activation='relu')(x) block_1_output = layers.MaxPooling2D(3)(x) x = layers.Conv2D(64, 3, activation='relu', padding='same')(block_1_output) x = layers.Conv2D(64, 3, activation='relu', padding='same')(x) block_2_output = layers.add([x, block_1_output]) x = layers.Conv2D(64, 3, activation='relu', padding='same')(block_2_output) x = layers.Conv2D(64, 3, activation='relu', padding='same')(x) block_3_output = layers.add([x, block_2_output]) x = layers.Conv2D(64, 3, activation='relu')(block_3_output) x = layers.GlobalAveragePooling2D()(x) x = layers.Dense(256, activation='relu')(x) x = layers.Dropout(0.5)(x) outputs = layers.Dense(10, activation='softmax')(x) model = keras.Model(inputs, outputs, name='toy_resnet') model.summary()
لنرسم رسم بياني نموذجي:
keras.utils.plot_model(model, 'mini_resnet.png', show_shapes=True)

وعلمها:
(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data() x_train = x_train.astype('float32') / 255. x_test = x_test.astype('float32') / 255. y_train = keras.utils.to_categorical(y_train, 10) y_test = keras.utils.to_categorical(y_test, 10) model.compile(optimizer=keras.optimizers.RMSprop(1e-3), loss='categorical_crossentropy', metrics=['acc']) model.fit(x_train, y_train, batch_size=64, epochs=1, validation_split=0.2)
تقاسم طبقة
الاستخدام الجيد الآخر لواجهة برمجة التطبيقات الوظيفية هي النماذج التي تستخدم طبقات شائعة. الطبقات الشائعة هي مثيلات الطبقات التي يتم إعادة استخدامها في نفس النموذج: فهي تدرس الميزات التي ترتبط بعدة مسارات في الرسم البياني للطبقة.
غالبًا ما يتم استخدام الطبقات الشائعة لتشفير بيانات الإدخال التي تأتي من نفس المسافات (على سبيل المثال ، من نصين مختلفين لهما نفس القاموس) ، حيث أنهما يوفران تبادل المعلومات بين هذه البيانات المختلفة ، مما يسمح بتدريب هذه النماذج على بيانات أقل. إذا ظهرت كلمة معينة على أحد المدخلات ، فسيسهل ذلك معالجتها على جميع المدخلات التي تمر عبر المستوى العام.
لمشاركة طبقة في API الوظيفية ، ما عليك سوى الاتصال بنفس مثيل الطبقة عدة مرات. على سبيل المثال ، تتم مشاركة طبقة
Embedding
هنا على
Embedding
للنص:
استرداد وإعادة استخدام العقد في رسم بياني طبقة
نظرًا لأن الرسم البياني للطبقة الذي تتعامل معه في واجهة برمجة التطبيقات الوظيفية هو بنية بيانات ثابتة ، يمكنك الوصول إليه والتحقق منه. هذه هي الطريقة التي نبني النماذج الوظيفية ، على سبيل المثال ، في شكل صور.
وهذا يعني أيضًا أنه يمكننا الوصول إلى تنشيط الطبقات الوسيطة ("العقد" في الرسم البياني) واستخدامها في أماكن أخرى. هذا مفيد للغاية لاستخراج السمات ، على سبيل المثال!
دعنا نرى مثالا. هذا نموذج VGG19 مع جداول تم تدريبها مسبقًا على ImageNet:
from tensorflow.keras.applications import VGG19 vgg19 = VGG19()
وهذه هي عمليات التنشيط النموذجية التي تم الحصول عليها عن طريق الاستعلام عن بنية بيانات الرسم البياني:
features_list = [layer.output for layer in vgg19.layers]
يمكننا استخدام هذه الميزات لإنشاء نموذج جديد لاستخراج المعالم يُرجع قيم التنشيط المتوسطة المستوى - ويمكننا أن نفعل كل ذلك في 3 أسطر
feat_extraction_model = keras.Model(inputs=vgg19.input, outputs=features_list) img = np.random.random((1, 224, 224, 3)).astype('float32') extracted_features = feat_extraction_model(img)
هذا مناسب عند تنفيذ نقل النمط العصبي ، كما في الحالات الأخرى.
تمديد API عن طريق كتابة طبقات مخصصة
tf.keras
لديها مجموعة واسعة من الطبقات المدمجة. فيما يلي بعض الأمثلة:
الطبقات التلافيفية:
Conv1D
،
Conv2D
،
Conv3D
،
Conv2DTranspose
، إلخ.
طبقات
MaxPooling1D
:
MaxPooling1D
، و
MaxPooling2D
، و
MaxPooling3D
، و
AveragePooling1D
، إلخ.
طبقات RNN:
GRU
،
LSTM
،
ConvLSTM2D
، إلخ.
BatchNormalization
،
Dropout
،
Embedding
، إلخ.
إذا لم تجد ما تحتاج إليه ، فمن السهل تمديد واجهة برمجة التطبيقات من خلال إنشاء الطبقة الخاصة بك.
جميع الطبقات فئة فرعية
Layer
وتنفيذ:
طريقة
call
التي تحدد العمليات الحسابية التي تقوم بها الطبقة.
طريقة الإنشاء التي تنشئ أوزان الطبقة (لاحظ أن هذا مجرد اصطلاح نمط ؛ يمكنك أيضًا إنشاء أوزان في
__init__
).
فيما يلي تطبيق بسيط للطبقة
Dense
:
class CustomDense(layers.Layer): def __init__(self, units=32): super(CustomDense, self).__init__() self.units = units def build(self, input_shape): self.w = self.add_weight(shape=(input_shape[-1], self.units), initializer='random_normal', trainable=True) self.b = self.add_weight(shape=(self.units,), initializer='random_normal', trainable=True) def call(self, inputs): return tf.matmul(inputs, self.w) + self.b inputs = keras.Input((4,)) outputs = CustomDense(10)(inputs) model = keras.Model(inputs, outputs)
إذا كنت تريد أن تدعم الطبقة المخصصة التسلسل ، فيجب عليك أيضًا تحديد طريقة
get_config
التي تُرجع وسيطات مُنشئ مثيل الطبقة:
class CustomDense(layers.Layer): def __init__(self, units=32): super(CustomDense, self).__init__() self.units = units def build(self, input_shape): self.w = self.add_weight(shape=(input_shape[-1], self.units), initializer='random_normal', trainable=True) self.b = self.add_weight(shape=(self.units,), initializer='random_normal', trainable=True) def call(self, inputs): return tf.matmul(inputs, self.w) + self.b def get_config(self): return {'units': self.units} inputs = keras.Input((4,)) outputs = CustomDense(10)(inputs) model = keras.Model(inputs, outputs) config = model.get_config() new_model = keras.Model.from_config( config, custom_objects={'CustomDense': CustomDense})
اختياريًا ، يمكنك أيضًا تطبيق طريقة الفئة
from_config (cls, config)
، المسؤولة عن إعادة إنشاء مثيل الطبقة ، بالنظر إلى قاموس التكوين الخاص بها. يبدو
from_config
الافتراضي
from_config
كما يلي:
def from_config(cls, config): return cls(**config)
متى تستخدم API الوظيفية
كيفية تحديد متى يكون من الأفضل استخدام واجهة برمجة التطبيقات الوظيفية لإنشاء نموذج جديد ، أو ببساطة
Model
فئة فرعية مباشرة؟
بشكل عام ، تعد API الوظيفية أكثر مستوى وسهولة في الاستخدام ، فهي تحتوي على عدد من الوظائف التي لا تدعمها الطرز الفرعية.
ومع ذلك ، فإن الفئة الفرعية للنموذج تمنحك مرونة كبيرة عند إنشاء نماذج لا يمكن وصفها بسهولة على أنها رسم بياني acyclic موجه للطبقات (على سبيل المثال ، لا يمكنك تطبيق Tree-RNN مع API الوظيفي ، تحتاج إلى فئة فرعية
Model
مباشرة).
نقاط القوة في API الوظيفية:
الخصائص المذكورة أدناه جميعها صحيحة بالنسبة للطرز التسلسلية (والتي هي أيضًا هياكل بيانات) ، لكنها صحيحة بالنسبة للطرز الفرعية (التي هي رمز بيثون ، وليس هياكل البيانات).
API الوظيفية تنتج رمز أقصر.
لا يوجد
super(MyClass, self).__init__(...)
، بدون
def call(self, ...):
إلخ.
قارن:
inputs = keras.Input(shape=(32,)) x = layers.Dense(64, activation='relu')(inputs) outputs = layers.Dense(10)(x) mlp = keras.Model(inputs, outputs)
مع إصدار فئة فرعية:
class MLP(keras.Model): def __init__(self, **kwargs): super(MLP, self).__init__(**kwargs) self.dense_1 = layers.Dense(64, activation='relu') self.dense_2 = layers.Dense(10) def call(self, inputs): x = self.dense_1(inputs) return self.dense_2(x)
يتم التحقق من صحة النموذج الخاص بك كما هو مكتوب.
في واجهة برمجة التطبيقات الوظيفية ، يتم إنشاء مواصفات الإدخال (الشكل والنوع) مقدمًا (عبر "الإدخال") ، وفي كل مرة تتصل بالطبقة ، تتحقق الطبقة من أن المواصفات التي تم تمريرها إليها تتوافق مع افتراضاتها ، وإذا لم تكن هذه هي الحالة ، فستتلقى رسالة خطأ مفيدة .
هذا يضمن أن أي نموذج تقوم بإنشائه باستخدام واجهة برمجة التطبيقات الوظيفية يبدأ. ستحدث جميع عمليات التصحيح (غير المتعلقة بتصحيح التقارب) بشكل ثابت أثناء إنشاء النموذج ، وليس في وقت التشغيل. هذا مشابه لنوع التدقيق في المحول البرمجي.
يمكن تمثيل النموذج الوظيفي الخاص بك بيانياً ، كما أنه قابل للاختبار.
يمكنك رسم النموذج في شكل رسم بياني ، ويمكنك بسهولة الوصول إلى العقد المتوسطة للرسم البياني ، على سبيل المثال ، لاستخراج وإعادة تنشيط تنشيط الطبقات الوسيطة ، كما رأينا في المثال السابق:
features_list = [layer.output for layer in vgg19.layers] feat_extraction_model = keras.Model(inputs=vgg19.input, outputs=features_list)
نظرًا لأن النموذج الوظيفي أكثر من بنية بيانات أكثر من كونه جزءًا من الكود ، فإنه يمكن تسلسله بأمان ويمكن حفظه كملف واحد يتيح لك إعادة إنشاء نفس النموذج تمامًا دون الوصول إلى الكود المصدر.
نقاط ضعف API الوظيفية
لا يدعم البنى الديناميكية.
تقوم API الوظيفية بمعالجة النماذج كطبقات DAG. هذا صحيح بالنسبة لمعظم أبنية التعلم العميقة ، ولكن ليس للجميع: على سبيل المثال ، لا تفي الشبكات العودية أو Tree RNNs بهذا الافتراض ولا يمكن تنفيذها في API الوظيفية.
في بعض الأحيان تحتاج فقط إلى كتابة كل شيء من الصفر.
عند كتابة تصميمات متقدمة ، قد ترغب في القيام بشيء يتجاوز "تحديد طبقات DAG": على سبيل المثال ، يمكنك استخدام العديد من أساليب التدريب والإخراج المخصصة على مثيل من النموذج الخاص بك. وهذا يتطلب فئة فرعية.
الجمع بين مختلف أساليب API والجمع بينها
من المهم ملاحظة أن الاختيار بين API الوظيفية أو التصنيف الفرعي للنموذج ليس حلاً ثنائياً يحدك من فئة واحدة من الطرز. API tf.keras , Sequential , Functional Models/Layers, .
Functional Sequential Model/Layer:
units = 32 timesteps = 10 input_dim = 5
, Layer Model Functional API
call
:
call(self, inputs, **kwargs)
inputs
(. ),
**kwargs
( ).
call(self, inputs, training=None, **kwargs)
training
, .
call(self, inputs, mask=None, **kwargs)
mask
( RNN, ).
call(self, inputs, training=None, mask=None, **kwargs)
— .
, `get_config` Layer Model, Functional .
RNN Functional :
units = 32 timesteps = 10 input_dim = 5 batch_size = 16 class CustomRNN(layers.Layer): def __init__(self): super(CustomRNN, self).__init__() self.units = units self.projection_1 = layers.Dense(units=units, activation='tanh') self.projection_2 = layers.Dense(units=units, activation='tanh') self.classifier = layers.Dense(1, activation='sigmoid') def call(self, inputs): outputs = [] state = tf.zeros(shape=(inputs.shape[0], self.units)) for t in range(inputs.shape[1]): x = inputs[:, t, :] h = self.projection_1(x) y = h + self.projection_2(state) state = y outputs.append(y) features = tf.stack(outputs, axis=1) return self.classifier(features)
Functional API!
.
بعد التحقق ، ستظهر الترجمة أيضًا على Tensorflow.org. إذا كنت ترغب في المشاركة في ترجمة وثائق موقع Tensorflow.org إلى اللغة الروسية ، يرجى الاتصال في رسالة شخصية أو تعليقات. هي موضع تقدير أي تصحيحات أو تعليقات. GoogLeNet, .