

The previous page defined the measures; this one is about which patients they are measured in. A model measured in the patients it was fitted to looks better than it is (apparent performance, see overfitting). The designs differ in how they find patients the model has not seen. In the figure, each square is a patient of a small development data set of 12.


Cross-validation and the bootstrap are internal validation: they estimate performance in new patients from the same population. Only external validation tests whether the model works elsewhere.
flowchart LR A["Development data<br/>(n patients)"] --> B["Fit the model<br/>apparent performance"] A --> C["Draw a bootstrap sample<br/>(n patients, with replacement)"] C --> D["Repeat the whole procedure<br/>(selection, tuning, fit)"] D --> E["Performance in the<br/>bootstrap sample"] D --> F["Performance in the<br/>original data"] E --> G["Optimism = E − F"] F --> G G --> H["Average over 200 samples<br/>corrected = apparent − optimism"] B --> H
The key is the box Repeat the whole procedure: everything that was done to build the model — variable selection, choice of interactions, the elastic net’s λ — is repeated in every bootstrap sample, so its optimism is included. clinpred does this automatically: the fitting procedure is a single function, used for the final model and for every resampled fit (and for every fold of cross-validation).
Two by-products come free:
The bootstrap is preferred for small and moderate data sets (it uses all patients to fit); repeated cross-validation behaves similarly when data are large. clinpred stratifies the folds by the outcome.
clinpred applies the development model, unchanged (the same coefficients and, for Cox models, the same baseline hazard), to
Whether performance holds or drops must be interpreted against the case-mix of the new population (Debray et al. 2015). clinpred’s case-mix table compares the predictors, the spread of the linear predictor (a wider spread raises discrimination by itself) and a membership c-statistic: how well a model can tell development from validation patients. Near 0.5 the validation tests reproducibility (same kind of patients); high values test transportability to a different population. For Cox models see also Royston and Altman (2013).
A model rarely fails completely in a new population. More often it still ranks patients well but its risks are off: the new population has a different baseline risk (another country, period or referral pattern), or the predictors carry less weight there. The model does not need to be rebuilt: it can be updated with a few parameters estimated in the new data (Steyerberg 2019; Houwelingen 2000). Writing LP for the original model’s linear predictor (its log-odds), the methods are:
| Method | Updated model | Re-estimated | Parameters |
|---|---|---|---|
| Original model | logit(risk) = LP | nothing | 0 |
| Recalibration in the large | logit(risk) = a + LP | the intercept: the overall risk level | 1 |
| Recalibration | logit(risk) = a + b × LP | intercept and slope: level and spread | 2 |
| Model revision | every coefficient refitted | all | all |
For Cox models, a re-estimates the baseline risk at the horizon instead of an intercept.
The figure shows a simulated example: a model developed in one population, validated in another with a higher event rate and weaker effects.


Updating changes the risks, not the ranking: the AUC is the same for the first three methods, because adding a constant or multiplying by a positive number does not reorder patients. Only revision, which re-weights the predictors, can change it.
More parameters always fit the new data better, so the simplest method that is good enough should be chosen. For logistic and linear models clinpred uses the closed testing procedure of Vergouwe et al. (2017). Each method is compared with revision (the most flexible) by a likelihood ratio test (F test for linear models), starting from the simplest:
flowchart TD
A{"Original model<br/>significantly worse than revision?"} -- no --> O["Keep the original model"]
A -- yes --> B{"Recalibration in the large<br/>significantly worse than revision?"}
B -- no --> C["Recalibration in the large"]
B -- yes --> D{"Recalibration<br/>significantly worse than revision?"}
D -- no --> R["Recalibration"]
D -- yes --> V["Model revision"]
The procedure protects against updating on noise. The price is power: when revision has many parameters, a one-parameter shift is diluted among them and may not be detected (the external validation example shows a case). Look at the O/E ratio and its confidence interval as well, and decide with clinical judgement.
For Cox models the partial likelihood does not involve the baseline hazard, so a change of the baseline risk cannot be tested against revision the same way. clinpred uses sequential tests from the most complex method down: revision against recalibration (partial likelihood ratio), slope = 1 (partial likelihood ratio), and observed/expected risk at the horizon = 1 (a Wald test of log O/E); the most complex method whose test is significant is chosen.
Updated models are evaluated in the same data that updated them, so their performance is optimistic — most of all for revision. An updated model should itself be validated before use.