ml-models / Core ML concepts / Supervised, unsupervised and self-supervised learning intro

Supervised, unsupervised and self-supervised learning

Every learning setup answers one question: where does the target come from? A person supplies it (supervised), nobody does and the model finds structure on its own (unsupervised), or the data supplies it by hiding part of itself (self-supervised). This page runs all three on tiny numbers you can check by hand, covers the in-between cases, and shows why self-supervision is what makes large-scale pretraining possible.

On this page
  1. Problem
  2. Intuition
  3. Mechanics
  4. Supervised learning
  5. Unsupervised learning
  6. Self-supervised learning
  7. In between
  8. The estimator API
  9. Worked example
  10. k-means with no labels
  11. Two labels and the unlabelled points
  12. Labels from the text itself
  13. Implementation
  14. Tradeoffs
  15. Check yourself
  16. Connections
  17. Read first
  18. Read next
  19. References

Problem

A model improves by being scored against something, so training needs a signal. The expensive part is rarely the model; it is the signal. Labelling a million photos with the objects in them takes people and money, while a trillion words of raw text cost almost nothing. Which setup you are in decides how much data you can use, what the model can learn, and what the loss measures (see loss functions).

Confusing the setups causes real mistakes: expecting clustering to recover the categories you had in mind, treating a pretraining loss as a quality score, or paying for labels a free objective could have supplied.

Intuition

Think of studying for an exam. Supervised: you have worked problems with answer keys. Unsupervised: you have a pile of problems with no answers and sort them into piles that look alike. Self-supervised: you cover a word in a textbook sentence and try to recall it; the book itself is the answer key, so you can quiz yourself for free, endlessly.

Where the target comes from in each setup Three columns. Supervised: inputs and human-provided labels both feed the loss. Unsupervised: inputs alone feed an objective such as cluster distance. Self-supervised: the input is split into a visible part and a hidden part, the visible part goes to the model and the hidden part is the target. supervised input x label y loss(model(x), y) y comes from people unsupervised input x objective(x, structure) no target; find structure self-supervised visible hidden loss(model(visible), hidden) y is part of x itself The labelled part is the costly one: supervised needs it, the others do not.

The only difference between the three is the source of the target.

Mechanics

Supervised learning

You have pairs (xi, yi) and fit a function f so that f(xi) ≈ yi by minimizing a loss. If y is a number it is regression (linear regression); if y is a category it is classification (logistic regression). The label defines the task: change it and the same inputs teach something else.

Unsupervised learning

You have only x. The goal is structure: groups (clustering), a compact description (dimensionality reduction), or the density p(x) itself. k-means is the standard example. It alternates two steps until nothing changes: assign each point to its nearest centre, then move each centre to the mean of its points. The quantity it lowers is inertia, the sum of squared distances from each point to its centre. Neither step can raise it, so it settles, though possibly in a poor spot that depends on the start. Nothing says the groups it finds match any human categories.

Self-supervised learning

You still only have x, but you manufacture a supervised problem from it by hiding a piece and predicting it. For text there are two standard choices:

  • Next-token prediction: the input is tokens up to position t and the target is token t+1. A sequence of n tokens yields n − 1 labelled examples. This is how a decoder-only model is pretrained, and what decoding later samples from.
  • Masked prediction: replace some tokens with a mask symbol and predict the originals from the surrounding words on both sides. The loss is a cross-entropy at the masked positions only.

The loss is the same cross-entropy as in supervised classification; only the labels' origin differs. For images, audio and video the hidden piece is a patch, a frame or the other view of the same item (the contrastive losses on the loss functions page).

In between

Semi-supervised learning has a few labels and many unlabelled points, and uses the unlabelled ones to learn the shape of the data, as in the worked example below. Weak supervision uses labels that are cheap but noisy: keywords, rules, links, or another model's guesses. Pretrain-then-fine-tune chains self-supervised pretraining on lots of raw data with supervised training on a small labelled set. Reinforcement learning is another case with its own signal, a reward, not covered here.

The estimator API

scikit-learn expresses the setups through one interface. Every estimator has fit(X, y=None); supervised ones need y, unsupervised ones ignore it. Then predict(X) for a supervised model, or labels_ and predict for a clusterer. Mixins add behaviour by role: ClassifierMixin.score is accuracy, RegressorMixin.score is R², and ClusterMixin adds fit_predict. PyTorch has no such interface; you write the loop yourself (see the training loop).

Nine points and two k-means clusters Nine points on a plane form a lower-left group of five and an upper-right group of four. The two final k-means centres are drawn as larger rings at (1.42, 1.40) and (4.30, 3.90). Two points are marked as the only labelled ones, the first point and the sixth. feature 1 labelled labelled dashed rings = final centres

Feature 2 is the vertical axis. Colour shows the cluster k-means found; the two circled points are the only ones with labels.

ComponentShape/ParamsMeaningSource
BaseEstimator get_params / set_params Base of every estimator; constructor arguments are the hyperparameters, learned values end in an underscore. base.py
ClassifierMixin.score X [n, d], y [n] Marks the estimator as a classifier; score defaults to accuracy. base.py
RegressorMixin.score X [n, d], y [n] Marks a regressor; score defaults to R². base.py
ClusterMixin.fit_predict X [n, d], no y Fits and returns a cluster id per point. base.py
KMeans.fit n_clusters, n_init; sets cluster_centers_, labels_, inertia_ Lloyd's alternation, repeated from several starts, keeping the lowest inertia. _kmeans.py
nn.CrossEntropyLoss logits [N, C], class indices [N] The loss for supervised classification, and for next-token and masked prediction alike. loss.py
nn.MSELoss prediction and target, same shape The usual supervised regression loss. loss.py

Worked example

k-means with no labels

