Two classes, one mental model
Dataset is a single Arrow-backed table with named columns and rows. DatasetDict is just {split_name: Dataset} with convenience methods that broadcast operations to every split. Anything you can do on a single Dataset — map, filter, select, shuffle — you can do on a DatasetDict and it applies to all splits.
Features are the schema
ds.features is the schema dict. Each column has a Value, ClassLabel, Sequence, Audio, Image, or nested type. For classification, ClassLabel carries the label-int-to-name mapping — so ds.features['label'].int2str(1) yields 'positive'. Treat the features dict like a database schema: type-aware, queryable, and the source of truth for what the data means.