LBA: The Linear Ballistic Accumulator (LBA)

Description Usage Arguments Details Value Note References Examples

Description

Density, distribution function, quantile function, and random generation for the LBA model with the following parameters: A (upper value of starting point), b (response threshold), t0 (non-decision time), and driftrate (v). All functions are available with different distributions underlying the drift rate: Normal (norm), Gamma (gamma), Frechet (frechet), and log normal (lnorm). The functions return their values conditional on the accumulator given in the response argument winning.

Usage

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
dLBA(rt, response, A, b, t0, ..., st0 = 0, distribution = c("norm",
  "gamma", "frechet", "lnorm"), args.dist = list(), silent = FALSE)

pLBA(rt, response, A, b, t0, ..., st0 = 0, distribution = c("norm",
  "gamma", "frechet", "lnorm"), args.dist = list(), silent = FALSE)

qLBA(p, response, A, b, t0, ..., st0 = 0, distribution = c("norm",
  "gamma", "frechet", "lnorm"), args.dist = list(), silent = FALSE,
  interval = c(0, 10), scale_p = FALSE, scale_max = Inf)

rLBA(n, A, b, t0, ..., st0 = 0, distribution = c("norm", "gamma",
  "frechet", "lnorm"), args.dist = list(), silent = FALSE)

Arguments

rt

vector of RTs. Or for convenience also a data.frame with columns rt and response (such as returned from rLBA or rdiffusion). See examples.

response

integer vector of winning accumulators/responses corresponding to the vector of RTs/p (i.e., used for specifying the response for a given RT/probability). Will be recycled if necessary. Cannot contain values larger than the number of accumulators. First response/accumulator must receive value 1, second 2, and so forth. For conmvenience, response is converted via as.numeric thereby allowing factors to be passed as well (such as returned from rdiffusion). Ignored if rt or p is a data.frame.

A

start point interval or evidence in accumulator before beginning of decision process. Start point varies from trial to trial in the interval [0, A] (uniform distribution). Average amount of evidence before evidence accumulation across trials is A/2.

b

response threshold. (b - A/2) is a measure of "response caution".

t0

non-decision time or response time constant (in seconds). Lower bound for the duration of all non-decisional processes (encoding and response execution).

...

two named drift rate parameters depending on distribution (e.g., mean_v and sd_v for distribution=="norm"). The parameters can either be given as a numeric vector or a list. If a numeric vector is passed each element of the vector corresponds to one accumulator. If a list is passed each list element corresponds to one accumulator allowing again trialwise driftrates. The shorter parameter will be recycled as necessary (and also the elements of the list to match the length of rt). See details.

st0

variability of non-decision time, such that t0 is uniformly distributed between t0 and t0 + st0. Default is 0. Can be trialwise, and will be recycled to length of rt.

distribution

character specifying the distribution of the drift rate. Possible values are c("norm", "gamma", "frechet", "lnorm"), default is "norm".

args.dist

list of optional further arguments to the distribution functions (i.e., posdrift or robust for distribution=="norm", see single-LBA).

silent

logical. Should the number of accumulators used be suppressed? Default is FALSE which prints the number of accumulators.

p

vector of probabilities. Or for convenience also a data.frame with columns p and response. See examples.

interval

a vector containing the end-points of the interval to be searched for the desired quantiles (i.e., RTs) in qLBA. Default is c(0, 10).

scale_p

logical. Should entered probabilities automatically be scaled by maximally predicted probability? Default is FALSE. Convenience argument for obtaining predicted quantiles. Can be slow as the maximally predicted probability is calculated individually for each p.

scale_max

numerical scalar. Value at which maximally predicted RT should be calculated if scale_p is TRUE.

n

desired number of observations (scalar integer).

Details

For convenience, all functions (with the exception of rdiffusion) allow that the first argument is a data.frame containing the information of the first and second argument in two columns (i.e., rt/p and response). Other columns will be ignored. This allows, for example, to pass the data.frame generated by rLBA directly to pLBA. See examples.

Parameters

The following arguments are allowed as ... drift rate parameters:

As described above, the accumulator parameters can either be given as a numeric vector or a list. If a numeric vector is passed each element of the vector corresponds to one accumulator. If a list is passed each list element corresponds to one accumulator allowing trialwise driftrates. The shorter parameter will be recycled as necessary (and also the elements of the list to match the length of rt).

