Lecture 9 Consistency by Simulation

This is the R session for week 3. In the previous two sessions we were promised that we would watch an estimator converge to the truth, i.e. the consistency from lecture 2. Today we will see this convergence in two different ways: we will watch an estimate converge to the truth as observations are added, and we will plot the mean squared error against nn. On the way there we will extend the Monte Carlo skills we acquired in lecture 6 by introducing a loop which varies the sample size and a matrix to store the results. We will conclude by doing a computation which shows what lecture 8 means by a sufficient statistic. As before, appendix B contains a written reference for this topic. We will predict the outcome of the simulations before we start each one.

9.1 A Running Estimate

Consistency, definition 2.8, is a statement about the sequence of estimators θ^1,θ^2,…\hat{\theta}_{1},\hat{\theta}_{2},\dots as the sample size increases. The most direct way to visualise this sequence is to simulate a long sample and to re-compute the estimate after each observation. We will consider the exponential distribution with rate θ=2\theta=2, where the maximum likelihood estimator for the rate is θ^n=1/X¯n\hat{\theta}_{n}=1/\bar{X}_{n}, as found in example 5.2, and we will see that this estimator is consistent for θ\theta, by theorems 2.9 and A.17.

The command cumsum can be used to compute the running totals X1X_{1}, X1+X2X_{1}+X_{2} and so on in one step, and dividing the count nn by these totals gives all 20002000 running estimates at once. Before you look at the output, predict the five printed numbers. How far from 22 do you expect the estimate after one observation to be? How far after 20002000?

theta <- 2
N <- 2000
set.seed(2026)
x <- rexp(N, rate = theta)
n <- seq_len(N)
running <- n / cumsum(x)
running[c(1, 10, 100, 1000, 2000)]
## [1] 5.033385 1.446844 1.770152 1.921852 1.939830

The first estimate is 1/x11/x_{1}, which could be any number; in this example it is more than twice the truth. By n=1000n=1000 the estimate is within 0.10.1 of the truth. To get a better understanding of the path taken by the estimate, we plot the estimate against nn. The argument log = "x" for the plot command tells R to plot nn on a logarithmic axis, so that we can still see the early part of the path. Before we look at the plot, try to sketch the path you expect the estimate to take. Where is the curve most volatile? Once the curve enters the band θ±0.1\theta\pm 0.1, does it stay there?

plot(n, running, type = "l", log = "x", ylim = c(1, 3.5),
xlab = "n", ylab = "running estimate")
abline(h = theta, lty = 2)
abline(h = theta + c(-0.1, 0.1), lty = 3)
A jagged path plotted against n on a logarithmic
axis, ranging from 1 to 2000. The path starts above 3.5, shows
large fluctuations for small n and from n near 300 is close to
the dashed line at 2. The path crosses the dotted band at 1.9
and 2.1 repeatedly, before settling.
Figure 9.1: The running estimate 1/X¯n1/\bar{X}_{n} for the exponential rate θ=2\theta=2, plotted against nn on a logarithmic axis. The truth is given by the dashed line, the band θ±0.1\theta\pm 0.1 is given by the dotted lines.

Figure 9.1 shows the expected behaviour: the path is wild for small nn and ends inside the band. It does not converge in the sense of a sequence of numbers where, after some point, no term is outside the band; the path leaves and re-enters the band at random times. What decreases is the probability of being outside the band at a given nn, as given in definition 2.8.

9.2 The Mean Squared Error as a Function of the Sample Size

In lecture 6 we estimated the mean squared error of the two uniform estimators 2⁢X¯2\bar{X} and maxi⁡Xi\max_{i}X_{i} for n=10n=10. To see how each decreases with nn we repeat the study for several sample sizes, and this is the everyday shape of a simulation study in the practical report: an outer loop over a setting, an inner Monte Carlo run and a table of results. We first put both estimates into one function, so that both are computed from the same sample and returned as a vector of length two. The command replicate collects the 1000010000 repetitions into a matrix, a rectangular table of numbers with two rows, one per estimator, and the command rowMeans can be used to average each row.

est_both <- function(n, theta) {
sample <- runif(n, min = 0, max = theta)
c(2 * mean(sample), max(sample))
}

The outer loop runs over a vector ns of sample sizes, using seq_along(ns) to count through its positions. The command matrix(0, nrow = length(ns), ncol = 2) can be used to set aside a matrix for the results, mse[j, ] refers to the jj-th row of this matrix, and row and column names, set using rownames and colnames, can be used to make the matrix a readable table. As in lecture 6, the box below shows the complete script, with the lines of the loop kept together for clarity, but with the lines in a shuffled order. Before you read the script, you should try to work out the correct order of lines to make the script work.

