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, . Let the probability of toxicity at dose be . The entire range of possible values for can be broken up into the following intervals:
Let and be the a-priori probabilities that the rate of toxicity associated with dose belongs to the intervals UI, EI and OI. By definition, . The authors advocate .
Let be the number of patients that have been treated at dose , yielding toxicity events. The so-called local BOIN variant (i.e. that advocated by Liu and Yuan (2015)) defines:
where and are model parameters. The authors advocate and . As defaults, they recommend and .
Having observed toxicity rate at the current dose , the logical action depends on the interval in which resides. If , then the current dose is likely an underdose, so our desire should be to escalate dose to . In contrast, if , then the current dose is likely an overdose and we will want to de-escalate dose to for the next patient. If , then the current dose is deemed sufficiently close to and we will want to stay at dose-level .
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 prior, dose is deemed inadmissible for being excessively toxic if
for a certainty threshold, , with being suggested. If a dose is excluded by this rule, it should not be recommended by the model. Irrespective the values of and , the design will recommend to stay at dose 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 , described in Yuan and Liu (2018).
Opting to take the defaults, and , 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
BOIN, like some other designs, selects the final dose differently to
how it selects doses mid-trial. To achieve this in
escalation
, we need an extra selector that will kick-in
when the parent selector(s) have selected a non-NA dose but expressed
continue == FALSE
, i.e. signaled the trial ends now but
we are interested in a dose. If used, it will almost surely come
last in the selector chain:
model <- get_boin(num_doses = 5, target = 0.3) %>%
stop_at_n(n = 12) %>%
select_boin_mtd()
outcomes <- '1NNN 2NTN 2NNN 3NTT'
model %>% fit(outcomes) %>% recommended_dose()
#> [1] 2
In the above example, stop_at_n
stopped the trial
because the threshold sample size was met, and the underlying algorithm
identified that at least one dose was worthy of selection. At this
juncture, select_boin_mtd
took over and applied the method
described by the authors. Whilst the underlying selector(s) were busy
conducting the trial (continue == TRUE
),
select_boin_mtd
kept silent.
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
:
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.