|
142 | 142 | }, |
143 | 143 | "outputs": [], |
144 | 144 | "source": [ |
145 | | - "!pip install pyyaml h5py # Required to save models in HDF5 format" |
| 145 | + "!pip install pyyaml h5py # Required to save models in HDF5 format." |
146 | 146 | ] |
147 | 147 | }, |
148 | 148 | { |
|
266 | 266 | }, |
267 | 267 | "outputs": [], |
268 | 268 | "source": [ |
269 | | - "checkpoint_path = \"training_1/cp.ckpt\"\n", |
| 269 | + "checkpoint_path = \"training_1/cp.weights.h5\" # we are only saving weights therefore we need to use .weights.h5 extension instead we would use .keras for whole model\n", |
270 | 270 | "checkpoint_dir = os.path.dirname(checkpoint_path)\n", |
271 | 271 | "\n", |
272 | 272 | "# Create a callback that saves the model's weights\n", |
|
275 | 275 | " verbose=1)\n", |
276 | 276 | "\n", |
277 | 277 | "# Train the model with the new callback\n", |
278 | | - "model.fit(train_images, \n", |
279 | | - " train_labels, \n", |
| 278 | + "model.fit(train_images,\n", |
| 279 | + " train_labels,\n", |
280 | 280 | " epochs=10,\n", |
281 | 281 | " validation_data=(test_images, test_labels),\n", |
282 | 282 | " callbacks=[cp_callback]) # Pass callback to training\n", |
|
312 | 312 | "id": "wlRN_f56Pqa9" |
313 | 313 | }, |
314 | 314 | "source": [ |
315 | | - "As long as two models share the same architecture you can share weights between them. So, when restoring a model from weights-only, create a model with the same architecture as the original model and then set its weights. \n", |
| 315 | + "As long as two models share the same architecture you can share weights between them. So, when restoring a model from weights-only, create a model with the same architecture as the original model and then set its weights.\n", |
316 | 316 | "\n", |
317 | 317 | "Now rebuild a fresh, untrained model and evaluate it on the test set. An untrained model will perform at chance levels (~10% accuracy):" |
318 | 318 | ] |
|
380 | 380 | "outputs": [], |
381 | 381 | "source": [ |
382 | 382 | "# Include the epoch in the file name (uses `str.format`)\n", |
383 | | - "checkpoint_path = \"training_2/cp-{epoch:04d}.ckpt\"\n", |
| 383 | + "checkpoint_path = \"training_2/cp-{epoch:04d}.weights.h5\"\n", |
384 | 384 | "checkpoint_dir = os.path.dirname(checkpoint_path)\n", |
| 385 | + "os.mkdir(checkpoint_dir)\n", |
385 | 386 | "\n", |
386 | 387 | "batch_size = 32\n", |
387 | 388 | "\n", |
|
392 | 393 | "\n", |
393 | 394 | "# Create a callback that saves the model's weights every 5 epochs\n", |
394 | 395 | "cp_callback = tf.keras.callbacks.ModelCheckpoint(\n", |
395 | | - " filepath=checkpoint_path, \n", |
396 | | - " verbose=1, \n", |
| 396 | + " filepath=checkpoint_path,\n", |
| 397 | + " verbose=1,\n", |
397 | 398 | " save_weights_only=True,\n", |
398 | 399 | " save_freq=5*n_batches)\n", |
399 | 400 | "\n", |
|
404 | 405 | "model.save_weights(checkpoint_path.format(epoch=0))\n", |
405 | 406 | "\n", |
406 | 407 | "# Train the model with the new callback\n", |
407 | | - "model.fit(train_images, \n", |
| 408 | + "model.fit(train_images,\n", |
408 | 409 | " train_labels,\n", |
409 | | - " epochs=50, \n", |
410 | | - " batch_size=batch_size, \n", |
| 410 | + " epochs=50,\n", |
| 411 | + " batch_size=batch_size,\n", |
411 | 412 | " callbacks=[cp_callback],\n", |
412 | 413 | " validation_data=(test_images, test_labels),\n", |
413 | 414 | " verbose=0)" |
|
441 | 442 | }, |
442 | 443 | "outputs": [], |
443 | 444 | "source": [ |
444 | | - "latest = tf.train.latest_checkpoint(checkpoint_dir)\n", |
| 445 | + "def load_latest_checkpoint(checkpoint_dir):\n", |
| 446 | + " latest = max(os.listdir(checkpoint_dir), key=lambda f: int(f.split('-')[1].split('.')[0]))\n", |
| 447 | + " return os.path.join(checkpoint_dir, latest)\n", |
| 448 | + "\n", |
| 449 | + "latest = load_latest_checkpoint(checkpoint_dir)\n", |
445 | 450 | "latest" |
446 | 451 | ] |
447 | 452 | }, |
|
505 | 510 | "source": [ |
506 | 511 | "## Manually save weights\n", |
507 | 512 | "\n", |
508 | | - "To save weights manually, use `tf.keras.Model.save_weights`. By default, `tf.keras`—and the `Model.save_weights` method in particular—uses the TensorFlow [Checkpoint](../../guide/checkpoint.ipynb) format with a `.ckpt` extension. To save in the HDF5 format with a `.h5` extension, refer to the [Save and load models](https://www.tensorflow.org/guide/keras/save_and_serialize) guide." |
| 513 | + "To save weights manually, use `tf.keras.Model.save_weights`. You have to use .weights.h5 extension to save the weights. You can refer to the [Save and load models](https://www.tensorflow.org/guide/keras/save_and_serialize) guide." |
509 | 514 | ] |
510 | 515 | }, |
511 | 516 | { |
|
517 | 522 | "outputs": [], |
518 | 523 | "source": [ |
519 | 524 | "# Save the weights\n", |
520 | | - "model.save_weights('./checkpoints/my_checkpoint')\n", |
| 525 | + "os.mkdir('./checkpoints')\n", |
| 526 | + "model.save_weights('./checkpoints/my_checkpoint.weights.h5')\n", |
521 | 527 | "\n", |
522 | 528 | "# Create a new model instance\n", |
523 | 529 | "model = create_model()\n", |
524 | 530 | "\n", |
525 | 531 | "# Restore the weights\n", |
526 | | - "model.load_weights('./checkpoints/my_checkpoint')\n", |
| 532 | + "model.load_weights('./checkpoints/my_checkpoint.weights.h5')\n", |
527 | 533 | "\n", |
528 | 534 | "# Evaluate the model\n", |
529 | 535 | "loss, acc = model.evaluate(test_images, test_labels, verbose=2)\n", |
|
657 | 663 | "id": "LtcN4VIb7JkK" |
658 | 664 | }, |
659 | 665 | "source": [ |
660 | | - "The SavedModel format is another way to serialize models. Models saved in this format can be restored using `tf.keras.models.load_model` and are compatible with TensorFlow Serving. The [SavedModel guide](../../guide/saved_model.ipynb) goes into detail about how to `serve/inspect` the SavedModel. The section below illustrates the steps to save and restore the model." |
| 666 | + "The SavedModel format is another way to serialize models. Models saved in this format can directly be used with TFLite/TFServing/etc for inferencing. The [SavedModel guide](../../guide/saved_model.ipynb) goes into detail about how to `serve/inspect` the SavedModel. The section below illustrates the steps to save and restore the model." |
661 | 667 | ] |
662 | 668 | }, |
663 | 669 | { |
|
674 | 680 | "\n", |
675 | 681 | "# Save the entire model as a SavedModel.\n", |
676 | 682 | "!mkdir -p saved_model\n", |
677 | | - "model.save('saved_model/my_model') " |
| 683 | + "tf.saved_model.save(model, 'saved_model/my_model')" |
678 | 684 | ] |
679 | 685 | }, |
680 | 686 | { |
|
707 | 713 | "id": "B7qfpvpY9HCe" |
708 | 714 | }, |
709 | 715 | "source": [ |
710 | | - "Reload a fresh Keras model from the saved model:" |
| 716 | + "Reload the saved SavedModel file:" |
711 | 717 | ] |
712 | 718 | }, |
713 | 719 | { |
|
718 | 724 | }, |
719 | 725 | "outputs": [], |
720 | 726 | "source": [ |
721 | | - "new_model = tf.keras.models.load_model('saved_model/my_model')\n", |
722 | | - "\n", |
723 | | - "# Check its architecture\n", |
724 | | - "new_model.summary()" |
725 | | - ] |
726 | | - }, |
727 | | - { |
728 | | - "cell_type": "markdown", |
729 | | - "metadata": { |
730 | | - "id": "uWwgNaz19TH2" |
731 | | - }, |
732 | | - "source": [ |
733 | | - "The restored model is compiled with the same arguments as the original model. Try running evaluate and predict with the loaded model:" |
734 | | - ] |
735 | | - }, |
736 | | - { |
737 | | - "cell_type": "code", |
738 | | - "execution_count": null, |
739 | | - "metadata": { |
740 | | - "id": "Yh5Mu0yOgE5J" |
741 | | - }, |
742 | | - "outputs": [], |
743 | | - "source": [ |
744 | | - "# Evaluate the restored model\n", |
745 | | - "loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)\n", |
746 | | - "print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))\n", |
747 | | - "\n", |
748 | | - "print(new_model.predict(test_images).shape)" |
| 727 | + "saved_model = tf.saved_model.load('saved_model/my_model')\n", |
| 728 | + "saved_model" |
749 | 729 | ] |
750 | 730 | }, |
751 | 731 | { |
|
756 | 736 | "source": [ |
757 | 737 | "### HDF5 format\n", |
758 | 738 | "\n", |
759 | | - "Keras provides a basic legacy high-level save format using the [HDF5](https://en.wikipedia.org/wiki/Hierarchical_Data_Format) standard. " |
| 739 | + "Keras provides a basic legacy high-level save format using the [HDF5](https://en.wikipedia.org/wiki/Hierarchical_Data_Format) standard." |
760 | 740 | ] |
761 | 741 | }, |
762 | 742 | { |
|
773 | 753 | "\n", |
774 | 754 | "# Save the entire model to a HDF5 file.\n", |
775 | 755 | "# The '.h5' extension indicates that the model should be saved to HDF5.\n", |
776 | | - "model.save('my_model.h5') " |
| 756 | + "model.save('my_model.h5')" |
777 | 757 | ] |
778 | 758 | }, |
779 | 759 | { |
|
859 | 839 | "\n", |
860 | 840 | "Refer to the [Writing layers and models from scratch](https://www.tensorflow.org/guide/keras/custom_layers_and_models) tutorial for examples of custom objects and `get_config`.\n" |
861 | 841 | ] |
862 | | - }, |
863 | | - { |
864 | | - "cell_type": "code", |
865 | | - "execution_count": null, |
866 | | - "metadata": { |
867 | | - "id": "jBVTkkUIkEF3" |
868 | | - }, |
869 | | - "outputs": [], |
870 | | - "source": [] |
871 | 842 | } |
872 | 843 | ], |
873 | 844 | "metadata": { |
874 | 845 | "accelerator": "GPU", |
875 | 846 | "colab": { |
876 | | - "collapsed_sections": [], |
877 | 847 | "name": "save_and_load.ipynb", |
878 | 848 | "toc_visible": true |
879 | 849 | }, |
|
0 commit comments