beginner · ~14 min
About Keras
TensorFlow's high-level API for building networks as a stack of layers — Sequential models, compile, fit, and reading a model.summary().
The Your First Neural Net module built a classifier by hand-assembling tf.layers.dense calls
inside tf.sequential(). That is Keras —
it's not a separate library bolted on top of TensorFlow, it's TensorFlow's own high-level API for
describing networks as a stack of layers instead of raw matrix math.
from tensorflow import keras
model = keras.Sequential([
keras.layers.Input(shape=(4,)),
keras.layers.Dense(8, activation="relu"),
keras.layers.Dense(1, activation="sigmoid"),
])
A Keras model is built from three ideas:
- Layers — each
Dense(units, activation)is one layer of neurons, exactly like the hidden layers from the previous module. Stack them withkeras.Sequential([...])when data flows straight through one layer after another. - Compile —
model.compile(optimizer, loss, metrics)picks how the model learns: which optimizer nudges the weights, which loss function measures wrongness, and which extra metrics (like accuracy) to track alongside it. - Fit —
model.fit(X, y, epochs=...)actually runs training: repeated forward passes, loss computation, and backpropagation, the same loop the playgrounds in this course run frame by frame, just hidden behind one call.
Beginner tip
The task you're solving decides the output layer and loss almost automatically: binary
classification wants 1 output unit with sigmoid and binary_crossentropy; multi-class
classification wants one unit per class with softmax and categorical_crossentropy;
regression wants 1 unit with no activation (linear) and mse. Change the task dropdown below
and watch the output layer and loss update to match.
Build a model below: set how many input features it takes, add or remove hidden Dense layers,
and pick a task. The summary table underneath isn't decorative — it's read straight off a real
model built with TensorFlow.js's tf.sequential(), the same numbers Python's model.summary()
would print for the equivalent Keras model.
🔍 Deep dive: Where do the parameter counts come from?
Every Dense(units_out) layer following an input (or previous layer) of size units_in learns
a weight matrix of shape (units_in, units_out) plus one bias per output unit — so its
parameter count is exactly units_in * units_out + units_out. A Dense(8) layer after a
4-feature input has 4*8 + 8 = 40 parameters; stack a Dense(8) after that and it's
8*8 + 8 = 72. This is also why adding units or layers grows a model's size multiplicatively,
not just additively — it's usually the biggest single lever on how many parameters (and how
much compute) a network needs.
Production note
Sequential only works when every layer has exactly one input and one output, feeding straight
into the next. Real architectures often need branches or multiple inputs — a second image
encoder, a skip connection, two outputs from one shared trunk — which is what Keras's
Functional API (keras.Model(inputs=..., outputs=...)) is for. Every Sequential model can
be rewritten in the Functional API, but not the reverse.
🔍 Deep dive: compile() vs fit(): why are they separate calls?
compile() only configures the model — it doesn't touch any data or weights, which is why you
can call it instantly even before you've loaded a dataset. fit() is the expensive part: it
runs the actual training loop, and it's the call that needs X and y in hand. Splitting them
means you can compile() once and then call fit() multiple times — for example to keep
training an already-partially-trained model with more data — without re-specifying the optimizer
and loss every time.
Playground
Hidden layers
| Layer (type) | Output Shape | Param # |
|---|---|---|
| dense_hidden_1 | (None, 8) | 40 |
| dense_hidden_2 | (None, 8) | 72 |
| dense_output | (None, 1) | 9 |
This table isn't a mockup — it's read straight off a real tf.sequential() model built in your browser with these exact layers.
model = keras.Sequential([
keras.layers.Input(shape=(4,)),
keras.layers.Dense(8, activation="relu"),
keras.layers.Dense(8, activation="relu"),
keras.layers.Dense(1, activation="sigmoid"),
])
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])