Build & train a Keras model — taxi fare (linear regression)
Source notebook
This walkthrough follows Google’s Machine Learning Crash Course lab:
Linear regression — taxi fare (Colab). The notebook uses Chicago taxi data: predict
FARE from trip features. We start with one input:
TRIP_MILES.
Code1
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
# Feature
# Machine Learning\Terms.html#Features (x)
X = np.array([1.0, 2.0, 3.0, 4.0], dtype=float)
# Label
# Machine Learning\Terms.html#Label (y)
y = np.array([2.0, 4.0, 6.0, 8.0], dtype=float)
# Machine Learning\Libraries\keras\Layers_and_APIs.html
model = keras.Sequential([
layers.Input(1), # 1 feature(x) (TRIP_MILES)
layers.Dense(1) # Layer with 1 neuron. 1 label(y)
])
# Machine Learning\Libraries\keras\Layers_and_APIs.html
# Configure the model for training
# learning_rate=0.01 is a hyperparameter for gradient descent Terms.html#Gradient Descent
model.compile(
optimizer=keras.optimizers.SGD(learning_rate=0.01), # Gradient Descent settings
loss='mean_squared_error' # Loss function
)
# Machine Learning\Libraries\keras\Layers_and_APIs.html
# Train the model
model.fit(X, y, epochs=500, verbose=0)
# Machine Learning\Libraries\keras\Layers_and_APIs.html
# Use the trained model to make predictions
print(model.predict(np.array([5.0])))
Code2
def create_model(
settings: ml_edu.experiment.ExperimentSettings,
metrics: list[keras.metrics.Metric],
) -> keras.Model:
inputs = {
name: keras.Input(shape=(1,), name=name)
for name in settings.input_features
}
concatenated_inputs = keras.layers.Concatenate()(list(inputs.values()))
outputs = keras.layers.Dense(units=1)(concatenated_inputs)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=settings.learning_rate),
loss="mean_squared_error",
metrics=metrics,
)
return model
def train_model(
experiment_name: str,
model: keras.Model,
dataset: pd.DataFrame,
label_name: str,
settings: ml_edu.experiment.ExperimentSettings,
) -> ml_edu.experiment.Experiment:
features = {name: dataset[name].values for name in settings.input_features}
label = dataset[label_name].values
history = model.fit(
x=features,
y=label,
batch_size=settings.batch_size,
epochs=settings.number_epochs,
)
return ml_edu.experiment.Experiment(
name=experiment_name,
settings=settings,
model=model,
epochs=history.epoch,
metrics_history=pd.DataFrame(history.history),
)
settings_1 = ml_edu.experiment.ExperimentSettings(
learning_rate=0.001,
number_epochs=20,
batch_size=50,
input_features=["TRIP_MILES"],
)
metrics = [keras.metrics.RootMeanSquaredError(name="rmse")]
model_1 = create_model(settings_1, metrics)
experiment_1 = train_model(
"one_feature", model_1, training_df, "FARE", settings_1
)
ml_edu.results.plot_experiment_metrics(experiment_1, ["rmse"])
ml_edu.results.plot_model_predictions(experiment_1, training_df, "FARE")
What this code does
This is linear regression using keras. Model tries to predict fares/label(y) using trip_miles/feature(x)
fare(y) ≈ w × trip_miles(x) + b
Keras implements that with a single Dense(units=1) layer
(no activation = linear). Training minimizes
mean squared error between predicted and actual fare.
What you need before this code runs
| Item | Role |
|---|---|
keras / tf.keras |
Build and train the neural network API |
pandas (pd) |
training_df — DataFrame with columns like
TRIP_MILES, FARE
|
ml_edu |
Google’s helper package in the Colab notebook —
ExperimentSettings, Experiment, plotting
utilities
|
training_df |
Preprocessed taxi dataset (created earlier in the notebook) |
ExperimentSettings |
Holds hyperparameters: learning rate, epochs, batch size, input feature names |
metrics |
List of Keras metrics to track during training (here: RMSE) |
In Colab, earlier cells install dependencies, load CSV data, and build
training_df. This page focuses on
model creation and training only.
create_model() — build the graph
Uses the Functional API (multiple named inputs → one output), not Sequential.
def create_model(
settings: ml_edu.experiment.ExperimentSettings,
metrics: list[keras.metrics.Metric],
) -> keras.Model:
# One Input layer per feature name in settings (here: only 'TRIP_MILES')
# shape=(1,) = one number per example; name= used for the dict key in fit()
inputs = {
name: keras.Input(shape=(1,), name=name)
for name in settings.input_features
}
# Merge all feature tensors into one vector (needed when you add more features)
concatenated_inputs = keras.layers.Concatenate()(list(inputs.values()))
# Single neuron, linear activation (default) → scalar prediction (fare)
outputs = keras.layers.Dense(units=1)(concatenated_inputs)
# Functional API: explicit inputs dict + output tensor
model = keras.Model(inputs=inputs, outputs=outputs)
# compile = choose optimizer, loss, and metrics for training
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=settings.learning_rate),
loss="mean_squared_error",
metrics=metrics,
)
return model
Line-by-line notes
-
keras.Input(shape=(1,), name=name)— defines a placeholder for one numeric feature per row. With one feature, input is shape(batch, 1). -
Concatenate()— joins inputs along the feature axis. With one feature it is a pass-through; with many (e.g.TRIP_MILES+TRIP_SECONDS) it stacks them into one vector before Dense. -
Dense(units=1)— one weight per input feature plus bias → linear regression output. -
RMSprop— adaptive learning-rate optimizer; updates weights to reduce loss each batch. -
loss="mean_squared_error"— average squared difference between predicted and true fare; what training minimizes. -
metrics— extra numbers logged each epoch (RMSE is in same units as fare — easier to read than MSE).
train_model() — fit on data
def train_model(
experiment_name: str,
model: keras.Model,
dataset: pd.DataFrame,
label_name: str,
settings: ml_edu.experiment.ExperimentSettings,
) -> ml_edu.experiment.Experiment:
"""Train the model by feeding it data."""
# Build dict of feature columns — keys must match Input layer names
features = {name: dataset[name].values for name in settings.input_features}
label = dataset[label_name].values
# fit = gradient descent loop for number_epochs passes over the data
history = model.fit(
x=features,
y=label,
batch_size=settings.batch_size,
epochs=settings.number_epochs,
)
return ml_edu.experiment.Experiment(
name=experiment_name,
settings=settings,
model=model,
epochs=history.epoch,
metrics_history=pd.DataFrame(history.history),
)
Line-by-line notes
-
featuresdict — for Functional API with named inputs,fit(x={...})keys must matchInput(name=...). -
label— target columnFARE(float dollars). -
batch_size=50— 50 rows per gradient update (noise vs speed tradeoff). -
epochs=20— full pass over the training set 20 times. -
history— per-epoch loss and RMSE; wrapped inExperimentfor Colab plotting helpers.
Run the experiment
settings_1 = ml_edu.experiment.ExperimentSettings(
learning_rate=0.001,
number_epochs=20,
batch_size=50,
input_features=["TRIP_MILES"],
)
metrics = [keras.metrics.RootMeanSquaredError(name="rmse")]
model_1 = create_model(settings_1, metrics)
experiment_1 = train_model(
"one_feature", model_1, training_df, "FARE", settings_1
)
# Colab helpers — plot loss/RMSE over epochs and predicted vs actual fare
ml_edu.results.plot_experiment_metrics(experiment_1, ["rmse"])
ml_edu.results.plot_model_predictions(experiment_1, training_df, "FARE")
Hyperparameters in this run
| Setting | Value | Meaning |
|---|---|---|
learning_rate |
0.001 | Step size for RMSprop weight updates |
number_epochs |
20 | How many times to iterate over full dataset |
batch_size |
50 | Examples per gradient step |
input_features |
['TRIP_MILES'] |
Single predictor — miles driven |
label |
FARE |
What we predict (dollars) |
rmse |
metric | Root mean squared error — typical error in fare units |
Concepts glossary (everything this code touches)
| Term | Meaning |
|---|---|
| Model | The computation graph: inputs → layers → output |
| Layer | Input, Concatenate, Dense — see Keras layers |
| compile | Attach optimizer, loss function, metrics before training |
| fit |
Train: feed features + labels, update weights for
epochs
|
| Optimizer (RMSprop) | Algorithm that adjusts weights using gradients of the loss |
| Loss (MSE) | What the optimizer minimizes; penalizes large prediction errors |
| Metric (RMSE) | Reported each epoch for monitoring; not always the same as loss |
| Functional API |
Model(inputs=..., outputs=...) — supports dict inputs
and branching
|
| Experiment |
Colab ml_edu wrapper storing settings, model, and
history for plots
|
Flow diagram
training_df['TRIP_MILES'] ──► Input(name='TRIP_MILES')
│
▼
Concatenate
│
▼
Dense(units=1) ──► predicted FARE
▲
training_df['FARE'] ────────────────┘ (compare via MSE, backprop updates weights)
settings: lr=0.001, batch=50, epochs=20
Try in Colab: Open notebook at create_model section →