The other LBA parameters (i.e., A, b, and t0, with the exception of st0) can either be a single numeric vector (which will be recycled to reach length(rt) or length(n) for trialwise parameters) or a list of such vectors in which each list element corresponds to the parameters for this accumulator (i.e., the list needs to be of the same length as there are accumulators). Each list will also be recycled to reach length(rt) for trialwise parameters per accumulator.

To make the difference between both paragraphs clear: Whereas for the accumulators both a single vector or a list corresponds to different accumulators, only the latter is true for the other parameters. For those (i.e., A, b, and t0) a single vector always corresponds to trialwise values and a list must be used for accumulator wise values.

st0 can only vary trialwise (via a vector). And it should be noted that st0 not equal to zero will considerably slow done everything.

Quantile Function

Due to the bivariate nature of the LBA, single accumulators only return defective CDFs that do not reach 1. Only the sum of all accumulators reaches 1. Therefore, qLBA can only return quantiles/RTs for any accumulator up to the maximal probability of that accumulator's CDF. This can be obtained by evaluating the CDF at Inf.

As a conveniece for the user, if scale_p = TRUE in the call to qLBA the desired probabilities are automatically scaled by the maximal probability for the corresponding response. Note that this can be slow as the maximal probability is calculated separately for each desired probability. See examples.

Also note that quantiles (i.e., predicted RTs) are obtained by numerically minimizing the absolute difference between desired probability and the value returned from pLBA using optimize. If the difference between the desired probability and probability corresponding to the returned quantile is above a certain threshold (currently 0.0001) no quantile is returned but NA. This can be either because the desired quantile is above the maximal probability for this accumulator or because the limits for the numerical integration are too small (default is c(0, 10)).

RNG

For random number generation at least one of the distribution parameters (i.e., mean_v, sd_v, shape_v, scale_v, rate_v, meanlog_v, and sdlog_v) should be of length > 1 to receive RTs from multiple responses. Shorter vectors are recycled as necessary.
Note that for random number generation from a normal distribution for the driftrate the number of returned samples may be less than the number of requested samples if posdrifts==FALSE.

Value

dLBA returns the density (PDF), pLBA returns the distribution function (CDF), qLBA returns the quantile/RT, rLBA return random response times and responses (in a data.frame).

The length of the result is determined by n for rLBA, equal to the length of rt for dLBA and pLBA, and equal to the length of p for qLBA.

The distribution parameters (as well as response) are recycled to the length of the result. In other words, the functions are completely vectorized for all parameters and even the response.

Note

These are the top-level functions intended for end-users. To obtain the density and cumulative density the race functions are called for each response time with the corresponding winning accumulator as first accumulator (see LBA-race).

References

Brown, S. D., & Heathcote, A. (2008). The simplest complete model of choice response time: Linear ballistic accumulation. Cognitive Psychology, 57(3), 153-178. doi:10.1016/j.cogpsych.2007.12.002

Donkin, C., Averell, L., Brown, S., & Heathcote, A. (2009). Getting more from accuracy and response time data: Methods for fitting the linear ballistic accumulator. Behavior Research Methods, 41(4), 1095-1110. doi:10.3758/BRM.41.4.1095

Heathcote, A., & Love, J. (2012). Linear deterministic accumulator models of simple choice. Frontiers in Psychology, 3, 292. doi:10.3389/fpsyg.2012.00292

Examples

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
## generate random LBA data:
rt1 <- rLBA(500, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))
head(rt1)
prop.table(table(rt1$response))

# original parameters have 'high' log-likelihood:
sum(log(dLBA(rt1$rt, rt1$response, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))))

# data can also be passed as data.frame (same is true for pLBA):
sum(log(dLBA(rt1, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))))

objective_fun <- function(par, rt, response, distribution = "norm") {
  # simple parameters
  spar <- par[!grepl("[12]$", names(par))]  
  
  # distribution parameters:
  dist_par_names <- unique(sub("[12]$", "", grep("[12]$" ,names(par), value = TRUE)))
  dist_par <- vector("list", length = length(dist_par_names))
  names(dist_par) <- dist_par_names
  for (i in dist_par_names) dist_par[[i]] <- as.list(unname(par[grep(i, names(par))]))
  dist_par$sd_v <- c(1, dist_par$sd_v) # fix first sd to 1

  # get summed log-likelihood:
  d <- do.call(dLBA, args = c(rt=list(rt), response=list(response), spar, dist_par, 
                               distribution=distribution, silent=TRUE))
  if (any(d < 0e-10)) return(1e6) 
  else return(-sum(log(d)))
}

