The Bayesian Optimal Interval (BOIN) design was introduced by Liu and Yuan (2015). It is one of a series of dose-finding trial designs that works by partitioning the probability of toxicity into a set of intervals. These designs make dose-selection decisions that are determined by the interval in which the probability of toxicity for the current dose is believed to reside.
BOIN seeks a dose with probability of toxicity close to some pre-specified target level, \(p_T\). Let the probability of toxicity at dose \(i\) be \(p_i\). The entire range of possible values for \(p_i\) can be broken up into the following intervals:
Let \(\pi_{UI,i}, \pi_{EI,i}\) and \(\pi_{OI,i}\) be the a-priori probabilities that the rate of toxicity associated with dose \(i\) belongs to the intervals UI, EI and OI. By definition, \(\pi_{UI,i} + \pi_{EI,i} + \pi_{OI,i} = 1\). The authors advocate \(\pi_{UI,i} = \pi_{EI,i} = \pi_{OI,i} = \frac{1}{3}\).
Let \(n_i\) be the number of patients that have been treated at dose \(i\), yielding \(x_i\) toxicity events. The so-called local BOIN variant (i.e. that advocated by Liu and Yuan (2015)) defines:
\[ \lambda_{1i} = \frac{\log{\left( \frac{1 - \phi_1}{1 - p_T} \right)} + \frac{1}{n_i} \log{\left( \frac{\pi_{UI,i}}{\pi_{EI,i}} \right)} }{ \log{\left( \frac{p_T (1 - \phi_1)}{\phi_1 (1 - p_T)} \right)} }\]
\[ \lambda_{2i} = \frac{\log{\left( \frac{1 - p_T}{1 - \phi_2} \right)} + \frac{1}{n_i} \log{\left( \frac{\pi_{EI,i}}{\pi_{OI,i}} \right)} }{ \log{\left( \frac{ \phi_2(1 - p_T)}{p_T (1 - \phi_2)} \right)} }\]
where \(\phi_1\) and \(\phi_2\) are model parameters. The authors advocate \(\phi_1 \in \left[ 0.5pT, 0.7pT \right]\) and \(\phi_2 \in \left[ 1.3pT, 1.5pT \right]\). As defaults, they recommend \(\phi_1 = 0.6p_T\) and \(\phi_2 = 1.4p_T\).
Having observed toxicity rate \(\hat{p}_i = x_i / n_i\) at the current dose \(i\), the logical action depends on the interval in which \(\hat{p}_i\) resides. If \(\hat{p}_i < \lambda_{1i}\), then the current dose is likely an underdose, so our desire should be to escalate dose to \(i+1\). In contrast, if \(\hat{p}_i > \lambda_{2i}\), then the current dose is likely an overdose and we will want to de-escalate dose to \(i-1\) for the next patient. If \(\lambda_{1i} < \hat{p}_i < \lambda_{2i}\), then the current dose is deemed sufficiently close to \(p_T\) and we will want to stay at dose-level \(i\).
The authors advocate a stopping rule to protect against repeated administration of a dose that is evidently excessively toxic. The proposed rule is similar to that used in TPI and mTPI. Using a \(Beta(1, 1)\) prior, dose \(i\) is deemed inadmissible for being excessively toxic if
\[ Pr(p_{i} > p_{T} | x_i, n_i) > \xi,\]
for a certainty threshold, \(\xi\), with \(\xi = 0.95\) being suggested. If a dose is excluded by this rule, it should not be recommended by the model. Irrespective the values of \(\lambda_{1i}\) and \(\lambda_{1i}\), the design will recommend to stay at dose \(i\) rather than escalate to a dose previously identified as being inadmissible. Furthermore, the design will advocate stopping if the lowest dose is inferred to be inadmissible.
See Liu and Yuan (2015) and Yuan and Liu (2018) for full details.
escalation
To demonstrate the method, let us reproduce the dose selection sequence in a trial of five doses targeting \(p_T = 0.3\), described in Yuan and Liu (2018).
Opting to take the defaults, \(\phi_1 = 0.6 p_T = 0.18\) and \(\phi_2 = 1.4 p_T = 0.42\), we create an object to fit the model using:
library(escalation)
model <- get_boin(num_doses = 5, target = 0.3)
This is short-hand for
model <- get_boin(num_doses = 5, target = 0.3, p.saf = 0.18, p.tox = 0.42)
The text in the paper describes that outcomes ‘1NNN’ were observed in the first cohort:
leading to advice to escalate:
fit %>% recommended_dose()
#> [1] 2
The next cohort also saw three non-toxicity events, leading to advice:
fit <- model %>% fit('1NNN 2NNN')
fit %>% recommended_dose()
#> [1] 3
In the third cohort, two patients had toxicity, leading to advice:
fit <- model %>% fit('1NNN 2NNN 3NTT')
fit %>% recommended_dose()
#> [1] 2
The relatively low sample size at dose 3 means that the dose has not yet been rendered inadmissible:
fit %>% dose_admissible()
#> [1] TRUE TRUE TRUE TRUE TRUE
We can reproduce some of the advice above using dose-paths to
exhaustively calculate all possible future model advice. For example,
after observing 1NNN
in the first cohort, we can reproduce
the advice to escalate further after seeing 2NNN
and then
de-escalate after seeing 3NTT
using:
cohort_sizes <- c(3, 3)
paths <- model %>% get_dose_paths(cohort_sizes = cohort_sizes,
previous_outcomes = '1NNN', next_dose = 2)
graph_paths(paths)
Thus, we can trace the path 1NNN 2NNN 3NNT
, along with
every other possible path in two cohorts of three after having observed
1NNN
.
For more information on working with dose-paths, refer to the dose-paths vignette.
Liu and Yuan (2015) present in their
Table 4 some simulated operating characteristics. We can use the
simulate_trials
function to reproduce the findings.
Their example concerns a clinical trial of six doses that targets 25%
toxicity. We specify the model
object to reflect this. They
also elect to limit the trial to a sample size of \(n=36\):
Their scenario 1 investigates the true probability vector:
true_prob_tox <- c(0.25, 0.35, 0.5, 0.6, 0.7, 0.8)
For the sake of speed, we will run just fifty iterations:
num_sims <- 50
In real life, however, we would naturally run many thousands of iterations.
Running the simulation:
sims <- model %>%
simulate_trials(num_sims = num_sims, true_prob_tox = true_prob_tox)
we see that from this small sample size, the probability that each dose is recommended is similar to that reported:
prob_recommend(sims)
#> NoDose 1 2 3 4 5 6
#> 0.1 0.7 0.2 0.0 0.0 0.0 0.0
and so is the expected number of patients treated at each dose level:
For more information on running dose-finding simulations, refer to the simulation vignette.