Skip to content

Commit 0b5c084

Browse files
Merge pull request #677 from GoogleCloudPlatform/metric-update
replace custom RMSE metric to use keras3 metric
2 parents 90f7ac2 + 298d8da commit 0b5c084

File tree

6 files changed

+51
-116
lines changed

6 files changed

+51
-116
lines changed

notebooks/introduction_to_tensorflow/labs/3_keras_sequential_api_vertex.ipynb

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,8 @@
4848
"outputs": [],
4949
"source": [
5050
"import os\n",
51-
"import warnings\n",
5251
"\n",
53-
"os.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"2\"\n",
54-
"warnings.filterwarnings(\"ignore\")\n",
52+
"os.environ[\"KERAS_BACKEND\"] = \"tensorflow\"\n",
5553
"\n",
5654
"# Set `PATH` to include the directory containing saved_model_cli\n",
5755
"PATH = %env PATH\n",
@@ -60,17 +58,19 @@
6058
"import datetime\n",
6159
"import shutil\n",
6260
"\n",
61+
"import keras\n",
6362
"import numpy as np\n",
6463
"import pandas as pd\n",
65-
"import tensorflow as tf\n",
64+
"import tensorflow as tf # Used only for tf.data loader\n",
6665
"from google.cloud import aiplatform\n",
66+
"from keras import Input\n",
67+
"from keras.callbacks import TensorBoard\n",
68+
"from keras.layers import Dense\n",
69+
"from keras.metrics import RootMeanSquaredError\n",
70+
"from keras.models import Sequential\n",
6771
"from matplotlib import pyplot as plt\n",
68-
"from tensorflow import keras\n",
69-
"from tensorflow.keras.callbacks import TensorBoard\n",
70-
"from tensorflow.keras.layers import Dense\n",
71-
"from tensorflow.keras.models import Sequential\n",
7272
"\n",
73-
"print(tf.__version__)\n",
73+
"print(keras.__version__)\n",
7474
"%matplotlib inline"
7575
]
7676
},
@@ -183,16 +183,14 @@
183183
"\n",
184184
"* An optimizer. This could be the string identifier of an existing optimizer (such as `rmsprop` or `adagrad`), or an instance of the [Optimizer class](https://keras.io/api/optimizers/).\n",
185185
"* A loss function. This is the objective that the model will try to minimize. It can be the string identifier of an existing loss function from the [Losses class](https://keras.io/api/losses/) (such as `categorical_crossentropy` or `mse`), or it can be a custom objective function.\n",
186-
"* A list of metrics. For any machine learning problem you will want a set of metrics to evaluate your model. A metric could be the string identifier of an existing metric or a custom metric function.\n",
187-
"\n",
188-
"We will add an additional custom metric called `rmse` (Root Mean Squared Error). This custom metric is defined using `keras.ops` functions, making it compatible across different Keras backends (TensorFlow, JAX, PyTorch)."
186+
"* A list of metrics. For any machine learning problem you will want a set of metrics to evaluate your model. A metric could be the string identifier of an existing metric or a custom metric function."
189187
]
190188
},
191189
{
192190
"cell_type": "markdown",
193191
"metadata": {},
194192
"source": [
195-
"**Exercise.** Compile the model you created above. Create a custom loss function called `rmse` which computes the root mean squared error between `y_true` and `y_pred`. Pass this function to the model as an evaluation metric. "
193+
"**Exercise.** Compile the model you created above. Use `mse` as the loss function and `rmse` as the metric."
196194
]
197195
},
198196
{
@@ -201,11 +199,6 @@
201199
"metadata": {},
202200
"outputs": [],
203201
"source": [
204-
"# Create a custom evalution metric\n",
205-
"def rmse(y_true, y_pred):\n",
206-
" return # TODO: Your code here\n",
207-
"\n",
208-
"\n",
209202
"# Compile the keras model\n",
210203
"# TODO: Your code here"
211204
]
@@ -306,7 +299,7 @@
306299
"metadata": {},
307300
"outputs": [],
308301
"source": [
309-
"RMSE_COLS = [\"rmse\", \"val_rmse\"]\n",
302+
"RMSE_COLS = [\"root_mean_squared_error\", \"val_root_mean_squared_error\"]\n",
310303
"\n",
311304
"pd.DataFrame(history.history)[RMSE_COLS].plot()"
312305
]

notebooks/introduction_to_tensorflow/labs/4_keras_functional_api.ipynb

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
" HashedCrossing,\n",
6464
" Input,\n",
6565
")\n",
66+
"from keras.metrics import RootMeanSquaredError\n",
6667
"from matplotlib import pyplot as plt"
6768
]
6869
},
@@ -320,23 +321,6 @@
320321
"output = # TODO"
321322
]
322323
},
323-
{
324-
"cell_type": "markdown",
325-
"metadata": {},
326-
"source": [
327-
"Then, we'll define our custom RMSE evaluation metric and build our wide and deep model."
328-
]
329-
},
330-
{
331-
"cell_type": "code",
332-
"execution_count": null,
333-
"metadata": {},
334-
"outputs": [],
335-
"source": [
336-
"def rmse(y_true, y_pred):\n",
337-
" return tf.sqrt(tf.reduce_mean(tf.square(y_pred - y_true)))"
338-
]
339-
},
340324
{
341325
"cell_type": "markdown",
342326
"metadata": {},
@@ -354,7 +338,7 @@
354338
"source": [
355339
"model = Model(inputs=list(inputs.values()), outputs=output)\n",
356340
"\n",
357-
"model.compile(optimizer=\"adam\", loss=\"mse\", metrics=[rmse])"
341+
"model.compile(optimizer=\"adam\", loss=\"mse\", metrics=[RootMeanSquaredError()])"
358342
]
359343
},
360344
{
@@ -437,7 +421,7 @@
437421
"metadata": {},
438422
"outputs": [],
439423
"source": [
440-
"RMSE_COLS = [\"rmse\", \"val_rmse\"]\n",
424+
"RMSE_COLS = [\"root_mean_squared_error\", \"val_root_mean_squared_error\"]\n",
441425
"\n",
442426
"pd.DataFrame(history.history)[RMSE_COLS].plot()"
443427
]
@@ -460,9 +444,9 @@
460444
"metadata": {
461445
"environment": {
462446
"kernel": "conda-base-py",
463-
"name": "workbench-notebooks.m131",
447+
"name": "workbench-notebooks.m132",
464448
"type": "gcloud",
465-
"uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m131"
449+
"uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m132"
466450
},
467451
"kernelspec": {
468452
"display_name": "Python 3 (ipykernel) (Local)",

notebooks/introduction_to_tensorflow/labs/5_keras_adv_feat_eng.ipynb

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
" Input,\n",
5353
" Lambda,\n",
5454
")\n",
55+
"from keras.metrics import RootMeanSquaredError\n",
5556
"from matplotlib import pyplot as plt"
5657
]
5758
},
@@ -350,17 +351,6 @@
350351
"Define the Keras Model with the original inputs and the final engineered output."
351352
]
352353
},
353-
{
354-
"cell_type": "code",
355-
"execution_count": null,
356-
"metadata": {},
357-
"outputs": [],
358-
"source": [
359-
"def rmse(y_true, y_pred):\n",
360-
" squared_error = tf.keras.ops.square(y_pred[:, 0] - y_true)\n",
361-
" return tf.keras.ops.sqrt(tf.keras.ops.mean(squared_error))"
362-
]
363-
},
364354
{
365355
"cell_type": "code",
366356
"execution_count": null,
@@ -370,7 +360,12 @@
370360
"model = keras.Model(inputs=list(inputs.values()), outputs=output)\n",
371361
"\n",
372362
"# Compile model\n",
373-
"model.compile(optimizer=\"adam\", loss=\"mse\", metrics=[rmse], run_eagerly=True)"
363+
"model.compile(\n",
364+
" optimizer=\"adam\",\n",
365+
" loss=\"mse\",\n",
366+
" metrics=[RootMeanSquaredError()],\n",
367+
" run_eagerly=True,\n",
368+
")"
374369
]
375370
},
376371
{
@@ -442,7 +437,7 @@
442437
"metadata": {},
443438
"outputs": [],
444439
"source": [
445-
"RMSE_COLS = [\"rmse\", \"val_rmse\"]\n",
440+
"RMSE_COLS = [\"root_mean_squared_error\", \"val_root_mean_squared_error\"]\n",
446441
"\n",
447442
"pd.DataFrame(history.history)[RMSE_COLS].plot()"
448443
]
@@ -486,9 +481,9 @@
486481
"metadata": {
487482
"environment": {
488483
"kernel": "conda-base-py",
489-
"name": "workbench-notebooks.m131",
484+
"name": "workbench-notebooks.m132",
490485
"type": "gcloud",
491-
"uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m131"
486+
"uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m132"
492487
},
493488
"kernelspec": {
494489
"display_name": "Python 3 (ipykernel) (Local)",

notebooks/introduction_to_tensorflow/solutions/3_keras_sequential_api_vertex.ipynb

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"from keras import Input\n",
6969
"from keras.callbacks import TensorBoard\n",
7070
"from keras.layers import Dense\n",
71+
"from keras.metrics import RootMeanSquaredError\n",
7172
"from keras.models import Sequential\n",
7273
"from matplotlib import pyplot as plt\n",
7374
"\n",
@@ -188,9 +189,7 @@
188189
"\n",
189190
"* An optimizer. This could be the string identifier of an existing optimizer (such as `rmsprop` or `adagrad`), or an instance of the [Optimizer class](https://keras.io/api/optimizers/).\n",
190191
"* A loss function. This is the objective that the model will try to minimize. It can be the string identifier of an existing loss function from the [Losses class](https://keras.io/api/losses/) (such as `categorical_crossentropy` or `mse`), or it can be a custom objective function.\n",
191-
"* A list of metrics. For any machine learning problem you will want a set of metrics to evaluate your model. A metric could be the string identifier of an existing metric or a custom metric function.\n",
192-
"\n",
193-
"We will add an additional custom metric called `rmse` (Root Mean Squared Error). This custom metric is defined using `keras.ops` functions, making it compatible across different Keras backends (TensorFlow, JAX, PyTorch)."
192+
"* A list of metrics. For any machine learning problem you will want a set of metrics to evaluate your model. A metric could be the string identifier of an existing metric or a custom metric function."
194193
]
195194
},
196195
{
@@ -201,18 +200,8 @@
201200
},
202201
"outputs": [],
203202
"source": [
204-
"# Create a custom evalution metric\n",
205-
"\n",
206-
"\n",
207-
"@keras.saving.register_keras_serializable(package=\"rmse\")\n",
208-
"def rmse(y_true, y_pred):\n",
209-
" return keras.ops.sqrt(\n",
210-
" keras.ops.mean(keras.ops.square(y_pred[:, 0] - y_true))\n",
211-
" )\n",
212-
"\n",
213-
"\n",
214203
"# Compile the keras model\n",
215-
"model.compile(optimizer=\"adam\", loss=\"mse\", metrics=[rmse, \"mse\"])"
204+
"model.compile(optimizer=\"adam\", loss=\"mse\", metrics=[RootMeanSquaredError()])"
216205
]
217206
},
218207
{
@@ -334,7 +323,7 @@
334323
"metadata": {},
335324
"outputs": [],
336325
"source": [
337-
"RMSE_COLS = [\"rmse\", \"val_rmse\"]\n",
326+
"RMSE_COLS = [\"root_mean_squared_error\", \"val_root_mean_squared_error\"]\n",
338327
"\n",
339328
"pd.DataFrame(history.history)[RMSE_COLS].plot()"
340329
]

notebooks/introduction_to_tensorflow/solutions/4_keras_functional_api.ipynb

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
" HashedCrossing,\n",
6666
" Input,\n",
6767
")\n",
68+
"from keras.metrics import RootMeanSquaredError\n",
6869
"from matplotlib import pyplot as plt"
6970
]
7071
},
@@ -321,26 +322,6 @@
321322
"output = Dense(1, activation=None, name=\"output\")(concat)"
322323
]
323324
},
324-
{
325-
"cell_type": "markdown",
326-
"metadata": {},
327-
"source": [
328-
"Then, we'll define our custom RMSE evaluation metric and build our wide and deep model."
329-
]
330-
},
331-
{
332-
"cell_type": "code",
333-
"execution_count": null,
334-
"metadata": {
335-
"tags": []
336-
},
337-
"outputs": [],
338-
"source": [
339-
"def rmse(y_true, y_pred):\n",
340-
" squared_error = tf.keras.ops.square(y_pred[:, 0] - y_true)\n",
341-
" return tf.keras.ops.sqrt(tf.keras.ops.mean(squared_error))"
342-
]
343-
},
344325
{
345326
"cell_type": "markdown",
346327
"metadata": {},
@@ -360,7 +341,12 @@
360341
"source": [
361342
"model = Model(inputs=list(inputs.values()), outputs=output)\n",
362343
"\n",
363-
"model.compile(optimizer=\"adam\", loss=\"mse\", metrics=[rmse], run_eagerly=True)"
344+
"model.compile(\n",
345+
" optimizer=\"adam\",\n",
346+
" loss=\"mse\",\n",
347+
" metrics=[RootMeanSquaredError()],\n",
348+
" run_eagerly=True,\n",
349+
")"
364350
]
365351
},
366352
{
@@ -451,7 +437,7 @@
451437
},
452438
"outputs": [],
453439
"source": [
454-
"RMSE_COLS = [\"rmse\", \"val_rmse\"]\n",
440+
"RMSE_COLS = [\"root_mean_squared_error\", \"val_root_mean_squared_error\"]\n",
455441
"\n",
456442
"pd.DataFrame(history.history)[RMSE_COLS].plot()"
457443
]
@@ -462,21 +448,14 @@
462448
"source": [
463449
"Copyright 2025 Google Inc. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License."
464450
]
465-
},
466-
{
467-
"cell_type": "code",
468-
"execution_count": null,
469-
"metadata": {},
470-
"outputs": [],
471-
"source": []
472451
}
473452
],
474453
"metadata": {
475454
"environment": {
476455
"kernel": "conda-base-py",
477-
"name": "workbench-notebooks.m131",
456+
"name": "workbench-notebooks.m132",
478457
"type": "gcloud",
479-
"uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m131"
458+
"uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m132"
480459
},
481460
"kernelspec": {
482461
"display_name": "Python 3 (ipykernel) (Local)",

notebooks/introduction_to_tensorflow/solutions/5_keras_adv_feat_eng.ipynb

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
" Input,\n",
5353
" Lambda,\n",
5454
")\n",
55+
"from keras.metrics import RootMeanSquaredError\n",
5556
"from matplotlib import pyplot as plt"
5657
]
5758
},
@@ -356,17 +357,6 @@
356357
"Define the Keras Model with the original inputs and the final engineered output."
357358
]
358359
},
359-
{
360-
"cell_type": "code",
361-
"execution_count": null,
362-
"metadata": {},
363-
"outputs": [],
364-
"source": [
365-
"def rmse(y_true, y_pred):\n",
366-
" squared_error = tf.keras.ops.square(y_pred[:, 0] - y_true)\n",
367-
" return tf.keras.ops.sqrt(tf.keras.ops.mean(squared_error))"
368-
]
369-
},
370360
{
371361
"cell_type": "code",
372362
"execution_count": null,
@@ -376,7 +366,12 @@
376366
"model = keras.Model(inputs=list(inputs.values()), outputs=output)\n",
377367
"\n",
378368
"# Compile model\n",
379-
"model.compile(optimizer=\"adam\", loss=\"mse\", metrics=[rmse], run_eagerly=True)"
369+
"model.compile(\n",
370+
" optimizer=\"adam\",\n",
371+
" loss=\"mse\",\n",
372+
" metrics=[RootMeanSquaredError()],\n",
373+
" run_eagerly=True,\n",
374+
")"
380375
]
381376
},
382377
{
@@ -453,7 +448,7 @@
453448
"metadata": {},
454449
"outputs": [],
455450
"source": [
456-
"RMSE_COLS = [\"rmse\", \"val_rmse\"]\n",
451+
"RMSE_COLS = [\"root_mean_squared_error\", \"val_root_mean_squared_error\"]\n",
457452
"\n",
458453
"pd.DataFrame(history.history)[RMSE_COLS].plot()"
459454
]
@@ -498,9 +493,9 @@
498493
"metadata": {
499494
"environment": {
500495
"kernel": "conda-base-py",
501-
"name": "workbench-notebooks.m131",
496+
"name": "workbench-notebooks.m132",
502497
"type": "gcloud",
503-
"uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m131"
498+
"uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m132"
504499
},
505500
"kernelspec": {
506501
"display_name": "Python 3 (ipykernel) (Local)",

0 commit comments

Comments
 (0)