نموذج Keras Sequential
المؤلف: fchollet
تاريخ الإنشاء: 2020/04/12
آخر تعديل: 2023/06/25
الوصف: دليل شامل لنموذج Sequential.
الإعداد
import keras
from keras import layers
from keras import ops2025-04-12 01:12:08.893795: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:467] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
E0000 00:00:1744413128.915049 186302 cuda_dnn.cc:8579] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered
E0000 00:00:1744413128.921381 186302 cuda_blas.cc:1407] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered
W0000 00:00:1744413128.937977 186302 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.
W0000 00:00:1744413128.937996 186302 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.
W0000 00:00:1744413128.937998 186302 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.
W0000 00:00:1744413128.938000 186302 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.
2025-04-12 01:12:08.943600: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.متى تستخدم نموذج Sequential
يُعد نموذج Sequential مناسبًا لـرصّ بسيط من الطبقات (Plain Stack of Layers)
حيث تمتلك كل طبقة تنسور إدخال واحد وتنسور إخراج واحد بالضبط.
بشكل تخطيطي، النموذج Sequential التالي:
# Define Sequential model with 3 layers
model = keras.Sequential(
[
keras.Input(shape=(3,1)),
layers.Dense(2, activation="relu", name="layer1"),
layers.Dense(3, activation="relu", name="layer2"),
layers.Dense(4, name="layer3"),
]
)I0000 00:00:1744413130.756751 186302 gpu_device.cc:2019] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 3486 MB memory: -> device: 0, name: NVIDIA GeForce GTX 1050, pci bus id: 0000:01:00.0, compute capability: 6.1نموذج Sequential غير مناسب عندما:
- يمتلك نموذجك مدخلات متعددة أو مخرجات متعددة
- تمتلك أي طبقة من طبقاتك مدخلات متعددة أو مخرجات متعددة
- تحتاج إلى مشاركة الطبقات (Layer Sharing)
- تريد بنية غير خطية (Non-Linear Topology) (مثل اتصال متبقٍ - Residual Connection، أو نموذج متعدد الفروع)
إنشاء نموذج Sequential
يمكنك إنشاء نموذج Sequential بتمرير قائمة من الطبقات إلى دالة الإنشاء (Constructor) الخاصة بـSequential:
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
)يمكن الوصول إلى طبقاته عبر الخاصية layers:
model.layers[<Dense name=dense, built=False>,
<Dense name=dense_1, built=False>,
<Dense name=dense_2, built=False>]يمكنك أيضًا إنشاء نموذج Sequential تدريجيًا عبر الدالة add():
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))لاحظ أن هناك أيضًا دالة مقابلة pop() لإزالة الطبقات:
فنموذج Sequential يتصرف تمامًا مثل قائمة من الطبقات.
model.pop()
print(len(model.layers)) # 22لاحظ أيضًا أن دالة إنشاء Sequential تقبل معاملًا باسم name، تمامًا مثل أي طبقة أو نموذج في Keras. هذا مفيد لتوسيم مخططات TensorBoard بأسماء ذات معنى دلالي.
model = keras.Sequential(name="my_sequential")
model.add(layers.Dense(2, activation="relu", name="layer1"))
model.add(layers.Dense(3, activation="relu", name="layer2"))
model.add(layers.Dense(4, name="layer3"))تحديد شكل الإدخال (Input Shape) مسبقًا
بشكل عام، تحتاج جميع الطبقات في Keras لمعرفة شكل مدخلاتها حتى تتمكن من إنشاء أوزانها. لذا عندما تنشئ طبقة كهذه، فإنها في البداية لا تملك أي أوزان:
layer = layers.Dense(3)
layer.weights # Empty[]تُنشئ الطبقة أوزانها في أول مرة تُستدعى فيها على مُدخل، لأن شكل الأوزان يعتمد على شكل المدخلات:
# Call layer on a test input
x = ops.ones((1, 4)) # creates a tensor of shape (1, 4) filled with ones.
y = layer(x)
layer.weights # Now it has weights, of shape (4, 3) and (3,)[<Variable path=dense_6/kernel, shape=(4, 3), dtype=float32, value=[[-0.5044515 0.05308157 0.14716184]
[ 0.7177764 0.79038775 -0.24358672]
[-0.37373823 0.14540124 -0.49619964]
[ 0.7793262 0.2937708 0.74665713]]>,
<Variable path=dense_6/bias, shape=(3,), dtype=float32, value=[0. 0. 0.]>]بطبيعة الحال، هذا ينطبق أيضًا على نماذج Sequential. عندما تُنشئ
نموذج Sequential دون تحديد شكل إدخال، فإنه لا يكون "مبنيًا" (Built): إذ لا يملك أوزانًا
(واستدعاء model.weights يؤدي إلى خطأ يوضّح ذلك بالضبط). تُنشَأ الأوزان
عندما يرى النموذج بعض بيانات الإدخال لأول مرة:
model = keras.Sequential(
[
#keras.Input(shape=(4,)), # if this removed, No weights defined at this stage!
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
)
model.weights[]# Call the model on a test input
# performs a forward pass of the input x through the model.
x = ops.ones((1, 4))
y = model(x)
# Now we have weights becuase input shape is defined
model.weights[<Variable path=sequential_3/dense_7/kernel, shape=(4, 2), dtype=float32, value=[[ 0.27308106 0.92928123]
[-0.43627477 -0.99500155]
[-0.77765346 -0.7791717 ]
[-0.9179177 0.26103258]]>,
<Variable path=sequential_3/dense_7/bias, shape=(2,), dtype=float32, value=[0. 0.]>,
<Variable path=sequential_3/dense_8/kernel, shape=(2, 3), dtype=float32, value=[[ 0.20243871 1.0758667 -0.10924119]
[-0.09442687 -0.52260804 0.633379 ]]>,
<Variable path=sequential_3/dense_8/bias, shape=(3,), dtype=float32, value=[0. 0. 0.]>,
<Variable path=sequential_3/dense_9/kernel, shape=(3, 4), dtype=float32, value=[[ 0.11011732 -0.16411787 -0.8681091 -0.23925018]
[ 0.46230102 -0.2525509 -0.5862144 0.42887437]
[ 0.7475811 0.3619343 0.55859923 -0.737006 ]]>,
<Variable path=sequential_3/dense_9/bias, shape=(4,), dtype=float32, value=[0. 0. 0. 0.]>]y<tf.Tensor: shape=(1, 4), dtype=float32, numpy=array([[0., 0., 0., 0.]], dtype=float32)>بمجرد أن يصبح النموذج "مبنيًا"، يمكنك استدعاء الدالة summary() الخاصة به لعرض
محتواه:
model.summary()[1mModel: "sequential_3"[0m
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃[1m [0m[1mLayer (type) [0m[1m [0m┃[1m [0m[1mOutput Shape [0m[1m [0m┃[1m [0m[1m Param #[0m[1m [0m┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ dense_7 ([38;5;33mDense[0m) │ ([38;5;34m1[0m, [38;5;34m2[0m) │ [38;5;34m10[0m │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_8 ([38;5;33mDense[0m) │ ([38;5;34m1[0m, [38;5;34m3[0m) │ [38;5;34m9[0m │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_9 ([38;5;33mDense[0m) │ ([38;5;34m1[0m, [38;5;34m4[0m) │ [38;5;34m16[0m │
└─────────────────────────────────┴────────────────────────┴───────────────┘
[1m Total params: [0m[38;5;34m35[0m (140.00 B)
[1m Trainable params: [0m[38;5;34m35[0m (140.00 B)
[1m Non-trainable params: [0m[38;5;34m0[0m (0.00 B)ومع ذلك، قد يكون من المفيد جدًا عند بناء نموذج Sequential تدريجيًا
أن تتمكن من عرض ملخص النموذج حتى تلك اللحظة، بما في ذلك شكل
الإخراج الحالي. في هذه الحالة، يجب أن تبدأ نموذجك بتمرير كائن Input
إليه، حتى يعرف شكل إدخاله منذ البداية:
model = keras.Sequential()
model.add(keras.Input(shape=(4,)))
model.add(layers.Dense(2, activation="relu"))
model.summary()[1mModel: "sequential_4"[0m
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃[1m [0m[1mLayer (type) [0m[1m [0m┃[1m [0m[1mOutput Shape [0m[1m [0m┃[1m [0m[1m Param #[0m[1m [0m┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ dense_10 ([38;5;33mDense[0m) │ ([38;5;45mNone[0m, [38;5;34m2[0m) │ [38;5;34m10[0m │
└─────────────────────────────────┴────────────────────────┴───────────────┘
[1m Total params: [0m[38;5;34m10[0m (40.00 B)
[1m Trainable params: [0m[38;5;34m10[0m (40.00 B)
[1m Non-trainable params: [0m[38;5;34m0[0m (0.00 B)لاحظ أن كائن Input لا يظهر كجزء من model.layers، لأنه
ليس طبقة:
model.layers[<Dense name=dense_10, built=True>]النماذج المبنية بشكل إدخال محدَّد مسبقًا كهذا تمتلك دائمًا أوزانًا (حتى قبل رؤية أي بيانات) ولها دائمًا شكل إخراج محدَّد.
-
بشكل عام، من الممارسات الموصى بها دائمًا تحديد شكل الإدخال لنموذج Sequential مسبقًا إذا كنت تعرفه.
-
عند بناء بنية Sequential جديدة، من المفيد رصّ الطبقات تدريجيًا باستخدام
add()وطباعة ملخصات النموذج بشكل متكرر، حتى تتمكن من مراقبة كيفية عمل رصّة الطبقات.
التدريب والتقييم والاستدلال (Inference)
يعمل التدريب والتقييم والاستدلال بنفس الطريقة تمامًا للنماذج
المبنية باستخدام الواجهة الوظيفية (Functional API) كما هو الحال في نماذج Sequential.
توفّر فئة Model حلقة تدريب مدمجة (الدالة fit())
وحلقة تقييم مدمجة (الدالة evaluate()). لاحظ
أنه يمكنك تخصيص هذه الحلقات بسهولة لتنفيذ روتينات تدريب خاصة بك.
هنا، حمّل بيانات صور MNIST، وأعد تشكيلها إلى متجهات، ودرّب النموذج على البيانات (مع مراقبة الأداء على جزء للتحقق - Validation Split)، ثم قيّم النموذج على بيانات الاختبار:
model = keras.Sequential()
model.add(keras.Input(shape=(784,)))
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dense(10, activation="softmax"))
model.summary()[1mModel: "sequential_5"[0m
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃[1m [0m[1mLayer (type) [0m[1m [0m┃[1m [0m[1mOutput Shape [0m[1m [0m┃[1m [0m[1m Param #[0m[1m [0m┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ dense_11 ([38;5;33mDense[0m) │ ([38;5;45mNone[0m, [38;5;34m64[0m) │ [38;5;34m50,240[0m │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_12 ([38;5;33mDense[0m) │ ([38;5;45mNone[0m, [38;5;34m64[0m) │ [38;5;34m4,160[0m │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_13 ([38;5;33mDense[0m) │ ([38;5;45mNone[0m, [38;5;34m10[0m) │ [38;5;34m650[0m │
└─────────────────────────────────┴────────────────────────┴───────────────┘
[1m Total params: [0m[38;5;34m55,050[0m (215.04 KB)
[1m Trainable params: [0m[38;5;34m55,050[0m (215.04 KB)
[1m Non-trainable params: [0m[38;5;34m0[0m (0.00 B)إليك كيف يبدو مسار العمل النموذجي من البداية إلى النهاية، ويتكون من:
- التدريب
- التحقق (Validation) على مجموعة محجوزة (Holdout Set) مولَّدة من بيانات التدريب الأصلية
- التقييم على بيانات الاختبار
سنستخدم بيانات MNIST لهذا المثال.
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# Preprocess the data (these are NumPy arrays)
x_train = x_train.reshape(60000, 784).astype("float32") / 255
x_test = x_test.reshape(10000, 784).astype("float32") / 255
y_train = y_train.astype("float32")
y_test = y_test.astype("float32")
# Reserve 10,000 samples for validation
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]الدالة compile(): تحديد دالة الخسارة، والمقاييس، والمُحسِّن
لتدريب نموذج باستخدام fit()، تحتاج إلى تحديد دالة خسارة (Loss Function)، ومُحسِّن (Optimizer)،
وبشكل اختياري، بعض المقاييس (Metrics) لمراقبتها.
تمرّر هذه العناصر إلى النموذج كمعاملات للدالة compile():
هناك العديد من المُحسِّنات ودوال الخسارة والمقاييس المدمجة (Built-in) المتاحة
يجب علينا تحديد إعدادات التدريب (المُحسِّن، دالة الخسارة، المقاييس):
-
استخدم
SparseCategoricalCrossentropyوSparseCategoricalAccuracyعندما تكون تسمياتك (Labels) ممثَّلة كأعداد صحيحة (مثل [0, 1, 2, ...]) وليس كمتجهات مرمَّزة بترميز One-Hot. -
استخدم
categorical_crossentropyوcategorical_accuracy، عند التصنيف متعدد الفئات بتسميات One-Hot [0, 0, 1]، [1, 0, 0] -
استخدم
binary_crossentropyوBinaryAccuracy، عند التصنيف الثنائي [0, 1, 1, 0]
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3), # Optimizer
# Loss function to minimize
loss=keras.losses.SparseCategoricalCrossentropy(),
# List of metrics to monitor
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)الآن، لنراجع كل جزء من هذا المسار بالتفصيل.
يجب أن يكون المعامل metrics قائمة -- يمكن أن يمتلك نموذجك أي عدد من المقاييس.
إذا كان لنموذجك مخرجات متعددة، يمكنك تحديد دوال خسارة ومقاييس مختلفة لكل مخرج، ويمكنك التحكم في مساهمة كل مخرج في إجمالي خسارة النموذج. ستجد المزيد من التفاصيل حول هذا في قسم تمرير البيانات للنماذج متعددة المدخلات ومتعددة المخرجات.
لاحظ أنه إذا كنت راضيًا عن الإعدادات الافتراضية، ففي كثير من الحالات يمكن تحديد المُحسِّن ودالة الخسارة والمقاييس عبر معرِّفات نصية (String Identifiers) كاختصار:
model.compile(
optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"],
)نستدعي fit()، والتي ستدرّب النموذج بتقطيع البيانات إلى "دُفعات" (Batches) بحجم
batch_size، والتكرار بشكل متكرر عبر مجموعة البيانات بأكملها لعدد معيّن من
epochs (الحِقَب).
print("Fit model on training data")
history = model.fit(
x_train,
y_train,
batch_size=64,
epochs=2,
# We pass some validation for
# monitoring validation loss and metrics
# at the end of each epoch
validation_data=(x_val, y_val),
)Fit model on training data
Epoch 1/2
2025-04-12 01:12:13.784480: W external/local_xla/xla/tsl/framework/cpu_allocator_impl.cc:83] Allocation of 156800000 exceeds 10% of free system memory.
2025-04-12 01:12:13.922969: W external/local_xla/xla/tsl/framework/cpu_allocator_impl.cc:83] Allocation of 156800000 exceeds 10% of free system memory.
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
I0000 00:00:1744413134.578135 186413 service.cc:152] XLA service 0x794ae0003af0 initialized for platform CUDA (this does not guarantee that XLA will be used). Devices:
I0000 00:00:1744413134.578154 186413 service.cc:160] StreamExecutor device (0): NVIDIA GeForce GTX 1050, Compute Capability 6.1
2025-04-12 01:12:14.597288: I tensorflow/compiler/mlir/tensorflow/utils/dump_mlir_util.cc:269] disabling MLIR crash reproducer, set env var `MLIR_CRASH_REPRODUCER_DIRECTORY` to enable.
I0000 00:00:1744413134.685004 186413 cuda_dnn.cc:529] Loaded cuDNN version 90300
[1m 56/782[0m [32m━[0m[37m━━━━━━━━━━━━━━━━━━━[0m [1m2s[0m 3ms/step - loss: 1.5649 - sparse_categorical_accuracy: 0.5465I0000 00:00:1744413135.606734 186413 device_compiler.h:188] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process.
[1m782/782[0m [32m━━━━━━━━━━━━━━━━━━━━[0m[37m[0m [1m6s[0m 5ms/step - loss: 0.5733 - sparse_categorical_accuracy: 0.8410 - val_loss: 0.3036 - val_sparse_categorical_accuracy: 0.9113
Epoch 2/2
[1m782/782[0m [32m━━━━━━━━━━━━━━━━━━━━[0m[37m[0m [1m2s[0m 3ms/step - loss: 0.1803 - sparse_categorical_accuracy: 0.9460 - val_loss: 0.1403 - val_sparse_categorical_accuracy: 0.9594المعامل الوصف
x : بيانات الإدخال (مصفوفة NumPy، أو Tensor، أو Dataset)
y : التسميات المستهدفة (Target Labels) (بنفس تنسيق مخرجات النموذج)
batch_size : عدد العيّنات في كل تحديث للتدرّج (Gradient) (الافتراضي: 32)
epochs : عدد مرات المرور عبر مجموعة البيانات بأكملها
validation_data : زوج (val_x, val_y) لتقييم النموذج في نهاية كل حقبة
shuffle : هل يتم خلط بيانات التدريب قبل كل حقبة (الافتراضي: True)
verbose : 0 = بدون مخرجات، 1 = شريط تقدّم، 2 = سطر واحد لكل حقبة
يحتفظ الكائن history المُعاد بسجل لقيم دالة الخسارة وقيم المقاييس
أثناء التدريب:
print(history.history){'loss': [0.34744855761528015, 0.17029716074466705], 'sparse_categorical_accuracy': [0.9023799896240234, 0.9497600197792053], 'val_loss': [0.30355894565582275, 0.14027070999145508], 'val_sparse_categorical_accuracy': [0.911300003528595, 0.9593999981880188]}نقيّم النموذج على بيانات الاختبار عبر evaluate():
# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)
# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)Evaluate on test data
[1m79/79[0m [32m━━━━━━━━━━━━━━━━━━━━[0m[37m[0m [1m1s[0m 3ms/step - loss: 0.1642 - sparse_categorical_accuracy: 0.9503
test loss, test acc: [0.14707498252391815, 0.9559000134468079]
Generate predictions for 3 samples
[1m1/1[0m [32m━━━━━━━━━━━━━━━━━━━━[0m[37m[0m [1m0s[0m 397ms/step
predictions shape: (3, 10)تمرين: جرّب مُحسِّنات (Optimizers) مختلفة:
SGD()(مع أو بدون الزخم - Momentum)Adam()- إلخ.
زِد قيمة batch_size وعدد epochs ولاحظ الفرق
دراسة ذاتية: واجهة Keras الوظيفية (Functional API)
المؤلف: fchollet
تاريخ الإنشاء: 2019/03/01
آخر تعديل: 2023/06/25
الوصف: دليل شامل للواجهة الوظيفية (Functional API).
مقدمة
الواجهة الوظيفية (Functional API) في Keras هي طريقة لإنشاء نماذج أكثر مرونة
من واجهة keras.Sequential. يمكن للواجهة الوظيفية التعامل مع نماذج
ذات بنية غير خطية، وطبقات مشترَكة، وحتى مدخلات أو مخرجات متعددة.
الفكرة الأساسية هي أن نموذج التعلّم العميق عادةً ما يكون مخططًا موجَّهًا غير دوري (Directed Acyclic Graph - DAG) من الطبقات. لذا فإن الواجهة الوظيفية هي طريقة لبناء مخططات من الطبقات.
لننظر إلى النموذج التالي:
هذا مخطط أساسي بثلاث طبقات. لبناء هذا النموذج باستخدام الواجهة الوظيفية، ابدأ بإنشاء عقدة إدخال (Input Node):
inputs = keras.Input(shape=(784,))يُحدَّد شكل البيانات كمتجه ذي 784 بُعدًا. يُحذَف حجم الدُّفعة (Batch Size) دائمًا لأنه يُحدَّد فقط شكل كل عيّنة.
فمثلًا، إذا كان لديك إدخال صورة بشكل (32, 32, 3)،
فستستخدم:
# Just for demonstration purposes.
img_inputs = keras.Input(shape=(32, 32, 3))يحتوي inputs المُعاد على معلومات حول شكل وdtype
بيانات الإدخال التي تُغذّي بها نموذجك.
إليك الشكل:
inputs.shape(None, 784)إليك الـdtype:
inputs.dtype'float32'تُنشئ عقدة جديدة في مخطط الطبقات باستدعاء طبقة على كائن inputs
هذا:
dense = layers.Dense(64, activation="relu")
x = dense(inputs)عملية "استدعاء الطبقة" أشبه برسم سهم من "inputs" إلى هذه الطبقة
التي أنشأتها.
أنت "تمرّر" المدخلات إلى الطبقة dense، وتحصل على x كمخرج.
لنضِف بعض الطبقات الإضافية إلى مخطط الطبقات:
x = layers.Dense(64, activation="relu")(x)
outputs = layers.Dense(10)(x)عند هذه النقطة، يمكنك إنشاء Model بتحديد مدخلاته ومخرجاته
في مخطط الطبقات:
model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")لنتحقق من شكل ملخص النموذج:
model.summary()[1mModel: "mnist_model"[0m
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃[1m [0m[1mLayer (type) [0m[1m [0m┃[1m [0m[1mOutput Shape [0m[1m [0m┃[1m [0m[1m Param #[0m[1m [0m┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ input_layer_4 ([38;5;33mInputLayer[0m) │ ([38;5;45mNone[0m, [38;5;34m784[0m) │ [38;5;34m0[0m │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_14 ([38;5;33mDense[0m) │ ([38;5;45mNone[0m, [38;5;34m64[0m) │ [38;5;34m50,240[0m │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_15 ([38;5;33mDense[0m) │ ([38;5;45mNone[0m, [38;5;34m64[0m) │ [38;5;34m4,160[0m │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_16 ([38;5;33mDense[0m) │ ([38;5;45mNone[0m, [38;5;34m10[0m) │ [38;5;34m650[0m │
└─────────────────────────────────┴────────────────────────┴───────────────┘
[1m Total params: [0m[38;5;34m55,050[0m (215.04 KB)
[1m Trainable params: [0m[38;5;34m55,050[0m (215.04 KB)
[1m Non-trainable params: [0m[38;5;34m0[0m (0.00 B)يمكنك أيضًا رسم النموذج كمخطط (Graph):
keras.utils.plot_model(model, "my_first_model.png")وبشكل اختياري، عرض أشكال الإدخال والإخراج لكل طبقة في المخطط المرسوم:
keras.utils.plot_model(model, "my_first_model_with_shape_info.png", show_shapes=True)هذا الشكل والكود متطابقان تقريبًا. في نسخة الكود، تُستبدَل أسهم الاتصال بعملية الاستدعاء (Call Operation).
"مخطط الطبقات" هو صورة ذهنية بديهية لنموذج التعلّم العميق، والواجهة الوظيفية هي طريقة لإنشاء نماذج تعكس هذه الصورة بشكل وثيق.