BKT fits Bayesian Knowledge Tracing models to student
response sequences. It supports model fitting, parameter inspection,
prediction, evaluation, cross-validation, parameter fixing, and several
BKT variants.
The package is based on the ideas implemented by pyBKT.
Install the development version from GitHub:
# install.packages("remotes")
remotes::install_github("Feng-Ji-Lab/bkt")Then load the package:
library(BKT)The package includes simulation_data_50, a small
simulated dataset containing 50 students and 494 response records:
data("simulation_data_50", package = "BKT")
head(simulation_data_50)The required columns are:
order_id: response order within a student sequencecorrect: 1 for a correct response and
0 for an incorrect responsestudent_id: student identifierskill_name: skill identifierBKT recognizes student_id automatically, so
no column mapping is needed for the included simulation data.
Create and fit a model directly from the included data frame:
library(BKT)
data("simulation_data_50", package = "BKT")
model <- bkt(seed = 42, num_fits = 1, parallel = FALSE)
fitted_model <- fit(model, data = simulation_data_50)
params(fitted_model)The returned parameter table contains the estimated learning,
guessing, slipping, and prior probabilities for the
mathematic skill.
Use a fitted model to generate response and knowledge-state probabilities:
predictions <- predict_bkt(fitted_model, data = simulation_data_50)
head(predictions)The result contains the original data plus:
correct_predictions: predicted probability of a correct
responsestate_predictions: predicted probability associated
with the latent knowledge stateThe default evaluation metric is root mean squared error:
evaluate(fitted_model, data = simulation_data_50)A custom metric can also be supplied:
mae <- function(true_vals, pred_vals) {
mean(abs(true_vals - pred_vals))
}
evaluate(fitted_model, data = simulation_data_50, metric = mae)Run cross-validation without downloading an external dataset:
model <- bkt(seed = 42, num_fits = 1, parallel = FALSE)
cv_results <- crossvalidate(
model,
data = simulation_data_50,
folds = 2,
parallel = FALSE
)
cv_resultsSet forgets = TRUE when fitting to estimate a forgetting
probability:
model <- bkt(seed = 42, num_fits = 1, parallel = FALSE)
fitted_with_forgetting <- fit(
model,
data = simulation_data_50,
forgets = TRUE
)
params(fitted_with_forgetting)Use set_coef() to initialize a parameter and
fixed to keep it unchanged during fitting:
model <- bkt(seed = 42, num_fits = 1, parallel = FALSE)
model <- set_coef(
model,
list(mathematic = list(prior = 0.5))
)
fitted_fixed <- fit(
model,
data = simulation_data_50,
skills = "mathematic",
fixed = list(mathematic = list(prior = TRUE))
)
params(fitted_fixed)For a data frame with different column names, provide a
defaults mapping. This example renames the included
simulation data in memory:
custom_data <- simulation_data_50
names(custom_data) <- c("sequence", "answer", "learner", "skill")
model <- bkt(
seed = 42,
num_fits = 1,
parallel = FALSE,
defaults = list(
order_id = "sequence",
correct = "answer",
user_id = "learner",
skill_name = "skill"
)
)
fitted_custom <- fit(model, data = custom_data)
params(fitted_custom)Alternatively, a CSV file can be supplied with
data_path. In-memory data frames are preferable for
reproducible examples because they do not require downloads or temporary
files.
The supported variants are enabled through fit():
multilearn = TRUE: separate learning rates by learning
resourcemultiprior = TRUE: separate prior probabilities by
groupmultipair = TRUE: learning rates based on consecutive
resource pairsmultigs = TRUE: separate guess and slip rates by
itemVariant data must contain the corresponding class column, supplied
through defaults when its name differs from the variant
argument. For example:
variant_data <- simulation_data_50
variant_data$item <- paste0("item_", variant_data$order_id %% 2 + 1)
model <- bkt(
seed = 42,
num_fits = 1,
parallel = FALSE,
defaults = list(multigs = "item")
)
fitted_multigs <- fit(
model,
data = variant_data,
multigs = TRUE
)
params(fitted_multigs)New BKT response sequences can be generated locally:
set.seed(42)
simulated_data <- simulate_bkt_data(
prior = 0.2,
guess = 0.1,
slip = 0.1,
learn = 0.3,
num_students = 5,
min_questions = 5,
max_questions = 10
)
head(simulated_data)The function returns a data frame by default. Use
output_file only when a CSV file is explicitly needed.
BKT is licensed under the MIT License.