Loading the lesson...
In the print dialog, choose "Save as PDF" as the destination.
Neural Networks - Lesson 6
A complete guide to the Sequential API, model building, training, and the Functional API
Sequential modelimport keras
from keras import layers, ops
model = keras.Sequential([
keras.Input(shape=(3, 1)),
layers.Dense(2, activation="relu", name="layer1"),
layers.Dense(3, activation="relu", name="layer2"),
layers.Dense(4, name="layer3"),
])add() / pop()model = keras.Sequential([
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
])
model.layers # list of 3 Dense layers
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.pop() # removes the last layername argument, useful for TensorBoard graphslayer = layers.Dense(3)
layer.weights # []
x = ops.ones((1, 4))
y = layer(x)
layer.weights # now shape (4,3) kernel and (3,) biasSequential model without Input(shape=...) is not "built": no weights until it sees datamodel(x) on real data triggers weight creation for every layersummary()keras.Input(shape=...) up front lets the model know its shape immediately: it always has weights and a defined output shapemodel = keras.Sequential()
model.add(keras.Input(shape=(4,)))
model.add(layers.Dense(2, activation="relu"))
model.summary()dense_10 (Dense) (None, 2) 10
Total params: 10model.summary()summary() often while building incrementallyDense layers: two ReLU hidden layers, one softmax output layer for 10 classesmodel = keras.Sequential()
model.add(keras.Input(shape=(784,)))
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dense(10, activation="softmax"))dense_11 (Dense) (None, 64) 50,240
dense_12 (Dense) (None, 64) 4,160
dense_13 (Dense) (None, 10) 650
Total params: 55,050 (215.04 KB)model.summary()784-length vectors, normalize to [0, 1](x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype("float32") / 255
x_test = x_test.reshape(10000, 784).astype("float32") / 255
# Reserve 10,000 samples for validation
x_val, y_val = x_train[-10000:], y_train[-10000:]
x_train, y_train = x_train[:-10000], y_train[:-10000]compile(): Loss, Optimizer, Metricscompile()| Label format | Loss | Metric |
|---|---|---|
| Integer labels | SparseCategoricalCrossentropy | SparseCategoricalAccuracy |
| One-hot labels | categorical_crossentropy | categorical_accuracy |
| Binary labels | binary_crossentropy | BinaryAccuracy |
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
# Shortcut with string identifiers:
# model.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy",
# metrics=["sparse_categorical_accuracy"])fit(): Training the Modelfit()epochs passes.validation_data reports validation loss and metrics at the end of each epochhistory = model.fit(
x_train, y_train,
batch_size=64,
epochs=2,
validation_data=(x_val, y_val),
)Epoch 1/2 - loss: 0.5733 - sparse_categorical_accuracy: 0.8410 - val_loss: 0.3036 - val_sparse_categorical_accuracy: 0.9113
Epoch 2/2 - loss: 0.1803 - sparse_categorical_accuracy: 0.9460 - val_loss: 0.1403 - val_sparse_categorical_accuracy: 0.9594| Parameter | Description |
|---|---|
x | Input data (NumPy array, Tensor, or Dataset) |
y | Target labels (same format as the output of the model) |
batch_size | Number of samples per gradient update (default 32) |
epochs | Number of passes through the entire dataset |
validation_data | Tuple (val_x, val_y) for evaluating the model at the end of each epoch |
shuffle | Whether to shuffle training data before each epoch (default True) |
verbose | 0 = silent, 1 = progress bar, 2 = one line per epoch |
history.history returns a dict of the recorded loss and metric values per epochevaluate() and predict()evaluate()predict()results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)
# test loss, test acc: [0.147, 0.956]
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape) # (3, 10)Self-Study
Sequential cannot: non-linear topology, shared layers, multiple inputs or outputs.Input
784-dim vector
Dense 64
relu
Dense 64
relu
Dense 10
output
inputs = keras.Input(shape=(784,)) # input node
dense = layers.Dense(64, activation="relu")
x = dense(inputs) # "layer call" = drawing an arrow
x = layers.Dense(64, activation="relu")(x)
outputs = layers.Dense(10)(x)
model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")inputs.shape is (None, 784), and inputs.dtype is 'float32', since the batch dimension is always omittedmodel.summary() works the same as it does for Sequential modelskeras.utils.plot_model() renders the graph visually, optionally with shape infomodel.summary()
# input_layer_4 (InputLayer) (None, 784) 0
# dense_14 (Dense) (None, 64) 50,240
# dense_15 (Dense) (None, 64) 4,160
# dense_16 (Dense) (None, 10) 650
keras.utils.plot_model(model, "my_first_model.png")
keras.utils.plot_model(model, "my_first_model_with_shape_info.png", show_shapes=True)Sequential fits linear layer stacks; the Functional API handles branching, sharing, and multi-input/output DAGsInput(shape=...) up front for a fully built modelmodel.summary() is the fastest way to sanity-check layer shapes and parameter counts while buildingcompile() sets the optimizer, loss, and metrics; match the loss to your label encoding (integer, one-hot, or binary)fit() trains with batching, epochs, and validation; evaluate() and predict() handle test-time inferenceoutput = layer(input), chained into a DAGMahmoud Abas|Keras Sequential model