Skip to content

Calibration leaves the teenage age mix and education status without direct targets: 35% too many 16-year-olds, half the 18- and 19-year-olds #563

Open

Description

@MaxGhenis

Summary

The calibration fixes the 15-19 population only through age-band totals: national five-year bands by sex, regional and local ten-year bands. No target reads education or training status directly. Inside those bands the weights drift a long way from both the ONS and the FRS.

Measured on enhanced_frs_2024_25.h5 from uk-data 1.58.0, at its saved 2024 weights, against the ONS 2024-based principal projection for 2024:

Age ONS, 2024 FRS 2024-25, GROSS4 Enhanced FRS 1.58.0 Enhanced vs ONS
15 838k 809k 1,035k +23%
16 846k 946k 1,146k +35%
17 817k 764k 990k +21%
18 807k 687k 429k −47%
19 818k 691k 395k −52%
15 to 19 4,127k 3,897k 3,995k −3%

The share of 16-year-olds outside education roughly doubles between the FRS and the enhanced file, and it moves between releases although the education code has not changed:

Dataset 16-year-olds Not in full-time education Outside qualifying education or training (UC test) Kish n of that cell
FRS 2024-25, GROSS4 (frs_2024_25.h5 @1.58.0) 946k (416 records) 6.9% (23 records) 7.7% (25 records) 21.6
Enhanced 1.56.16 1,135k 16.0% (83 records)
Enhanced 1.57.4 1,086k 17.1% 17.9% (83 records)
Enhanced 1.58.0 1,146k 11.9% 13.1% (83 records) 3.7

Twenty of the 83 records are government trainees wrongly coded as outside training (#560). Without them the 1.58.0 figure is 12.7%; the FRS figure is 6.3%. Kish n counts rows, and copies of one household are separate rows, so it measures concentration, not a design-based standard error.

Where it comes from

  • Not the education mapping, as far as full-time status goes. current_education == "NOT_IN_EDUCATION" equals EDUCFT != 1 for every person aged 19 or under. This holds in the base file and in all 113,589 persons of the enhanced file, each traced back to its FRS record through the stacking offsets in utils/stack.py. This does not validate the finer education levels.

  • Not the copying itself. The SPI-synthetic copies, capital-gains halves and CGT donors are copies of the same records. The release build uses one OA clone (push.yaml:118). The copies do enter calibration with their own priors, but of the 150.6k, the original rows and their capital-gains halves carry 139.8k (72.6k on GROSS4), and the other copies about 10.7k.

  • The calibration reweights it. For each FRS household I summed the final weight of its original row and its capital-gains half, then divided by GROSS4. The split keeps their sum equal to GROSS4 (imputations/capital_gains.py:108-113).

    Households n Aggregate multiplier Median 90th percentile Max
    All FRS households 16,288 0.77 0.23 1.12 169
    With a 16-year-old in qualifying education or training 385 0.90 0.23 2.23 38.7
    With a 16-year-old outside it 25 1.93 0.24 2.39 14.9
    • The 25 households have an ordinary median, but two of them are above 5x.
    • They are the same two in 1.56.16, 1.57.4 and 1.58.0 (aggregate multiplier 1.95, 2.05 and 1.93). So the pattern persists across these releases; seed sensitivity has not been tested.
    • In 1.58.0 the top record holds 36.5% of the cell and the top five 84.5%.
  • No direct target limits it.

    • The national age targets are five-year bands by sex (targets/sources/ons_demographics.py:75-79). Regional and local ones are ten-year bands (targets/sources/local_age.py:28).
    • No target reads education or training status directly. UC and Child Benefit targets depend on it only through modelled eligibility.
    • The loss is target fit only (utils/calibrate.py:326-360). The survey weights set the starting point, after half the prior mass is reserved for the zero-weight synthetic rows (:110-145, :280-289). No term holds a household near its survey weight afterwards.
    • The only other element is a random dropout that replaces 5% of log weights with their mean each epoch (:387-395, used at :455, :499). Main does not seed it.
  • Weights are concentrated across the whole file.

    • Household Kish effective n is 10,217 on the FRS grossing weights (16,288 rows) and 1,396 on the enhanced weights (52,846 rows).
    • The top 1% of rows carry 43.8% of the weight.
    • It was 1,192 in 1.56.16, 1,181 in 1.57.4 and about 980 in cached 2023-24 enhanced files, so this is long-standing.

Why it matters

Options

These are complementary experiments, not alternatives, and none has been built.

  • Each needs builds.
  • A conclusion about stability needs repeated seeds.
  • Any new target needs a matched year and population definition.
  1. Finer national age targets for teenagers. Split the 15-19 bands into single years, or into 15, 16-17 and 18-19. The ONS projection is already downloaded by single year of age, so this is a change of aggregation, like the move from 15-year to five-year bands.
  2. A target for 16- to 19-year-olds in non-advanced education or approved training. Candidate sources:
    • HMRC's Child Benefit count of young persons aged 16 to 19. These are claims, so take-up and High Income Child Benefit Charge opt-outs need handling.
    • DfE and devolved participation statistics. These use academic age and different geographies and coverage.
  3. A term in the loss for distance from the survey weights, or a cap on the multiplier. This addresses the concentration generally and would likely move many aggregates. It needs a defined reference weight for the synthetic rows that start at zero.

Revised 11 October after an independent fact-check. Changes: the ONS comparison now uses the same year as the saved weights; the shares are separated by definition; the dropout and prior allocation are described; the options are framed as complementary.

Activity

  1. changed the title [-]Calibration leaves the teenage age mix and education status unconstrained: 36% too many 16-year-olds, half the 18- and 19-year-olds[/-] [+]Calibration leaves the teenage age mix and education status without direct targets: 35% too many 16-year-olds, half the 18- and 19-year-olds[/+] on Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions