Skip to content

Commit 8a99668

Browse files
authored
Migrate hparams plugin to Keras 3 and remove Keras 2 from requirements.txt (#6759)
We must still install keras 2 as part of CI in order to successfully run graph plugin tests.
1 parent 3049d0c commit 8a99668

File tree

4 files changed

+32
-35
lines changed

4 files changed

+32
-35
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,8 @@ jobs:
7878
run: |
7979
python -m pip install -U pip
8080
pip install "${TENSORFLOW_VERSION}"
81+
pip install "${TF_KERAS_VERSION}"
8182
if: matrix.tf_version_id != 'notf'
82-
# Replace the `tf-keras` with `tf-keras-nightly` in the requirements.txt
83-
# to avoid incompatibilities when using alongside `tf-nightly`.
84-
# TODO: Remove this after migrating to Keras 3.
85-
- name: 'Make user to use tf-keras-nightly with tf-nightly'
86-
run: |
87-
sed -i "s/^tf-keras.*/${TF_KERAS_VERSION}/g" ./tensorboard/pip_package/requirements.txt
8883
- name: 'Install Python dependencies'
8984
run: |
9085
python -m pip install -U pip

tensorboard/pip_package/requirements.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,4 @@ setuptools >= 41.0.0 # Note: provides pkg_resources as well as setuptools
3333
# requirement, and likely this will not disrupt existing users of the package.
3434
six > 1.9
3535
tensorboard-data-server >= 0.7.0, < 0.8.0
36-
# Stay on Keras 2 for now: https://github.com/keras-team/keras/issues/18467.
37-
# TODO: Remove this after migrating to Keras 3.
38-
tf-keras >= 2.15.0
3936
werkzeug >= 1.0.1

tensorboard/plugins/hparams/_keras.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,8 @@
2424
from tensorboard.plugins.hparams import summary
2525
from tensorboard.plugins.hparams import summary_v2
2626

27-
# Stay on Keras 2 for now: https://github.com/keras-team/keras/issues/18467.
28-
version_fn = getattr(tf.keras, "version", None)
29-
if version_fn and version_fn().startswith("3."):
30-
import tf_keras as keras # Keras 2
31-
else:
32-
keras = tf.keras # Keras 2
3327

34-
35-
class Callback(keras.callbacks.Callback):
28+
class Callback(tf.keras.callbacks.Callback):
3629
"""Callback for logging hyperparameters to TensorBoard.
3730
3831
NOTE: This callback only works in TensorFlow eager mode.
@@ -41,7 +34,7 @@ class Callback(keras.callbacks.Callback):
4134
def __init__(self, writer, hparams, trial_id=None):
4235
"""Create a callback for logging hyperparameters to TensorBoard.
4336
44-
As with the standard `keras.callbacks.TensorBoard` class, each
37+
As with the standard `tf.keras.callbacks.TensorBoard` class, each
4538
callback object is valid for only one call to `model.fit`.
4639
4740
Args:

tensorboard/plugins/hparams/_keras_test.py

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,14 @@
1818
from unittest import mock
1919

2020
from google.protobuf import text_format
21+
import numpy as np
2122
import tensorflow as tf
2223

2324
from tensorboard.plugins.hparams import _keras
2425
from tensorboard.plugins.hparams import metadata
2526
from tensorboard.plugins.hparams import plugin_data_pb2
2627
from tensorboard.plugins.hparams import summary_v2 as hp
2728

28-
# Stay on Keras 2 for now: https://github.com/keras-team/keras/issues/18467.
29-
version_fn = getattr(tf.keras, "version", None)
30-
if version_fn and version_fn().startswith("3."):
31-
import tf_keras as keras # Keras 2
32-
else:
33-
keras = tf.keras # Keras 2
34-
35-
tf.compat.v1.enable_eager_execution()
36-
3729

3830
class CallbackTest(tf.test.TestCase):
3931
def setUp(self):
@@ -46,12 +38,12 @@ def _initialize_model(self, writer):
4638
"optimizer": "adam",
4739
HP_DENSE_NEURONS: 8,
4840
}
49-
self.model = keras.models.Sequential(
41+
self.model = tf.keras.models.Sequential(
5042
[
51-
keras.layers.Dense(
43+
tf.keras.layers.Dense(
5244
self.hparams[HP_DENSE_NEURONS], input_shape=(1,)
5345
),
54-
keras.layers.Dense(1, activation="sigmoid"),
46+
tf.keras.layers.Dense(1, activation="sigmoid"),
5547
]
5648
)
5749
self.model.compile(loss="mse", optimizer=self.hparams["optimizer"])
@@ -69,7 +61,11 @@ def mock_time():
6961
initial_time = mock_time.time
7062
with mock.patch("time.time", mock_time):
7163
self._initialize_model(writer=self.logdir)
72-
self.model.fit(x=[(1,)], y=[(2,)], callbacks=[self.callback])
64+
self.model.fit(
65+
x=tf.constant([(1,)]),
66+
y=tf.constant([(2,)]),
67+
callbacks=[self.callback],
68+
)
7369
final_time = mock_time.time
7470

7571
files = os.listdir(self.logdir)
@@ -142,7 +138,11 @@ def test_explicit_writer(self):
142138
filename_suffix=".magic",
143139
)
144140
self._initialize_model(writer=writer)
145-
self.model.fit(x=[(1,)], y=[(2,)], callbacks=[self.callback])
141+
self.model.fit(
142+
x=tf.constant([(1,)]),
143+
y=tf.constant([(2,)]),
144+
callbacks=[self.callback],
145+
)
146146

147147
files = os.listdir(self.logdir)
148148
self.assertEqual(len(files), 1, files)
@@ -158,15 +158,27 @@ def test_non_eager_failure(self):
158158
with self.assertRaisesRegex(
159159
RuntimeError, "only supported in TensorFlow eager mode"
160160
):
161-
self.model.fit(x=[(1,)], y=[(2,)], callbacks=[self.callback])
161+
self.model.fit(
162+
x=np.ones((10, 10)),
163+
y=np.ones((10, 10)),
164+
callbacks=[self.callback],
165+
)
162166

163167
def test_reuse_failure(self):
164168
self._initialize_model(writer=self.logdir)
165-
self.model.fit(x=[(1,)], y=[(2,)], callbacks=[self.callback])
169+
self.model.fit(
170+
x=tf.constant([(1,)]),
171+
y=tf.constant([(2,)]),
172+
callbacks=[self.callback],
173+
)
166174
with self.assertRaisesRegex(
167175
RuntimeError, "cannot be reused across training sessions"
168176
):
169-
self.model.fit(x=[(1,)], y=[(2,)], callbacks=[self.callback])
177+
self.model.fit(
178+
x=tf.constant([(1,)]),
179+
y=tf.constant([(2,)]),
180+
callbacks=[self.callback],
181+
)
170182

171183
def test_invalid_writer(self):
172184
with self.assertRaisesRegex(

0 commit comments

Comments
 (0)