Skip to content

Commit

Permalink
Provide a setter for layers in Sequential and Functional.
Browse files Browse the repository at this point in the history
The `Model` class has a setter for `layers` to provide a more descriptive message on why this property cannot be changed. But it only applies to sub-class models as classes that override `layers` don't inherit it.

This adds a similar message for functional and sequential models.
  • Loading branch information
hertschuh committed Sep 20, 2024
1 parent 9dbbc72 commit 15a80ca
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 0 deletions.
7 changes: 7 additions & 0 deletions keras/src/models/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ def layers(self):
layers.append(operation)
return layers

@layers.setter
def layers(self, _):
raise AttributeError(
"`Model.layers` attribute is reserved and should not be used. "
"Please use another name."
)

def call(self, inputs, training=None, mask=None):
# Add support for training, masking
inputs = self._standardize_inputs(inputs)
Expand Down
9 changes: 9 additions & 0 deletions keras/src/models/functional_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,3 +530,12 @@ def test_for_functional_in_sequential(self):
def test_add_loss(self):
# TODO
pass

def test_layers_setter(self):
inputs = Input(shape=(3,), batch_size=2, name="input")
outputs = layers.Dense(5)(inputs)
model = Functional(inputs, outputs)
with self.assertRaisesRegex(
AttributeError, "`Model.layers` attribute is reserved"
):
model.layers = [layers.Dense(4)]
8 changes: 8 additions & 0 deletions keras/src/models/model_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -876,3 +876,11 @@ def test_get_state_tree_with_duplicate_path(self):
"The following variable path is found twice in the model",
):
model.get_state_tree()


def test_layers_setter(self):
model = Model()
with self.assertRaisesRegex(
AttributeError, "`Model.layers` attribute is reserved"
):
model.layers = [layers.Dense(4)]
7 changes: 7 additions & 0 deletions keras/src/models/sequential.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ def layers(self):
return layers[1:]
return layers[:]

@layers.setter
def layers(self, _):
raise AttributeError(
"`Sequential.layers` attribute is reserved and should not be used. "
"Use `add()` and `pop()` to change the layers in this model."
)

def compute_output_spec(self, inputs, training=None, mask=None):
if self._functional:
return self._functional.compute_output_spec(
Expand Down
7 changes: 7 additions & 0 deletions keras/src/models/sequential_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,3 +378,10 @@ def test_hasattr(self):
self.assertTrue(hasattr(model, "output_shape"))
self.assertTrue(hasattr(model, "inputs"))
self.assertTrue(hasattr(model, "outputs"))

def test_layers_setter(self):
model = Sequential()
with self.assertRaisesRegex(
AttributeError, "Use `add\(\)` and `pop\(\)`"
):
model.layers = [layers.Dense(4)]

0 comments on commit 15a80ca

Please sign in to comment.