So far, we have mostly asked how to estimate parameters and quantify uncertainty about them.
Today we ask: is the model we fit any good?
In the parametric bootstrap, we replace the unknown truth \(P_{\theta_0}\) with the fitted model \(P_{\hat\theta}\):
\[ Y^{*(b)}\sim P_{\hat\theta}. \]
This tells us how our estimator would behave if the fitted model were generating the data, which gave us an approximation to the sampling distribution of the estimator.
Today, we’ll use the same sorts of simulated data to check whether the model “fits” the data.
Different from getting a precise parameter estimate
If the bootstrap distribution of \(\hat \theta\) is very narrow, then the interpretation is that the estimation procedure would give similar answers across repeated datasets from \(P_{\hat \theta}\). This doesn’t tell us much about whether the fitted model will reproduce aspects of the data we didn’t use for fitting.
Model “fit” can be quantified in different ways, but essentially the question is: for any characteristic of the data that we can observe, does the fitted model give values that are roughly in line with the observed values?
The two questions:
| Question | Procedure |
|---|---|
| How much would \(\hat\theta\) vary if the fitted model generated new datasets? | Parametric bootstrap |
| Can the fitted model generate datasets resembling the observed one? | Model checking |
Choose a feature of the data, \(T(Y)\), that we want to check.
Fit the model: \[ \hat\theta=h(Y_{\mathrm{obs}}). \]
Simulate replicated datasets: \[ Y^{\operatorname{rep},(b)}\sim P_{\hat\theta}. \]
Calculate the same feature in every dataset: \[ T_{\mathrm{obs}}=T(Y_{\mathrm{obs}}), \qquad T^{\operatorname{rep},(b)}=T(Y^{\operatorname{rep},(b)}). \]
Compare \(T_{\mathrm{obs}}\) with the distribution of the replicated values.
The replicated data should reproduce the original data-collection experiment:
Otherwise, differences between the observed and replicated data might come from changing the experiment rather than from a failure of the model.
A useful check should be:
There is no single universally best check. Different checks probe different possible failures.
Suppose we chose \(\hat\theta\) specifically to make
\[ s(Y_{\mathrm{obs}}) \approx \overline{s(Y_{\hat \theta})}. \]
Discovering afterward that these summaries agree is not much evidence for the model. We chose the parameters to make them agree.
For estimation, we want a summary whose distribution changes when \(\theta\) changes.
For model checking, we want a feature that represents a consequence of the model that could be wrong; it doesn’t have to change with the paramater we’re estimating.
Start with our very simple model from before:
\[ Y_i\stackrel{\mathrm{iid}}{\sim}N(\mu,\sigma^2). \]
We are measuring one quantity 500 times, and we fit \(\mu\) and \(\sigma\) to the measurements.
The story this time is that we’re observing some quality of a manufacturing process (maybe the location of a pre-drilled hole in a piece of Ikea furniture).
Most of the time, the hole is in the right place, but a small minority of the time the machine/worker messes up and you see a much wider spread in the measurements.
Almost all of the readings sit in a tight band. A handful are far away.
Suppose we fit the model somehow and obtain \(\hat\mu\) and \(\hat\sigma\).
It does not matter for what follows how we got them.
The fitted generative model is
\[ Y_i^{\operatorname{rep}}\stackrel{\mathrm{iid}}{\sim} N(\hat\mu,\hat\sigma^2), \]
and we can now simulate as many replicate datasets from it as we like.
Two things are wrong at once: the simulated bulk is too wide, and the simulated data never produce a reading anywhere near the far ones.
Sort both datasets. Plot the \(k\)-th smallest simulated value against the \(k\)-th smallest observed value, for every \(k\).
The bulk crosses the line steeply, and the extreme observed readings have no simulated counterpart.
The plots show the discrepancy.
In this case, it’s clear by eye that there’s a huge discrepancy between observed and simulated, but if we want to be a bit more formal (or let a computer automate it), a statistic lets us measure it.
How far from the middle is the most extreme reading?
\[ T(Y) = \max_i\left|Y_i-\operatorname{median}(Y)\right|. \]
For \(b=1,\ldots,B\):
Simulate a dataset of the original size: \[ Y^{\operatorname{rep},(b)} \sim N(\hat\mu,\hat\sigma^2). \]
Calculate \[ T^{\operatorname{rep},(b)} =T(Y^{\operatorname{rep},(b)}). \]
Then compare \(T(Y_{\mathrm{obs}})\) with the values the fitted model produces.
R
Everything specific to this check lives in
outlier_distance(). The surrounding simulate-and-compare
loop is the same in all three examples.
The observed value is far outside anything the fitted model produces.
The failure is not evidence that \(\mu\) or \(\sigma\) was estimated imprecisely.
Changing \(\mu\) moves the distribution and changing \(\sigma\) stretches it. Neither lets a Normal model produce a tight bulk and an occasional reading thirteen units away from the middle.
We could have obtained \((\hat\mu,\hat\sigma)\) using:
Once the fitted generative model is \(N(\hat\mu,\hat\sigma^2)\), the same simulation-based check is available.
Consider the ordinary linear regression model
\[ Y_i\mid x_i \sim N(\beta_0+\beta_1x_i,\sigma^2), \]
independently across observations.
This is a generative model for the responses, conditional on the predictor values.
After fitting \((\hat\beta_0,\hat\beta_1,\hat\sigma)\), we can simulate complete alternative response datasets from it.
The Puromycin data in R record reaction velocity at
several substrate concentrations.
We will use one treatment group and start with the linear model
\[ \operatorname{velocity}_i = \beta_0+ \beta_1\operatorname{concentration}_i+ \varepsilon_i, \qquad \varepsilon_i\stackrel{\mathrm{iid}}{\sim}N(0,\sigma^2). \]
Assume we have somehow obtained fitted values for \(\beta_0\), \(\beta_1\), \(\sigma\).
Velocity rises with concentration, steeply at first and then much less so.
The concentrations were part of the experimental design, so we hold them fixed.
For each replicate dataset, simulate
\[ Y_i^{\operatorname{rep},(b)} \sim N\left( \hat\beta_0+\hat\beta_1x_i, \hat\sigma^2 \right) \]
at exactly the observed values \(x_1,\ldots,x_n\).
We are asking what other response datasets could have occurred under the fitted line in this same experiment.
Each grey shape is the distribution of simulated velocities at that concentration.
Each concentration was run twice and averaged, and the red dots are the average of the observed data at each concentration.
Every concentration was run exactly twice, and so we can measure the amount of noise using the absolute difference between the two observations at a given concentration.
\[ T(Y)=\sum_{\text{concentrations }c} \left|Y_{c,1}-Y_{c,2}\right|. \]
We can compare observed and simulated on this statistic.
R
The violin plots and this statistic detect the same defect in different ways:
In this case, it’s a bit easier to check on the discrepancy in the noise.
The straight-line fit does not explain the data well.
We need some sort of a curve.
A scientifically motivated revision might use a Michaelis-Menten curve,
\[ E(Y\mid x) = \frac{V_{\max}x}{K+x}, \]
rather than simply adding terms until the residual plot looks better.
Several classical regression diagnostics are model checks:
Simulation makes the reference comparison explicit and extends the same logic to models where standard diagnostic theory is unavailable.
Return to the queue from Lecture 3.
In an \(M/M/1\) queue:
\[ A_i\stackrel{\mathrm{iid}}{\sim}\operatorname{Exponential}(\lambda), \]
\[ S_i\stackrel{\mathrm{iid}}{\sim}\operatorname{Exponential}(\mu), \]
where \(A_i\) is the time between arrivals, \(S_i\) is a service time, and there is one first-come, first-served server.
We observe one queue: the arrival times and the waiting times of a long run of customers.
Suppose we have fitted \(\lambda\) and \(\mu\) somehow, giving \(\hat\lambda\) and \(\hat\mu\). As before, how we fitted them does not matter here.
We can again use the fitted model to generate new queues and check whether the simulated queues look like the observed queues.
Simulate one complete queue from the fitted model (same number of customers, same fitted rates) and put its waiting times beside the observed ones.
For \(b=1,\ldots,B\):
R
simulate_queue() is the Lecture 3 simulator. Only the
choice of mean_wait() is new.
The fitted model expects a mean wait of about 0.74. The observed queue averages 1.57.
Mainly that the model is insufficient to explain waiting times
You would need to know a bit more about the model and play around with other possibilities to see how to fix it.
In this case, it could be fixed by modifying the service-time distribution (the data were actually generated under a model where arrivals were from an exponential distribution but service times were from a distribution with heavier tails).
If the observed feature is unusual under the fitted model, several explanations are possible:
A useful check narrows these possibilities, but rarely identifies a unique replacement model by itself.
If the observed feature looks ordinary relative to the simulations, then the model has reproduced that particular feature.
It does not follow that: