"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {},
31 | "source": [
32 | "# Setup\n",
33 | "First, let's import a few common modules, ensure MatplotLib plots figures inline and prepare a function to save the figures. We also check that Python 3.5 or later is installed (although Python 2.x may work, it is deprecated so we strongly recommend you use Python 3 instead), as well as Scikit-Learn ≥0.20 and TensorFlow ≥2.0.\n"
34 | ]
35 | },
36 | {
37 | "cell_type": "code",
38 | "execution_count": 1,
39 | "metadata": {},
40 | "outputs": [],
41 | "source": [
42 | "# Python ≥3.5 is required\n",
43 | "import sys\n",
44 | "assert sys.version_info >= (3, 5)\n",
45 | "\n",
46 | "# Scikit-Learn ≥0.20 is required\n",
47 | "import sklearn\n",
48 | "assert sklearn.__version__ >= \"0.20\"\n",
49 | "\n",
50 | "try:\n",
51 | " # %tensorflow_version only exists in Colab.\n",
52 | " %tensorflow_version 2.x\n",
53 | " !echo \"deb http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal\" > /etc/apt/sources.list.d/tensorflow-serving.list\n",
54 | " !curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | apt-key add -\n",
55 | " !apt update && apt-get install -y tensorflow-model-server\n",
56 | " !pip install -q -U tensorflow-serving-api\n",
57 | " IS_COLAB = True\n",
58 | "except Exception:\n",
59 | " IS_COLAB = False\n",
60 | "\n",
61 | "# TensorFlow ≥2.0 is required\n",
62 | "import tensorflow as tf\n",
63 | "from tensorflow import keras\n",
64 | "assert tf.__version__ >= \"2.0\"\n",
65 | "\n",
66 | "if not tf.config.list_physical_devices('GPU'):\n",
67 | " print(\"No GPU was detected. CNNs can be very slow without a GPU.\")\n",
68 | " if IS_COLAB:\n",
69 | " print(\"Go to Runtime > Change runtime and select a GPU hardware accelerator.\")\n",
70 | "\n",
71 | "# Common imports\n",
72 | "import numpy as np\n",
73 | "import os\n",
74 | "\n",
75 | "# to make this notebook's output stable across runs\n",
76 | "np.random.seed(42)\n",
77 | "tf.random.set_seed(42)\n",
78 | "\n",
79 | "# To plot pretty figures\n",
80 | "%matplotlib inline\n",
81 | "import matplotlib as mpl\n",
82 | "import matplotlib.pyplot as plt\n",
83 | "mpl.rc('axes', labelsize=14)\n",
84 | "mpl.rc('xtick', labelsize=12)\n",
85 | "mpl.rc('ytick', labelsize=12)\n",
86 | "\n",
87 | "# Where to save the figures\n",
88 | "PROJECT_ROOT_DIR = \".\"\n",
89 | "CHAPTER_ID = \"deploy\"\n",
90 | "IMAGES_PATH = os.path.join(PROJECT_ROOT_DIR, \"images\", CHAPTER_ID)\n",
91 | "os.makedirs(IMAGES_PATH, exist_ok=True)\n",
92 | "\n",
93 | "def save_fig(fig_id, tight_layout=True, fig_extension=\"png\", resolution=300):\n",
94 | " path = os.path.join(IMAGES_PATH, fig_id + \".\" + fig_extension)\n",
95 | " print(\"Saving figure\", fig_id)\n",
96 | " if tight_layout:\n",
97 | " plt.tight_layout()\n",
98 | " plt.savefig(path, format=fig_extension, dpi=resolution)"
99 | ]
100 | },
101 | {
102 | "cell_type": "markdown",
103 | "metadata": {},
104 | "source": [
105 | "# Deploying TensorFlow models to TensorFlow Serving (TFS)\n",
106 | "We will use the REST API or the gRPC API."
107 | ]
108 | },
109 | {
110 | "cell_type": "markdown",
111 | "metadata": {},
112 | "source": [
113 | "## Save/Load a `SavedModel`"
114 | ]
115 | },
116 | {
117 | "cell_type": "code",
118 | "execution_count": 2,
119 | "metadata": {},
120 | "outputs": [],
121 | "source": [
122 | "(X_train_full, y_train_full), (X_test, y_test) = keras.datasets.mnist.load_data()\n",
123 | "X_train_full = X_train_full[..., np.newaxis].astype(np.float32) / 255.\n",
124 | "X_test = X_test[..., np.newaxis].astype(np.float32) / 255.\n",
125 | "X_valid, X_train = X_train_full[:5000], X_train_full[5000:]\n",
126 | "y_valid, y_train = y_train_full[:5000], y_train_full[5000:]\n",
127 | "X_new = X_test[:3]"
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "execution_count": 3,
133 | "metadata": {},
134 | "outputs": [
135 | {
136 | "name": "stdout",
137 | "output_type": "stream",
138 | "text": [
139 | "Train on 55000 samples, validate on 5000 samples\n",
140 | "Epoch 1/10\n",
141 | "55000/55000 [==============================] - 2s 40us/sample - loss: 0.7018 - accuracy: 0.8223 - val_loss: 0.3722 - val_accuracy: 0.9022\n",
142 | "Epoch 2/10\n",
143 | "55000/55000 [==============================] - 2s 36us/sample - loss: 0.3528 - accuracy: 0.9021 - val_loss: 0.3000 - val_accuracy: 0.9170\n",
144 | "Epoch 3/10\n",
145 | "55000/55000 [==============================] - 2s 36us/sample - loss: 0.3032 - accuracy: 0.9150 - val_loss: 0.2659 - val_accuracy: 0.9280\n",
146 | "Epoch 4/10\n",
147 | "55000/55000 [==============================] - 2s 37us/sample - loss: 0.2730 - accuracy: 0.9233 - val_loss: 0.2442 - val_accuracy: 0.9342\n",
148 | "Epoch 5/10\n",
149 | "55000/55000 [==============================] - 2s 37us/sample - loss: 0.2504 - accuracy: 0.9305 - val_loss: 0.2272 - val_accuracy: 0.9346\n",
150 | "Epoch 6/10\n",
151 | "55000/55000 [==============================] - 2s 37us/sample - loss: 0.2319 - accuracy: 0.9353 - val_loss: 0.2104 - val_accuracy: 0.9418\n",
152 | "Epoch 7/10\n",
153 | "55000/55000 [==============================] - 2s 37us/sample - loss: 0.2156 - accuracy: 0.9395 - val_loss: 0.1987 - val_accuracy: 0.9484\n",
154 | "Epoch 8/10\n",
155 | "55000/55000 [==============================] - 2s 36us/sample - loss: 0.2019 - accuracy: 0.9434 - val_loss: 0.1893 - val_accuracy: 0.9496\n",
156 | "Epoch 9/10\n",
157 | "55000/55000 [==============================] - 2s 41us/sample - loss: 0.1898 - accuracy: 0.9471 - val_loss: 0.1765 - val_accuracy: 0.9526\n",
158 | "Epoch 10/10\n",
159 | "55000/55000 [==============================] - 2s 39us/sample - loss: 0.1791 - accuracy: 0.9495 - val_loss: 0.1691 - val_accuracy: 0.9550\n"
160 | ]
161 | },
162 | {
163 | "data": {
164 | "text/plain": [
165 | "