הצג באתר TensorFlow.org | הפעל בגוגל קולאב | צפה במקור ב-GitHub | הורד מחברת |
ניתן לשמור את התקדמות הדגם במהלך ואחרי האימון. המשמעות היא שדוגמנית יכולה להמשיך מהמקום שבו הפסיקה ולהימנע מזמני אימון ארוכים. שמירה פירושה גם שאתה יכול לשתף את הדגם שלך ואחרים יכולים ליצור מחדש את העבודה שלך. בעת פרסום מודלים וטכניקות מחקר, רוב המתרגלים למידת מכונה חולקים:
- קוד ליצירת המודל, ו
- המשקולות המאומנות, או הפרמטרים, עבור הדגם
שיתוף הנתונים האלה עוזר לאחרים להבין איך המודל עובד ולנסות אותו בעצמם עם נתונים חדשים.
אפשרויות
ישנן דרכים שונות לשמור דגמי TensorFlow בהתאם ל-API שבו אתה משתמש. מדריך זה משתמש ב- tf.keras , ממשק API ברמה גבוהה כדי לבנות ולהכשיר מודלים ב-TensorFlow. לגישות אחרות עיין במדריך השמירה והשחזור של TensorFlow או Saving in eager .
להכין
התקנות וייבוא
התקנה ויבוא של TensorFlow ותלויות:
pip install pyyaml h5py # Required to save models in HDF5 format
import os
import tensorflow as tf
from tensorflow import keras
print(tf.version.VERSION)
2.8.0-rc1
קבל דוגמה למערך נתונים
כדי להדגים כיצד לשמור ולטעון משקלים, תשתמש במערך הנתונים של MNIST . כדי להאיץ את הריצות הללו, השתמש ב-1000 הדוגמאות הראשונות:
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()
train_labels = train_labels[:1000]
test_labels = test_labels[:1000]
train_images = train_images[:1000].reshape(-1, 28 * 28) / 255.0
test_images = test_images[:1000].reshape(-1, 28 * 28) / 255.0
הגדירו דגם
התחל בבניית מודל רציף פשוט:
# Define a simple sequential model
def create_model():
model = tf.keras.models.Sequential([
keras.layers.Dense(512, activation='relu', input_shape=(784,)),
keras.layers.Dropout(0.2),
keras.layers.Dense(10)
])
model.compile(optimizer='adam',
loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=[tf.metrics.SparseCategoricalAccuracy()])
return model
# Create a basic model instance
model = create_model()
# Display the model's architecture
model.summary()
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense (Dense) (None, 512) 401920 dropout (Dropout) (None, 512) 0 dense_1 (Dense) (None, 10) 5130 ================================================================= Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 _________________________________________________________________
שמור מחסומים במהלך האימון
אתה יכול להשתמש במודל מאומן מבלי להכשיר אותו מחדש, או להמשיך באימונים מהמקום שבו הפסקת למקרה שתהליך האימון הופסק. ה- tf.keras.callbacks.ModelCheckpoint
התקשרות חוזרת מאפשרת לך לשמור את הדגם ללא הרף גם במהלך האימון וגם בסוף .
שימוש בנקודת התקשרות חוזרת
צור callback tf.keras.callbacks.ModelCheckpoint
שחוסך משקלים רק במהלך האימון:
checkpoint_path = "training_1/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
# Create a callback that saves the model's weights
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
save_weights_only=True,
verbose=1)
# Train the model with the new callback
model.fit(train_images,
train_labels,
epochs=10,
validation_data=(test_images, test_labels),
callbacks=[cp_callback]) # Pass callback to training
# This may generate warnings related to saving the state of the optimizer.
# These warnings (and similar warnings throughout this notebook)
# are in place to discourage outdated usage, and can be ignored.
Epoch 1/10 23/32 [====================>.........] - ETA: 0s - loss: 1.3666 - sparse_categorical_accuracy: 0.6060 Epoch 1: saving model to training_1/cp.ckpt 32/32 [==============================] - 1s 10ms/step - loss: 1.1735 - sparse_categorical_accuracy: 0.6690 - val_loss: 0.7180 - val_sparse_categorical_accuracy: 0.7750 Epoch 2/10 24/32 [=====================>........] - ETA: 0s - loss: 0.4238 - sparse_categorical_accuracy: 0.8789 Epoch 2: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.4201 - sparse_categorical_accuracy: 0.8810 - val_loss: 0.5621 - val_sparse_categorical_accuracy: 0.8150 Epoch 3/10 24/32 [=====================>........] - ETA: 0s - loss: 0.2795 - sparse_categorical_accuracy: 0.9336 Epoch 3: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.2815 - sparse_categorical_accuracy: 0.9310 - val_loss: 0.4790 - val_sparse_categorical_accuracy: 0.8430 Epoch 4/10 24/32 [=====================>........] - ETA: 0s - loss: 0.2027 - sparse_categorical_accuracy: 0.9427 Epoch 4: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.2016 - sparse_categorical_accuracy: 0.9440 - val_loss: 0.4361 - val_sparse_categorical_accuracy: 0.8610 Epoch 5/10 24/32 [=====================>........] - ETA: 0s - loss: 0.1739 - sparse_categorical_accuracy: 0.9583 Epoch 5: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.1683 - sparse_categorical_accuracy: 0.9610 - val_loss: 0.4640 - val_sparse_categorical_accuracy: 0.8580 Epoch 6/10 23/32 [====================>.........] - ETA: 0s - loss: 0.1116 - sparse_categorical_accuracy: 0.9796 Epoch 6: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.1125 - sparse_categorical_accuracy: 0.9780 - val_loss: 0.4420 - val_sparse_categorical_accuracy: 0.8580 Epoch 7/10 24/32 [=====================>........] - ETA: 0s - loss: 0.0978 - sparse_categorical_accuracy: 0.9831 Epoch 7: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.0989 - sparse_categorical_accuracy: 0.9820 - val_loss: 0.4163 - val_sparse_categorical_accuracy: 0.8590 Epoch 8/10 21/32 [==================>...........] - ETA: 0s - loss: 0.0669 - sparse_categorical_accuracy: 0.9911 Epoch 8: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 6ms/step - loss: 0.0690 - sparse_categorical_accuracy: 0.9910 - val_loss: 0.4411 - val_sparse_categorical_accuracy: 0.8600 Epoch 9/10 22/32 [===================>..........] - ETA: 0s - loss: 0.0495 - sparse_categorical_accuracy: 0.9972 Epoch 9: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.0516 - sparse_categorical_accuracy: 0.9950 - val_loss: 0.4064 - val_sparse_categorical_accuracy: 0.8650 Epoch 10/10 24/32 [=====================>........] - ETA: 0s - loss: 0.0436 - sparse_categorical_accuracy: 0.9948 Epoch 10: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.0437 - sparse_categorical_accuracy: 0.9960 - val_loss: 0.4061 - val_sparse_categorical_accuracy: 0.8770 <keras.callbacks.History at 0x7eff8d865390>
זה יוצר אוסף יחיד של קבצי נקודת ביקורת TensorFlow שמתעדכנים בסוף כל תקופה:
os.listdir(checkpoint_dir)
['checkpoint', 'cp.ckpt.index', 'cp.ckpt.data-00000-of-00001']
כל עוד שני דגמים חולקים את אותה ארכיטקטורה אתה יכול לחלוק משקלים ביניהם. לכן, כאשר משחזרים מודל ממשקולות בלבד, צור דגם עם אותה ארכיטקטורה כמו הדגם המקורי ולאחר מכן קבע את המשקולות שלו.
כעת בנה מחדש דגם חדש ולא מיומן והעריך אותו במערך המבחן. דגם לא מאומן יתפקד ברמות סיכוי (דיוק של 10% בערך):
# Create a basic model instance
model = create_model()
# Evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Untrained model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 2.4473 - sparse_categorical_accuracy: 0.0980 - 145ms/epoch - 5ms/step Untrained model, accuracy: 9.80%
לאחר מכן טען את המשקולות מהמחסום והעריך מחדש:
# Loads the weights
model.load_weights(checkpoint_path)
# Re-evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 0.4061 - sparse_categorical_accuracy: 0.8770 - 65ms/epoch - 2ms/step Restored model, accuracy: 87.70%
אפשרויות התקשרות חוזרת של נקודת ביקורת
ההתקשרות חזרה מספקת מספר אפשרויות לספק שמות ייחודיים למחסומים ולהתאים את תדירות הביקורת.
אמן דגם חדש ושמור נקודות ביקורת עם שם ייחודי אחת לחמש תקופות:
# Include the epoch in the file name (uses `str.format`)
checkpoint_path = "training_2/cp-{epoch:04d}.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
batch_size = 32
# Create a callback that saves the model's weights every 5 epochs
cp_callback = tf.keras.callbacks.ModelCheckpoint(
filepath=checkpoint_path,
verbose=1,
save_weights_only=True,
save_freq=5*batch_size)
# Create a new model instance
model = create_model()
# Save the weights using the `checkpoint_path` format
model.save_weights(checkpoint_path.format(epoch=0))
# Train the model with the new callback
model.fit(train_images,
train_labels,
epochs=50,
batch_size=batch_size,
callbacks=[cp_callback],
validation_data=(test_images, test_labels),
verbose=0)
Epoch 5: saving model to training_2/cp-0005.ckpt Epoch 10: saving model to training_2/cp-0010.ckpt Epoch 15: saving model to training_2/cp-0015.ckpt Epoch 20: saving model to training_2/cp-0020.ckpt Epoch 25: saving model to training_2/cp-0025.ckpt Epoch 30: saving model to training_2/cp-0030.ckpt Epoch 35: saving model to training_2/cp-0035.ckpt Epoch 40: saving model to training_2/cp-0040.ckpt Epoch 45: saving model to training_2/cp-0045.ckpt Epoch 50: saving model to training_2/cp-0050.ckpt <keras.callbacks.History at 0x7eff807703d0>
כעת, התבונן בנקודות הבידוק שהתקבלו ובחר את האחרון:
os.listdir(checkpoint_dir)
['cp-0005.ckpt.data-00000-of-00001', 'cp-0050.ckpt.index', 'checkpoint', 'cp-0010.ckpt.index', 'cp-0035.ckpt.data-00000-of-00001', 'cp-0000.ckpt.data-00000-of-00001', 'cp-0050.ckpt.data-00000-of-00001', 'cp-0010.ckpt.data-00000-of-00001', 'cp-0020.ckpt.data-00000-of-00001', 'cp-0035.ckpt.index', 'cp-0040.ckpt.index', 'cp-0025.ckpt.data-00000-of-00001', 'cp-0045.ckpt.index', 'cp-0020.ckpt.index', 'cp-0025.ckpt.index', 'cp-0030.ckpt.data-00000-of-00001', 'cp-0030.ckpt.index', 'cp-0000.ckpt.index', 'cp-0045.ckpt.data-00000-of-00001', 'cp-0015.ckpt.index', 'cp-0015.ckpt.data-00000-of-00001', 'cp-0005.ckpt.index', 'cp-0040.ckpt.data-00000-of-00001']
latest = tf.train.latest_checkpoint(checkpoint_dir)
latest
'training_2/cp-0050.ckpt'
כדי לבדוק, אפס את הדגם וטען את נקודת הבידוק העדכנית ביותר:
# Create a new model instance
model = create_model()
# Load the previously saved weights
model.load_weights(latest)
# Re-evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 0.4996 - sparse_categorical_accuracy: 0.8770 - 150ms/epoch - 5ms/step Restored model, accuracy: 87.70%
מה זה הקבצים האלה?
הקוד לעיל מאחסן את המשקולות לאוסף של קבצים בפורמט של נקודת ביקורת המכילים רק את המשקולות המאומנות בפורמט בינארי. מחסומים מכילים:
- רסיס אחד או יותר המכילים את המשקולות של הדגם שלך.
- קובץ אינדקס המציין אילו משקלים מאוחסנים באיזה רסיס.
אם אתה מאמן דגם במכונה בודדת, יהיה לך רסיס אחד עם הסיומת: .data-00000-of-00001
שמור משקלים באופן ידני
שמירת משקלים באופן ידני בשיטת Model.save_weights
. כברירת מחדל, tf.keras
— ובפרט save_weights
— משתמש בפורמט נקודת המחסום TensorFlow עם סיומת .ckpt
(שמירה ב- HDF5 עם סיומת .h5
מכוסה במדריך Save and serialize models ):
# Save the weights
model.save_weights('./checkpoints/my_checkpoint')
# Create a new model instance
model = create_model()
# Restore the weights
model.load_weights('./checkpoints/my_checkpoint')
# Evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 0.4996 - sparse_categorical_accuracy: 0.8770 - 143ms/epoch - 4ms/step Restored model, accuracy: 87.70%
שמור את כל הדגם
התקשר ל- model.save
כדי לשמור את הארכיטקטורה, המשקלים ותצורת האימון של הדגם בקובץ/תיקיה בודדים. זה מאפשר לך לייצא מודל כך שניתן יהיה להשתמש בו ללא גישה לקוד Python המקורי*. מכיוון שמצב האופטימיזציה משוחזר, אתה יכול להמשיך את האימון בדיוק מהמקום שבו הפסקת.
ניתן לשמור דגם שלם בשני פורמטים שונים של קבצים ( SavedModel
ו- HDF5
). פורמט SavedModel
הוא פורמט הקובץ המוגדר כברירת מחדל ב-TF2.x. עם זאת, ניתן לשמור דגמים בפורמט HDF5
. פרטים נוספים על שמירת דגמים שלמים בשני פורמטי הקבצים מתוארים להלן.
שמירת מודל תפקודי מלא היא שימושית מאוד - אתה יכול לטעון אותם ב-TensorFlow.js ( דגם שמור , HDF5 ) ולאחר מכן לאמן ולהפעיל אותם בדפדפני אינטרנט, או להמיר אותם להפעלה במכשירים ניידים באמצעות TensorFlow Lite ( דגם שמור , HDF5 )
*אובייקטים מותאמים אישית (כגון דגמים או שכבות בסיווג משנה) דורשים תשומת לב מיוחדת בעת שמירה וטעינה. עיין בסעיף שמירת אובייקטים מותאמים אישית למטה
פורמט SavedModel
הפורמט SavedModel הוא דרך נוספת ליצירת מודלים בסידרה. ניתן לשחזר מודלים שנשמרו בפורמט זה באמצעות tf.keras.models.load_model
והם תואמים ל- TensorFlow Serving. המדריך SavedModel מפרט כיצד להגיש/לבדוק את SavedModel. הסעיף שלהלן ממחיש את השלבים לשמירה ושחזור של המודל.
# Create and train a new model instance.
model = create_model()
model.fit(train_images, train_labels, epochs=5)
# Save the entire model as a SavedModel.
!mkdir -p saved_model
model.save('saved_model/my_model')
Epoch 1/5 32/32 [==============================] - 0s 2ms/step - loss: 1.1988 - sparse_categorical_accuracy: 0.6550 Epoch 2/5 32/32 [==============================] - 0s 2ms/step - loss: 0.4180 - sparse_categorical_accuracy: 0.8930 Epoch 3/5 32/32 [==============================] - 0s 2ms/step - loss: 0.2900 - sparse_categorical_accuracy: 0.9220 Epoch 4/5 32/32 [==============================] - 0s 2ms/step - loss: 0.2070 - sparse_categorical_accuracy: 0.9540 Epoch 5/5 32/32 [==============================] - 0s 2ms/step - loss: 0.1593 - sparse_categorical_accuracy: 0.9630 2022-01-26 07:30:22.888387: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. WARNING:tensorflow:Detecting that an object or model or tf.train.Checkpoint is being deleted with unrestored values. See the following logs for the specific values in question. To silence these warnings, use `status.expect_partial()`. See https://www.tensorflow.org/api_docs/python/tf/train/Checkpoint#restorefor details about the status object returned by the restore function. WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.iter WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.beta_1 WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.beta_2 WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.decay WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.learning_rate WARNING:tensorflow:Detecting that an object or model or tf.train.Checkpoint is being deleted with unrestored values. See the following logs for the specific values in question. To silence these warnings, use `status.expect_partial()`. See https://www.tensorflow.org/api_docs/python/tf/train/Checkpoint#restorefor details about the status object returned by the restore function. WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.iter WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.beta_1 WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.beta_2 WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.decay WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.learning_rate INFO:tensorflow:Assets written to: saved_model/my_model/assets
הפורמט SavedModel הוא ספרייה המכילה פרוטובוף בינארי ונקודת ביקורת TensorFlow. בדוק את ספריית הדגם השמורה:
# my_model directory
ls saved_model
# Contains an assets folder, saved_model.pb, and variables folder.
ls saved_model/my_model
my_model assets keras_metadata.pb saved_model.pb variables
טען מחדש דגם חדש של Keras מהדגם השמור:
new_model = tf.keras.models.load_model('saved_model/my_model')
# Check its architecture
new_model.summary()
Model: "sequential_5" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_10 (Dense) (None, 512) 401920 dropout_5 (Dropout) (None, 512) 0 dense_11 (Dense) (None, 10) 5130 ================================================================= Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 _________________________________________________________________
המודל המשוחזר מורכב עם אותם טיעונים כמו הדגם המקורי. נסה להריץ הערכה וחיזוי עם המודל הנטען:
# Evaluate the restored model
loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))
print(new_model.predict(test_images).shape)
32/32 - 0s - loss: 0.4577 - sparse_categorical_accuracy: 0.8430 - 156ms/epoch - 5ms/step Restored model, accuracy: 84.30% (1000, 10)
פורמט HDF5
Keras מספקת פורמט שמירה בסיסי באמצעות תקן HDF5 .
# Create and train a new model instance.
model = create_model()
model.fit(train_images, train_labels, epochs=5)
# Save the entire model to a HDF5 file.
# The '.h5' extension indicates that the model should be saved to HDF5.
model.save('my_model.h5')
Epoch 1/5 32/32 [==============================] - 0s 2ms/step - loss: 1.1383 - sparse_categorical_accuracy: 0.6970 Epoch 2/5 32/32 [==============================] - 0s 2ms/step - loss: 0.4094 - sparse_categorical_accuracy: 0.8920 Epoch 3/5 32/32 [==============================] - 0s 2ms/step - loss: 0.2936 - sparse_categorical_accuracy: 0.9160 Epoch 4/5 32/32 [==============================] - 0s 2ms/step - loss: 0.2050 - sparse_categorical_accuracy: 0.9460 Epoch 5/5 32/32 [==============================] - 0s 2ms/step - loss: 0.1485 - sparse_categorical_accuracy: 0.9690
כעת, צור מחדש את המודל מהקובץ הזה:
# Recreate the exact same model, including its weights and the optimizer
new_model = tf.keras.models.load_model('my_model.h5')
# Show the model architecture
new_model.summary()
Model: "sequential_6" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_12 (Dense) (None, 512) 401920 dropout_6 (Dropout) (None, 512) 0 dense_13 (Dense) (None, 10) 5130 ================================================================= Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 _________________________________________________________________
בדוק את הדיוק שלו:
loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))
32/32 - 0s - loss: 0.4266 - sparse_categorical_accuracy: 0.8620 - 141ms/epoch - 4ms/step Restored model, accuracy: 86.20%
קרס מציל דגמים על ידי בדיקת הארכיטקטורות שלהם. טכניקה זו חוסכת הכל:
- ערכי המשקל
- הארכיטקטורה של הדגם
- תצורת האימון של המודל (מה שאתה מעביר לשיטת
.compile()
) - האופטימיזציה והמצב שלו, אם בכלל (זה מאפשר לך להתחיל מחדש את האימון מהמקום שהפסקת)
Keras אינה מסוגלת לשמור את מטבי v1.x
(מ- tf.compat.v1.train
) מכיוון שהם אינם תואמים לנקודות ביקורת. עבור אופטימיזציית v1.x, עליך להרכיב מחדש את המודל לאחר הטעינה - איבוד מצב האופטימיזציה.
שמירת אובייקטים מותאמים אישית
אם אתה משתמש בפורמט SavedModel, אתה יכול לדלג על סעיף זה. ההבדל העיקרי בין HDF5 לבין SavedModel הוא ש-HDF5 משתמש בתצורות אובייקטים כדי לשמור את ארכיטקטורת המודל, בעוד SavedModel שומר את גרף הביצוע. לפיכך, SavedModels מסוגלים לשמור אובייקטים מותאמים אישית כמו דגמי תת-סיווג ושכבות מותאמות אישית מבלי לדרוש את הקוד המקורי.
כדי לשמור אובייקטים מותאמים אישית ב-HDF5, עליך לבצע את הפעולות הבאות:
- הגדר שיטת
get_config
באובייקט שלך, ובאופן אופציונליfrom_config
.-
get_config(self)
מחזיר מילון ניתן להסדרה של JSON של פרמטרים הדרושים ליצירה מחדש של האובייקט. -
from_config(cls, config)
משתמש בתצורה המוחזרת מ-get_config
כדי ליצור אובייקט חדש. כברירת מחדל, פונקציה זו תשתמש ב-config כאתחול kwargs (return cls(**config)
).
-
- העבר את האובייקט לארגומנט
custom_objects
בעת טעינת המודל. הארגומנט חייב להיות מילון הממפה את שם מחלקת המחרוזת למחלקה Python. למשלtf.keras.models.load_model(path, custom_objects={'CustomLayer': CustomLayer})
עיין במדריך כתיבת שכבות ומודלים מאפס לדוגמאות של אובייקטים מותאמים אישית ו- get_config
.
# MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.