One call, the whole training loop
model.fit() is where everything you configured in compile() finally runs. Under one call hides the entire loop — batching, the forward pass, the loss, backprop, the optimizer step, metric accumulation, and the callback bus firing at every boundary. The arguments in the Code section are the knobs you'll reach for most: epochs is how many times you sweep the data, batch_size is how many samples feed each gradient step, and validation is wired in one of two ways.
The arguments that actually change outcomes
Use validation_split=0.2 to carve a validation set off the tail of your training data when you don't have a dedicated one; pass validation_data=(x_val, y_val) when you do — that's the honest choice, because validation_split takes the last slice without shuffling, so a sorted dataset gives you a garbage validation set. class_weight is the lever for imbalanced data: weight the rare class up so its mistakes count more, instead of letting the model win by always predicting the majority.
Whatever you pass, fit() hands back a History object. Its .history attribute is a dict of per-epoch lists — loss, val_loss, every metric and its val_ twin. That's your entire learning curve, and the next lesson's callbacks are what act on it automatically while training runs.