signif(mse, 3)
for (j in seq_along(ns)) {
ests <- replicate(10000, est_both(ns[j], theta))
mse[j, ] <- rowMeans((ests - theta)^2)
}
mse <- matrix(0, nrow = length(ns), ncol = 2)
set.seed(2026)
rownames(mse) <- ns
theta <- 1
colnames(mse) <- c("2 * mean", "max")
ns <- c(5, 10, 20, 50, 100, 200, 500, 1000)

The rule for writing R scripts is still in force: all names must be defined before they are used, i.e. theta and ns must come first, the seed of the random number generator must be set before the loop starts, and the names and the display (using the signif function to round the numbers) require the matrix to be complete. Before you try the reconstructed script, try to predict the last row of the output. What will the two mean squared errors be for n=1000n=1000? For n=10n=10 the second mean squared error was approximately half of the first one. Will the ratio between the two mean squared errors stay close to two, or will it change?

theta <- 1
ns <- c(5, 10, 20, 50, 100, 200, 500, 1000)
mse <- matrix(0, nrow = length(ns), ncol = 2)
set.seed(2026)
for (j in seq_along(ns)) {
ests <- replicate(10000, est_both(ns[j], theta))
mse[j, ] <- rowMeans((ests - theta)^2)
}
rownames(mse) <- ns
colnames(mse) <- c("2 * mean", "max")
signif(mse, 3)
## 2 * mean max
## 5 0.065900 4.58e-02
## 10 0.033300 1.52e-02
## 20 0.016600 4.48e-03
## 50 0.006610 7.51e-04
## 100 0.003310 1.91e-04
## 200 0.001660 5.07e-05
## 500 0.000668 7.86e-06
## 1000 0.000331 1.99e-06

The row for n=10n=10 coincides with the two numbers from lecture 6 up to simulation error (the samples are not the same, since the loop has already sampled the n=5n=5 values first), and the values for each column decrease as nn increases, as expected from the sufficient condition for consistency given in corollary 2.11. The ratio between the mean squared errors is not close to two anymore: for n=1000n=1000 the mean squared error for the maximum is smaller by a factor of approximately 170170. The exact values from exercises 2.2 and 4.4 show that this is expected, since θ2/(3⁢n)\theta^{2}/(3n) decreases like 1/n1/n while 2⁢θ2/((n+1)⁢(n+2))2\theta^{2}/\bigl{(}(n+1)(n+2)\bigr{)} decreases like 1/n21/n^{2}. If we plot the data on log-log axes, i.e. if we use the argument log = "xy" for the plot, then a quantity proportional to n−kn^{-k} can be plotted as a straight line with slope −k-k. What will the two sets of points look like on a log-log plot? Will the two sets of points be parallel?

plot(ns, mse[, 1], log = "xy", pch = 16, xlab = "n", ylab = "MSE",
ylim = range(mse))
points(ns, mse[, 2], pch = 1)
lines(ns, theta^2 / (3 * ns), lty = 2)
lines(ns, 2 * theta^2 / ((ns + 1) * (ns + 2)), lty = 3)
legend("bottomleft", legend = c("2 * mean", "max"), pch = c(16, 1))
Eight filled and eight open circles on log-log
axes, for n ranging from 5 to 1000. The filled circles are
connected by a dashed straight line with a moderate negative
slope. The open circles are connected by a dotted line with a
slope that is twice as negative as the dashed line. The two lines
diverge as they go to infinity.
Figure 9.2: Simulated mean squared errors for 2⁢X¯2\bar{X} (filled circles) and maxi⁡Xi\max_{i}X_{i} (open circles), for the uniform parameter θ=1\theta=1, on logarithmic axes. The exact values θ2/(3⁢n)\theta^{2}/(3n) (dashed line) and 2⁢θ2/((n+1)⁢(n+2))2\theta^{2}/\bigl{(}(n+1)(n+2)\bigr{)} (dotted line) are also shown.

Both sets of points lie on straight lines: the slope is −1-1 for 2⁢X¯2\bar{X} and the slope is −2-2 for the maximum. The usual rate of decrease for a mean squared error is like 1/n1/n. All the estimators we will consider in the R strand of this module will have slope −1-1. The faster rate for the maximum is a consequence of the support of the uniform distribution moving with θ\theta. We will consider this example again in lecture 13.

We can also consider the full sampling distribution of the maximum at n=50n=50, since in lecture 8 we know the exact density: by proposition 8.9 and example 8.10, the maximum of nn observations from Uniform⁢(0,1)\text{Uniform}(0,1) has density f⁢(y)=n⁢yn−1f(y)=ny^{n-1} for 0≤y≤10\leq y\leq 1. To plot this density on top of a histogram, we need to plot the histogram using the density scale. This can be achieved by using the argument freq = FALSE of hist. Then the command curve can be used to plot any function of x on the horizontal axis, on top of the existing plot, if add = TRUE is used. Sketch the density 50⁢y4950y^{49} before the plot appears. Where is the density largest? What is the density at y=1y=1?