Nine points, five near the lower left and four upper right (see the figure). Start the two centres badly, on the first two points (0.5, 1.0) and (1.0, 1.4). Each row is one pass: assign, record the inertia, then move the centres.

PassPoints in cluster 1InertiaNew centre 1New centre 2
1874.92(0.5, 1.0)(3.0, 2.7)
2519.23(1.2, 1.2)(3.9, 3.6)
347.43(1.4, 1.4)(4.3, 3.9)
445.89(1.4, 1.4)(4.3, 3.9)

Inertia falls every pass and the last pass leaves the centres unchanged, so it stops. The clusters match the two visible groups, but the algorithm only produced the numbers 0 and 1; nothing says which is "small". Starting from the first and last points instead, it settles on the same answer in 2 passes.

Two labels and the unlabelled points

Suppose only points 1 and 6 have labels (class 0 and class 1). Option one: give each point the label of its nearest labelled point. Option two: cluster all nine points as above, then give each cluster the label of the labelled point inside it. Against the true labels:

MethodUses unlabelled structureWrong pointsAccuracy
Nearest labelled pointno10.89
Cluster, then name the clusteryes01.00

Point 5, (2.4, 2.2), is nearer to the labelled class-1 point (3.6, 3.0) than to the class-0 point (0.5, 1.0), so the first method calls it class 1. But it sits in the lower-left cluster, which holds the class-0 label, so the second method gets it right. The unlabelled points told the method where the groups are. This only works if clusters line up with classes; when they do not, the extra data misleads.

Labels from the text itself

Take the 10-token text "the cat sat on the mat and the cat ran". With no human involved, it gives 9 next-token examples: input "the" → target "cat", input "cat" → target "sat", and so on. Masking position 2 gives the input "the [MASK] sat on the mat and the cat ran" with target "cat"; masking position 6 gives "the cat sat on the [MASK] and the cat ran" with target "mat".

A model that just counts which token follows which (a bigram table, fit on this same text) has a mean cross-entropy of 0.37 nats on these 9 examples. Guessing uniformly among the 7 distinct tokens costs ln 7 = 1.95. The gap is the structure learned. Measured on its own training text, though, this number is optimistic; a real evaluation uses held-out text.

Implementation

import torch
import torch.nn.functional as F
from sklearn.cluster import KMeans
from sklearn.linear_model import LogisticRegression

# supervised: the labels y come from people
clf = LogisticRegression().fit(X, y)
clf.score(X_test, y_test)                       # accuracy

# unsupervised: no y; the labels_ are arbitrary cluster ids
km = KMeans(n_clusters=2, n_init=10).fit(X)
km.labels_, km.inertia_

# self-supervised: the targets are the inputs shifted by one
def next_token_loss(model, tokens):             # tokens: [B, T] ints
    logits = model(tokens[:, :-1])              # [B, T-1, V]
    return F.cross_entropy(
        logits.reshape(-1, logits.size(-1)), tokens[:, 1:].reshape(-1)
    )

# masked prediction: loss only where a token was hidden
def masked_loss(model, tokens, mask):           # mask: [B, T] bool
    corrupted = tokens.masked_fill(mask, MASK_ID)
    logits = model(corrupted)
    targets = tokens.masked_fill(~mask, -100)   # ignore_index default
    return F.cross_entropy(logits.transpose(1, 2), targets)

Note that KMeans.fit(X) takes no y, whereas LogisticRegression.fit(X, y) requires it, which is the whole distinction in one line. The self-supervised loss is the same cross_entropy call as the supervised one; -100 is its default ignore_index, which is what lets unmasked positions contribute nothing.

Tradeoffs

  • Cost of labels. Supervised data is limited by annotation; self-supervised data is limited only by what you can collect. The price is that the objective is a proxy: predicting words is not the same as being helpful or correct.
  • Evaluation. Supervised models have an obvious test, accuracy on held-out labels. Unsupervised ones have no ground truth, so you judge by indirect measures (inertia, downstream use) that can be gamed or misleading.
  • Label quality. A supervised model learns the labellers' mistakes and biases. Weak labels scale but add noise the model can fit.
  • k-means pitfalls. You must choose k; it assumes roughly round, similar-sized groups; and different starts give different results, which is why n_init exists. Lower inertia with larger k is not evidence of better clusters, since k = n gives zero.
  • Mixing setups. Pretraining then fine-tuning gets the best of both but inherits the pretraining data's biases, and a fine-tuned model can forget what it learned in pretraining if tuned too hard.

Check yourself

Is next-token prediction supervised or unsupervised?

Mechanically it is supervised (inputs, targets, a cross-entropy loss), but the targets cost nothing because they are part of the input. That is why it is called self-supervised.

Why can k-means never raise its inertia from one pass to the next?

Reassigning each point to its nearest centre cannot increase total distance, and the mean is the point that minimizes squared distance to a set, so moving a centre to it cannot either.

In the worked example, how many next-token examples does a text of 100 tokens give?

99. Each position except the last is the input for the token after it.

Connections

Read first

Nothing: this page is a starting point.

Read next

References

  • Hastie, Tibshirani and Friedman. The Elements of Statistical Learning, 2nd ed., chapters 2 and 14. Springer, 2009.
  • Lloyd. Least Squares Quantization in PCM. IEEE Transactions on Information Theory, 1982 (circulated as a Bell Labs memo in 1957).
  • Devlin et al. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. 2018 (arXiv 1810.04805), for masked prediction.
  • Radford et al. Language Models are Unsupervised Multitask Learners (GPT-2). OpenAI, 2019, for next-token pretraining.
  • scikit-learn 1.9.1: BaseEstimator, KMeans.fit.
  • PyTorch v2.15.0: CrossEntropyLoss.