Designs for Response Surfaces

Where to sample along a response surface.

Kris Sankaran true
12-02-2021

Readings 11.4.1-11.4.2, Rmarkdown

Initial runs are using a factorial design, while later runs use a CCD.

Figure 1: Initial runs are using a factorial design, while later runs use a CCD.

We have been fitting surfaces to find some configuration of factors that optimizes a response. Sometimes we found the optimum just from one experiment, but more often, we ran a series of experiments, gradually refining our understanding of the response surface.

For any of these experiments, what designs should we use?

In theory, any of the designs we have discussed in this course could be used, but we will prefer those which give us an accurate estimate of the response surface (especially around stationary points) using as few samples as possible.

Designs for First-Order Models

In first-order models, we are interested in linear effects associated with each factor. Reasonable choices in this setting are,

Designs for Second-Order Models

For second-order models, we need to estimation nonlinear and interaction effects, which means we need more intensive sampling. The most common choice is the,

though some alternatives are,

In practice, you can use functions from the rsm package. This code produces a central composite design with three center points for both the factorial and axial runs. The package also has code for factorial, fractional factorial, and Box-Behnken designs.

library(rsm)

codings <- list(
  time_coded ~ (time - 35) / 5,
  temp_coded ~ (temp - 150) / 5
)
ccd_design <- ccd(~ time_coded + temp_coded, coding = codings, oneblock = TRUE)
head(ccd_design)
  run.order std.order     time     temp
1         1         3 35.00000 142.9289
2         2         1 30.00000 145.0000
3         3         6 35.00000 150.0000
4         4         1 27.92893 150.0000
5         5         8 35.00000 150.0000
6         6         2 42.07107 150.0000

Data are stored in coded form using these coding formulas ...
time_coded ~ (time - 35)/5
temp_coded ~ (temp - 150)/5
ggplot(decode.data(ccd_design)) +
  geom_point(
    aes(x = time, y = temp),
    position = position_jitter(w = 0.5, h = 0.5),
    size = 3
  ) +
  coord_fixed()
A generated CCD using the `rsm` package.

Figure 2: A generated CCD using the rsm package.

Using the same function, we can easily generate fractional or foldover designs, which are useful during the first-order phase of response surface modeling. For example, the code below generates a \(2^{4 - 1}\) design.

codings_x = list(
  x1 ~ (x1_ - 10) / 3,
  x2 ~ (x2_ - 20) / 6,
  x3 ~ (x3_ + 1) / 4
)
ffactorial <- cube(
  ~ x1 + x2 + x3, 
  n0 = 0, 
  coding = codings_x,
  generators = x4 ~ x1 * x2 * x3
  )

And if we want to foldover this fractional factorial, we can use foldover.

foldover(ffactorial, randomize = FALSE)
mfactorial <- ffactorial %>%
  head() %>%
  melt(id.vars = "std.order") %>%
  filter(variable != "run.order")
ggplot(mfactorial) +
  geom_tile(
    aes(x = variable, y = as.factor(std.order), fill = as.factor(value))
  ) +
  coord_fixed() +
  labs(x = "factor", y = "run", fill = "level") +
  scale_fill_brewer(palette = "Set2")
A $2^{4 - 1}$ fractional factorial design, made using the `rsm` package.

Figure 3: A \(2^{4 - 1}\) fractional factorial design, made using the rsm package.

mfactorial <- foldover(ffactorial, randomize=FALSE) %>%
  head() %>%
  melt(id.vars = "std.order") %>%
  filter(variable != "run.order")
ggplot(mfactorial) +
  geom_tile(
    aes(x = variable, y = as.factor(std.order), fill = as.factor(value))
  ) +
  coord_fixed() +
  labs(x = "factor", y = "run", fill = "level") +
  scale_fill_brewer(palette = "Set2")
The foldover of the previous fractional factorial design.

Figure 4: The foldover of the previous fractional factorial design.

Variance of Response Surfaces

At any point \(x\), it’s possible to estimate the variance of the surface at that point, denoted \(V\left(\hat{y}\left(x\right)\right)\).

If there are only 2 factors, this surface can be directly visualized.

ccd_design <- ccd(~ time_coded + temp_coded, coding = codings, oneblock = TRUE)
par(mfrow = c(1, 2))
varfcn(ccd_design, ~ SO(time_coded, temp_coded))
varfcn(ccd_design, ~ SO(time_coded, temp_coded), contour = TRUE, asp = 1)
The scaled prediction variance functions for a rotatable CCD.

Figure 5: The scaled prediction variance functions for a rotatable CCD.

ccd_design <- ccd(~ time_coded + temp_coded, coding = codings, alpha=2, oneblock = TRUE)
par(mfrow = c(1, 2))
varfcn(ccd_design, ~ SO(time_coded, temp_coded))
varfcn(ccd_design, ~ SO(time_coded, temp_coded), contour = TRUE, asp = 1)
The analogous functions for a nonrotatable CCD. Note that the axis and diagonal variance curves don't overlap.

Figure 6: The analogous functions for a nonrotatable CCD. Note that the axis and diagonal variance curves don’t overlap.