Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A lot of changes #397

Merged
merged 78 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f93b77b
bookkeeping
osorensen Jan 19, 2024
f9f55db
removed unnecessary call
osorensen Jan 19, 2024
84a2230
marking as const
osorensen Jan 19, 2024
7959b6c
adding more consts
osorensen Jan 19, 2024
2a639d6
additional safety measures
osorensen Jan 19, 2024
7391954
parallelization working (#355)
osorensen Jan 19, 2024
a8bdc0d
correcting an error in docs
osorensen Jan 19, 2024
2d69ada
Merge branch 'develop' of https://github.com/ocbe-uio/BayesMallows in…
osorensen Jan 19, 2024
83248f6
update cran-comments
osorensen Jan 24, 2024
506d5c4
updating comments
osorensen Jan 24, 2024
a5d84e4
Merge branch 'master' into develop
osorensen Jan 26, 2024
d25a0f2
updating news
osorensen Jan 26, 2024
243b8a3
deleting submission file
osorensen Jan 26, 2024
16a93ba
Adding support for sampling from prior (#360)
osorensen Jan 26, 2024
eddbd22
Merge branch 'develop' of https://github.com/ocbe-uio/BayesMallows in…
osorensen Jan 26, 2024
9b7d4dc
fixed error in update_mallows.SMCMallows
osorensen Jan 26, 2024
236a21d
updated failing test and added namespace qualifier
osorensen Jan 26, 2024
144a451
added long-running SMC test from prior
osorensen Jan 26, 2024
a62545e
Take care of item names properly (#363)
osorensen Jan 26, 2024
ec9500c
Can now deal with a single vector of input data (#364)
osorensen Jan 26, 2024
db8a31b
updating news
osorensen Jan 26, 2024
78e4f29
updated set_priors function
osorensen Feb 7, 2024
86723fc
closes #370
osorensen Feb 7, 2024
2a61f42
Added a gamma prior (#371)
osorensen Feb 7, 2024
45e1eeb
Merge branch 'priors-issue-370' of https://github.com/ocbe-uio/BayesM…
osorensen Feb 7, 2024
9f4cc7f
Had forgot to implement the change... (#372)
osorensen Feb 7, 2024
defa9db
Merge branch 'develop' of https://github.com/ocbe-uio/BayesMallows in…
osorensen Feb 8, 2024
41cb4ab
Added lag option (#373)
osorensen Feb 8, 2024
9fddacd
ready for the change
osorensen Feb 8, 2024
ee08f70
Merge branch 'develop' of https://github.com/ocbe-uio/BayesMallows in…
osorensen Feb 8, 2024
701bf6b
Resampling issue 365 (#376)
osorensen Feb 9, 2024
bd74eb5
resolving conflict and bumping dev version
osorensen Feb 9, 2024
0747676
removed git conflict marker
osorensen Feb 9, 2024
ce0128a
added a line shift
osorensen Feb 15, 2024
d3bbc55
removing const-ref from built-in types
osorensen Feb 15, 2024
0af8731
refactoring limits functions for pairwise augmentation
osorensen Feb 15, 2024
7c55d63
increasing test strictness
osorensen Feb 15, 2024
ea86e61
added some more work
osorensen Feb 16, 2024
30d7774
moving distance code into implementation file
osorensen Feb 16, 2024
2d71e7c
moved partition function code into cpp files
osorensen Feb 16, 2024
4395859
added code for reproducing Liu et al 2019 review
osorensen Feb 16, 2024
4f2608f
changed updating frequency for pkgdown. closes #380
osorensen Feb 16, 2024
a80b0d6
adding ignore to codecov
osorensen Feb 16, 2024
2fe90c2
fixing #381 (#382)
osorensen Feb 16, 2024
9924131
Heatplot issue 381 (#383)
osorensen Feb 16, 2024
84e5671
updated news
osorensen Feb 16, 2024
c9cf154
fixing conflict
osorensen Feb 16, 2024
7a0593d
resolving conflict
osorensen Feb 19, 2024
eb10ac8
updated tests
osorensen Feb 20, 2024
fe4c937
Swap issue 368 (#384)
osorensen Feb 21, 2024
a0b03cd
corrected typo in docs
osorensen Feb 22, 2024
b1a5693
refactor
osorensen Feb 22, 2024
3a4f470
removed unused argument
osorensen Feb 22, 2024
e8d0f0f
changed argument order
osorensen Feb 22, 2024
5af0249
moved metric into the parameters class
osorensen Feb 22, 2024
11ecd7f
fixed a bug
osorensen Feb 22, 2024
b196f54
simplifying the tidy function
osorensen Feb 23, 2024
ad96fcd
simplified n_assessors argument
osorensen Feb 23, 2024
212ed23
removed observation_frequency from cpp return values
osorensen Feb 23, 2024
e4ba5b6
moved any_missing to setup_rank_data
osorensen Feb 23, 2024
d22834a
moving augpair to setup_rank_data
osorensen Feb 23, 2024
8c5b28f
added test for burnin
osorensen Feb 23, 2024
39e9a5c
some fixes
osorensen Feb 23, 2024
1b42c5b
updated news
osorensen Feb 23, 2024
f79c738
rebuilt smc vignette
osorensen Feb 23, 2024
8e47867
recompiled readme
osorensen Feb 23, 2024
b244710
Function for sequential learning (#391)
osorensen Feb 27, 2024
60ab54a
harmonizing pairwise and partial
osorensen Feb 27, 2024
3d7757d
Merge branch 'develop' of https://github.com/ocbe-uio/BayesMallows in…
osorensen Feb 27, 2024
a2600d1
Burnin issue 394 (#396)
osorensen Feb 28, 2024
35dd003
incremented dev version
osorensen Feb 28, 2024
190d85d
updated example
osorensen Feb 28, 2024
e037e7d
styling
osorensen Feb 28, 2024
eabbf2f
styling
osorensen Feb 28, 2024
8d47802
pleasing CodeFactor
osorensen Feb 28, 2024
fd8441f
fixed bug in acceptance rate for compute_mallows_sequentially
osorensen Feb 28, 2024
7187759
not linting examples
osorensen Feb 28, 2024
f19be0f
small improvement of docs to plot_elbow
osorensen Feb 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 1 addition & 13 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,7 @@ jobs:
run: |
library(lintr)
excluded_files <- list(
"inst/examples/compute_consensus_example.R",
"inst/examples/compute_mallows_example.R",
"inst/examples/compute_mallows_mixtures_example.R",
"inst/examples/compute_posterior_intervals_example.R",
"inst/examples/estimate_partition_function_example.R",
"inst/examples/generate_constraints_example.R",
"inst/examples/generate_initial_ranking_example.R",
"inst/examples/generate_transitive_closure_example.R",
"inst/examples/label_switching_example.R",
"inst/examples/obs_freq_example.R",
"inst/examples/plot_top_k_example.R",
"inst/examples/plot.BayesMallows_example.R",
"inst/examples/sample_mallows_example.R",
"inst",
"data-raw",
"tests/testthat.R",
"tests",
Expand Down
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: BayesMallows
Type: Package
Title: Bayesian Preference Learning with the Mallows Rank Model
Version: 2.0.1.9003
Version: 2.0.1.9006
Authors@R: c(person("Oystein", "Sorensen",
email = "oystein.sorensen.1985@gmail.com",
role = c("aut", "cre"),
Expand Down
11 changes: 11 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
# Generated by roxygen2: do not edit by hand

S3method("burnin<-",BayesMallows)
S3method("burnin<-",BayesMallowsMixtures)
S3method(assess_convergence,BayesMallows)
S3method(assess_convergence,BayesMallowsMixtures)
S3method(burnin,BayesMallows)
S3method(burnin,BayesMallowsMixtures)
S3method(burnin,SMCMallows)
S3method(compute_consensus,BayesMallows)
S3method(compute_consensus,SMCMallows)
S3method(compute_posterior_intervals,BayesMallows)
S3method(compute_posterior_intervals,SMCMallows)
S3method(generate_initial_ranking,BayesMallowsIntransitive)
S3method(generate_initial_ranking,BayesMallowsTransitiveClosure)
S3method(get_acceptance_ratios,BayesMallows)
S3method(get_acceptance_ratios,SMCMallows)
S3method(plot,BayesMallows)
S3method(plot,SMCMallows)
S3method(print,BayesMallows)
Expand All @@ -16,18 +23,22 @@ S3method(print,SMCMallows)
S3method(update_mallows,BayesMallows)
S3method(update_mallows,BayesMallowsPriorSamples)
S3method(update_mallows,SMCMallows)
export("burnin<-")
export(assess_convergence)
export(assign_cluster)
export(burnin)
export(compute_consensus)
export(compute_expected_distance)
export(compute_mallows)
export(compute_mallows_mixtures)
export(compute_mallows_sequentially)
export(compute_observation_frequency)
export(compute_posterior_intervals)
export(compute_rank_distance)
export(create_ordering)
export(create_ranking)
export(estimate_partition_function)
export(get_acceptance_ratios)
export(get_cardinalities)
export(get_mallows_loglik)
export(get_transitive_closure)
Expand Down
23 changes: 19 additions & 4 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# BayesMallows (development versions)

* Acceptance ratios are now tracked both in the Metropolis-Hastings algorithm
used by compute_mallows() and in the move step inside the sequential Monte
Carlo algorithm used by update_mallows() and compute_mallows_sequentially().
Use the function get_acceptance_ratios() to access them.
* BREAKING CHANGE: Burnin now has to be explicitly set using
'burnin(model) <- value' if it is not already set in compute_options. This
alleviates the need for a 'burnin' argument in the functions for assessing the
posterior distribution and it abstracts away the implementation from the user.
See '?burnin' and '?burnin<-' for details.
* The swap proposal defined in Crispino et al., Annals of Applied Statistics
(2019) is now an option for proposing the modal ranking rho. It can be
defined by setting rho_proposal="swap" in set_compute_options(). The leap-and-
shift distribution is still the default.
* Fixed a bug in heat_plot() when the model has been estimated with
rho_thinning > 1, causing the probabilities to be unnormalized. Issue #381.
Thanks to Marta Crispino for discovering the bug.
Expand All @@ -10,10 +23,12 @@
sampling of latent ranks, specified in the "latent_sampling_lag" argument
to set_smc_options().
* Prior for precision parameter alpha is now a gamma distribution. Until now
an exponential distribution has been assumed. Since the exponential is a special
case of the gamma with shape parameter equal to 1 (the default), this is not
a breaking change. However, it adds flexibility when it comes to specifying the prior.
* setup_rank_data() now accepts a single vector of rankings, silently converting a to matrix with a single row.
an exponential distribution has been assumed. Since the exponential is a
special case of the gamma with shape parameter equal to 1 (the default), this
is not a breaking change. However, it adds flexibility when it comes to
specifying the prior.
* setup_rank_data() now accepts a single vector of rankings, silently converting
a vector to matrix with a single row.
* Sequential Monte Carlo algorithm can now start from a sample from the prior
distribution, see the sample_prior() function for an example.
* Added support for parallelism under-the-hood with oneTBB.
Expand Down
33 changes: 33 additions & 0 deletions R/acceptance_ratio.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#' @title Get Acceptance Ratios
#' @description Extract acceptance ratio from Metropolis-Hastings
#' algorithm used by [compute_mallows()] or by the move step in
#' [update_mallows()] and [compute_mallows_sequentially()]. Currently the
#' function only returns the values, but it will be refined in the future. If
#' burnin is not set in the call to [compute_mallows()], the acceptance ratio
#' for all iterations will be reported. Otherwise the post burnin acceptance
#' ratio is reported. For the SMC method the acceptance ratios apply to all
#' iterations, since no burnin is needed in here.
#'
#' @param model_fit A model fit.
#' @param ... Other arguments passed on to other methods. Currently not used.
#'
#' @export
#' @example /inst/examples/get_acceptance_ratios_example.R
#'
#' @family posterior quantities
#'
get_acceptance_ratios <- function(model_fit, ...) {
UseMethod("get_acceptance_ratios")
}

#' @export
#' @rdname get_acceptance_ratios
get_acceptance_ratios.BayesMallows <- function(model_fit, ...) {
model_fit$acceptance_ratios
}

#' @export
#' @rdname get_acceptance_ratios
get_acceptance_ratios.SMCMallows <- function(model_fit, ...) {
model_fit$acceptance_ratios
}
34 changes: 17 additions & 17 deletions R/assess_convergence.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#' `"theta"`.
#'
#' @param items The items to study in the diagnostic plot for `rho`. Either a
#' vector of item names, corresponding to `model_fit$items` or a vector of
#' vector of item names, corresponding to `model_fit$data$items` or a vector of
#' indices. If NULL, five items are selected randomly. Only used when
#' `parameter = "rho"` or `parameter = "Rtilde"`.
#'
Expand Down Expand Up @@ -109,23 +109,23 @@ trace_alpha <- function(m, clusters) {
}

trace_rho <- function(model_fit, items, clusters = model_fit$n_clusters > 1) {
if (is.null(items) && model_fit$n_items > 5) {
if (is.null(items) && model_fit$data$n_items > 5) {
message("Items not provided by user. Picking 5 at random.")
items <- sample.int(model_fit$n_items, 5)
} else if (is.null(items) && model_fit$n_items > 0) {
items <- seq.int(from = 1, to = model_fit$n_items)
items <- sample.int(model_fit$data$n_items, 5)
} else if (is.null(items) && model_fit$data$n_items > 0) {
items <- seq.int(from = 1, to = model_fit$data$n_items)
} else if (!is.null(items)) {
if (is.numeric(items) &&
length(setdiff(items, seq_len(model_fit$n_item))) > 0) {
length(setdiff(items, seq_len(model_fit$data$n_items))) > 0) {
stop("numeric items vector must contain indices between 1 and the number of items")
}
if (is.character(items) && length(setdiff(items, model_fit$items) > 0)) {
if (is.character(items) && length(setdiff(items, model_fit$data$items) > 0)) {
stop("unknown items provided")
}
}

if (!is.character(items)) {
items <- model_fit$items[items]
items <- model_fit$data$items[items]
}

df <- model_fit$rho[model_fit$rho$item %in% items, , drop = FALSE]
Expand Down Expand Up @@ -157,20 +157,20 @@ trace_rtilde <- function(model_fit, items, assessors, ...) {
stop("Please rerun with compute_mallows with save_aug = TRUE")
}

if (is.null(items) && model_fit$n_items > 5) {
if (is.null(items) && model_fit$data$n_items > 5) {
message("Items not provided by user. Picking 5 at random.")
items <- sample.int(model_fit$n_items, 5)
} else if (is.null(items) && model_fit$n_items > 0) {
items <- seq.int(from = 1, to = model_fit$n_items)
items <- sample.int(model_fit$data$n_items, 5)
} else if (is.null(items) && model_fit$data$n_items > 0) {
items <- seq.int(from = 1, to = model_fit$data$n_items)
}

if (is.null(assessors) && model_fit$n_assessors > 5) {
if (is.null(assessors) && model_fit$data$n_assessors > 5) {
message("Assessors not provided by user. Picking 5 at random.")
assessors <- sample.int(model_fit$n_assessors, 5)
} else if (is.null(assessors) && model_fit$n_assessors > 0) {
assessors <- seq.int(from = 1, to = model_fit$n_assessors)
assessors <- sample.int(model_fit$data$n_assessors, 5)
} else if (is.null(assessors) && model_fit$data$n_assessors > 0) {
assessors <- seq.int(from = 1, to = model_fit$data$n_assessors)
} else if (!is.null(assessors)) {
if (length(setdiff(assessors, seq(1, model_fit$n_assessors, 1))) > 0) {
if (length(setdiff(assessors, seq(1, model_fit$data$n_assessors, 1))) > 0) {
stop("assessors vector must contain numeric indices between 1 and the number of assessors")
}
}
Expand Down
13 changes: 4 additions & 9 deletions R/assign_cluster.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
#' @param model_fit An object of type `BayesMallows`, returned from
#' [compute_mallows()].
#'
#' @param burnin A numeric value specifying the number of iterations to discard
#' as burn-in. Defaults to `model_fit$burnin`, and must be provided if
#' `model_fit$burnin` does not exist. See [assess_convergence()].
#'
#' @param soft A logical specifying whether to perform soft or hard clustering.
#' If `soft=TRUE`, all cluster probabilities are returned, whereas if
#' `soft=FALSE`, only the maximum a posterior (MAP) cluster probability is
Expand Down Expand Up @@ -42,14 +38,13 @@
#' head(assign_cluster(mixture_model, soft = FALSE))
#'
assign_cluster <- function(
model_fit, burnin = model_fit$burnin, soft = TRUE, expand = FALSE) {
if (is.null(burnin)) {
stop("Please specify the burnin.")
model_fit, soft = TRUE, expand = FALSE) {
if (is.null(burnin(model_fit))) {
stop("Please specify the burnin with 'burnin(model_fit) <- value'.")
}
stopifnot(burnin < model_fit$nmc)

df <- model_fit$cluster_assignment[
model_fit$cluster_assignment$iteration > burnin, ,
model_fit$cluster_assignment$iteration > burnin(model_fit), ,
drop = FALSE
]

Expand Down
82 changes: 82 additions & 0 deletions R/burnin.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#' @title Set the burnin
#' @description Set or update the burnin of a model
#' computed using Metropolis-Hastings.
#'
#' @param model An object of class `BayesMallows` returned from
#' [compute_mallows()] or an object of class `BayesMallowsMixtures` returned
#' from [compute_mallows_mixtures()].
#' @param ... Optional arguments passed on to other methods. Currently not used.
#' @param value An integer specifying the burnin. If `model` is of class
#' `BayesMallowsMixtures`, a single value will be assumed to be the burnin
#' for each model element. Alternatively, `value` can be specified as an
#' integer vector of the same length as `model`, and hence a separate burnin
#' can be set for each number of mixture components.
#'
#' @export
#' @return An object of class `BayesMallows` with burnin set.
#'
#' @family modeling
#'
#' @example /inst/examples/burnin_example.R
#'
`burnin<-` <- function(model, ..., value) UseMethod("burnin<-")

#' @export
#' @rdname burnin-set
`burnin<-.BayesMallows` <- function(model, ..., value) {
if (inherits(model, "SMCMallows")) {
stop("Cannot set burnin for SMC model.")
}
validate_integer(value)
if (value >= model$compute_options$nmc) {
stop("Burnin cannot be larger than the number of Monte Carlo samples.")
}
# Workaround as long as we have the deprecation notice for `$<-`
class(model) <- "list"
model$compute_options$burnin <- value
class(model) <- "BayesMallows"
model
}

#' @export
#' @rdname burnin-set
`burnin<-.BayesMallowsMixtures` <- function(model, ..., value) {
for (v in value) validate_integer(v)
if (length(value) == 1) value <- rep(value, length(model))
if (length(value) != length(model)) stop("Wrong number of entries in value.")

Check warning on line 46 in R/burnin.R

View check run for this annotation

Codecov / codecov/patch

R/burnin.R#L46

Added line #L46 was not covered by tests

for (i in seq_along(model)) burnin(model[[i]]) <- value[[i]]
model
}

#' @title See the burnin
#' @description
#' See the current burnin value of the model.
#'
#' @param model A model object.
#' @param ... Optional arguments passed on to other methods. Currently not used.
#'
#' @export
#' @return An integer specifying the burnin, if it exists. Otherwise `NULL`.
#'
#' @family modeling
#'
#' @example /inst/examples/burnin_example.R
#'
burnin <- function(model, ...) UseMethod("burnin")

#' @rdname burnin
#' @export
burnin.BayesMallows <- function(model, ...) {
model$compute_options$burnin
}

#' @rdname burnin
#' @export
burnin.BayesMallowsMixtures <- function(model, ...) {
lapply(model, burnin)
}

#' @rdname burnin
#' @export
burnin.SMCMallows <- function(model, ...) 0
18 changes: 8 additions & 10 deletions R/compute_consensus.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
#' @param model_fit A model fit.
#' @param type Character string specifying which consensus to compute. Either
#' `"CP"` or `"MAP"`. Defaults to `"CP"`.
#' @param burnin A numeric value specifying the number of iterations to discard
#' as burn-in. Defaults to `model_fit$burnin`, and must be provided if
#' `model_fit$burnin` does not exist. See [assess_convergence()].
#' @param parameter Character string defining the parameter for which to compute
#' the consensus. Defaults to `"rho"`. Available options are `"rho"` and
#' `"Rtilde"`, with the latter giving consensus rankings for augmented ranks.
Expand All @@ -32,10 +29,11 @@ compute_consensus <- function(model_fit, ...) {
#' @export
#' @rdname compute_consensus
compute_consensus.BayesMallows <- function(
model_fit, type = c("CP", "MAP"), burnin = model_fit$burnin,
model_fit, type = c("CP", "MAP"),
parameter = c("rho", "Rtilde"), assessors = 1L, ...) {
if (is.null(burnin)) stop("Please specify the burnin.")
stopifnot(burnin < model_fit$nmc)
if (is.null(burnin(model_fit))) {
stop("Please specify the burnin with 'burnin(model_fit) <- value'.")
}
type <- match.arg(type, c("CP", "MAP"))
parameter <- match.arg(parameter, c("rho", "Rtilde"))

Expand All @@ -45,15 +43,15 @@ compute_consensus.BayesMallows <- function(
}

if (parameter == "rho") {
df <- model_fit$rho[model_fit$rho$iteration > burnin, , drop = FALSE]
df <- model_fit$rho[model_fit$rho$iteration > burnin(model_fit), , drop = FALSE]
if (type == "CP") {
df <- cpc_bm(df)
} else if (type == "MAP") {
df <- cpm_bm(df)
}
} else if (parameter == "Rtilde") {
df <- model_fit$augmented_data[
model_fit$augmented_data$iteration > burnin &
model_fit$augmented_data$iteration > burnin(model_fit) &
model_fit$augmented_data$assessor %in% assessors, ,
drop = FALSE
]
Expand Down Expand Up @@ -83,8 +81,8 @@ compute_consensus.BayesMallows <- function(
compute_consensus.SMCMallows <- function(
model_fit, type = c("CP", "MAP"), parameter = "rho", ...) {
parameter <- match.arg(parameter, "rho")
model_fit$burnin <- 0
model_fit$nmc <- model_fit$n_particles
model_fit$compute_options$burnin <- 0
model_fit$compute_options$nmc <- model_fit$n_particles
NextMethod("compute_consensus")
}

Expand Down
4 changes: 3 additions & 1 deletion R/compute_mallows.R
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ compute_mallows <- function(
validate_rankings(data)
validate_initial_values(initial_values, data)

pfun_values <- extract_pfun_values(model_options, data, pfun_estimate)
pfun_values <- extract_pfun_values(
model_options$metric, data$n_items, pfun_estimate
)

if (is.null(cl)) {
lapplyfun <- lapply
Expand Down
Loading
Loading