# gives same value as manual calculation above:
objective_fun(c(A=0.5, b=1, t0=0.5, mean_v1=2.4, mean_v2=1.6, sd_v2=1.2), 
              rt=rt1$rt, response=rt1$response)

## Not run: 
# can we recover the parameters? 
# should be run several times with different random values of init_par
init_par <- runif(6)
init_par[2] <- sum(init_par[1:2]) # ensures b is larger than A
init_par[3] <- runif(1, 0, min(rt1$rt)) #ensures t0 is mot too large
names(init_par) <- c("A", "b", "t0", "mean_v1", "mean_v2",  "sd_v2")
nlminb(objective_fun, start = init_par, rt=rt1$rt, response=rt1$response, lower = 0)

## End(Not run)


# plot cdf (2 accumulators):
curve(pLBA(x, response = 1, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2)), 
     xlim = c(0, 2), ylim = c(0,1), 
     ylab = "cumulative probability", xlab = "response time",
     main = "Defective CDFs of LBA")
curve(pLBA(x, response = 2, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2)), 
     add=TRUE, lty = 2)
legend("topleft", legend=c("1", "2"), title="Response", lty=1:2)


# plot cdf (3 accumulators):
curve(pLBA(x, response = 1, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6, 1.0), sd_v=c(1,1.2, 2.0)), 
     xlim = c(0, 2), ylim = c(0,1), 
     ylab = "cumulative probability", xlab = "response time",
     main = "Defective CDFs of LBA")
curve(pLBA(x, response = 2, A=0.5, b=1, t0 = 0.5,  mean_v=c(2.4, 1.6, 1.0), sd_v=c(1,1.2, 2.0)), 
     add=TRUE, lty = 2)
curve(pLBA(x, response = 3, A=0.5, b=1, t0 = 0.5,  mean_v=c(2.4, 1.6, 1.0), sd_v=c(1,1.2, 2.0)), 
     add=TRUE, lty = 3)
legend("topleft", legend=c("1", "2", "3"), title="Response", lty=1:2)


## qLBA can only return values up to maximal predicted probability:
(max_p <- pLBA(Inf, response = 1, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2)))
# [1] 0.6604696

qLBA(0.66, response = 1, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))
# 2.559532

qLBA(0.67, response = 1, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))
# NA

# to get predicted quantiles, scale required quantiles by maximally predicted response rate:
qs <- c(.1, .3, .5, .7, .9)
qLBA(qs*max_p, response = 1, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))

# or set scale_p to TRUE which scales automatically by maximum p
# (but can be slow as it calculates max_p for each probability separately) 
qLBA(qs, response = 1, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2), scale_p=TRUE)

# qLBA also accepts a data.frame as first argument:
t <- data.frame(p = rep(c(0.05, 0.1, 0.66), 2), response = rep(1:2, each = 3))
#      p response
# 1 0.05        1
# 2 0.10        1
# 3 0.66        1
# 4 0.05        2
# 5 0.10        2
# 6 0.66        2
qLBA(t, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))


## LBA and diffusion can be used interchangeably:
rt1 <- rLBA(500, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))
rt2 <- rdiffusion(500, a=1, v=2, t0=0.5)

# data can also be passed as data.frame (same is true for pLBA):
sum(log(dLBA(rt1, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))))
sum(log(dLBA(rt2, A=0.5, b=1, t0 = 0.5, mean_v=c(2.4, 1.6), sd_v=c(1,1.2))))

sum(log(ddiffusion(rt1, a=1, v=2, t0=0.5)))
sum(log(ddiffusion(rt2, a=1, v=2, t0=0.5)))

### trial wise parameters work as expected (only since package version 0.9):
x1 <- dLBA(rt=c(1,1), response=c(1,2), A=1,b=list(c(1,3),c(2,4)),
           t0=0.1, mean_v=c(3,3), sd_v=c(1,1),distribution="norm")
x2a <- dLBA(rt=c(1), response=c(1), A=1,b=list(c(1),c(2)),
            t0=0.1,mean_v=c(3,3),sd_v=c(1,1),distribution="norm")
x2b <- dLBA(rt=c(1), response=c(2), A=1,b=list(c(3),c(4)),
            t0=0.1,mean_v=c(3,3),sd_v=c(1,1),distribution="norm")
all(x1 == c(x2a, x2b)) ## should be TRUE

rtdists documentation built on Jan. 7, 2022, 5:16 p.m.