set.seed(2026)
mle50 <- replicate(10000, max(runif(50, min = 0, max = 1)))
hist(mle50, freq = FALSE, breaks = 40, col = "grey85", main = "",
xlab = "estimate")
curve(50 * x^49, add = TRUE, lwd = 2)

The curve closely follows the tops of the bars, and reaches the value 5050 at the boundary of the interval. The histogram is not a bell-shaped distribution as in figure 6.1: a sampling distribution can be concentrated around the truth, without being normal. In figure B.1 in appendix B you can see the same construction for a normal sample.

9.3 A Sufficient Statistic in R

To conclude these notes, we consider an example for use in lecture 8: for Poisson samples, the total number of counts ∑iXi\sum_{i}X_{i} is sufficient by example 8.4. The factorisation theorem 8.2 states that for data sets with the same total count, the likelihoods are proportional, differing by a constant shift on the log scale. We consider three data sets of size n=5n=5, where the first two have the same total count. We compute the log-likelihood for these data sets using the dpois function in R, with the log = TRUE option to get the log-likelihoods, and without any manual simplification of the results. The sapply command can be used to evaluate a function on every element of a vector; here we use it to evaluate the log-likelihoods on a grid of θ\theta-values. Will the difference between the first two curves be the same at every grid point? Will the same be true for the first and third curves? Do the three maxima coincide?

x1 <- c(2, 0, 3, 1, 4)
x2 <- c(2, 2, 2, 2, 2)
x3 <- c(0, 1, 0, 2, 1)
c(sum(x1), sum(x2), sum(x3))
loglik <- function(theta, data) {
sum(dpois(data, lambda = theta, log = TRUE))
}
grid <- seq(0.5, 4, by = 0.01)
ll1 <- sapply(grid, loglik, data = x1)
ll2 <- sapply(grid, loglik, data = x2)
ll3 <- sapply(grid, loglik, data = x3)
range(ll1 - ll2)
range(ll1 - ll3)
grid[c(which.max(ll1), which.max(ll2), which.max(ll3))]
## [1] 10 10 4
## [1] -2.197225 -2.197225
## [1] -9.128696 3.347953
## [1] 2.0 2.0 0.8

The difference between the first two curves is constant at every grid point, taking the value −2.197-2.197. This is equal to log⁡(32/288)\log(32/288), the logarithm of the ratio of the two factors 1/∏ixi!1/\prod_{i}x_{i}!, which do not depend on θ\theta. The difference to the third curve varies between −9.1-9.1 and 3.33.3. The first two maxima are both at x¯=2\bar{x}=2 while the third maximum is at 0.80.8. The likelihood does not allow us to infer anything about θ\theta beyond what is already known from the total count: for x1 and x2, the information about θ\theta is the same, once the total count is known.

9.4 A Task to Take Home

The following task is a review of the topics of this lecture, in the style of a practical report. Following the structure of section 9.2, for the exponential rate with θ=2\theta=2 and sample sizes given in ns, estimate the bias and mean squared error of the maximum likelihood estimator 1/X¯1/\bar{X} using 1000010000 repetitions each, in a table with named rows and columns. Create a plot of the mean squared error against nn, using logarithmic axes. From the plot, determine the slope. Compare the empirical bias to the exact value from exercise 2.3. Write three sentences about what the table and plot show about the consistency of the estimator 1/X¯1/\bar{X}.

Just like it is important to understand the syntax of a programming language, it is also important to be able to read the output of R commands. Before the next session, type in the commands from this session, and check that the output matches what is shown in the text.

Summary.
  • •
    ​

    Appendix B is the written reference for cumsum, the matrices returned by replicate and curve.

  • •
    ​

    The command cumsum can be used to compute all running estimates of a growing sample at once. Plotted against nn, the path keeps leaving and re-entering a band around the truth; what decreases is the probability of being outside it.

  • •
    ​

    A loop over a vector of sample sizes, with the results of each Monte Carlo run stored in one row of a matrix, gives the mean squared error as a function of nn. On log-log axes a mean squared error proportional to n−kn^{-k} is a straight line with slope −k-k: for the uniform parameter, 2⁢X¯2\bar{X} shows slope −1-1, the usual rate, and maxi⁡Xi\max_{i}X_{i} slope −2-2.

  • •
    ​

    With the argument freq = FALSE a histogram is drawn on the density scale, and curve(..., add = TRUE) can be used to superimpose a theoretical density on top of it.

  • •
    ​

    Two Poisson data sets with the same total have log-likelihoods which differ by a constant: the total is sufficient.