|
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