Coder Social home page Coder Social logo

wjakethompson / measr Goto Github PK

View Code? Open in Web Editor NEW
8.0 4.0 2.0 122.04 MB

R package for the Bayesian estimation of diagnostic classification models using Stan

Home Page: https://measr.info

License: GNU General Public License v3.0

R 56.82% CSS 1.09% Stan 2.05% TeX 3.91% Shell 0.03% C++ 36.10%
bayesian cdm cmdstanr cognitive-diagnostic-models dcm r r-package rstan rstats stan

measr's Introduction

measr

Project Status: Active – The project has reached a stable, usable state and is being actively developed. lifecycle R package version Package downloads DOI
R-CMD-check codecov Netlify Status
Signed by License

Diagnostic classification models (DCMs) are a class of psychometric models that estimate respondent abilities as a profile of proficiency on a pre-defined set of skills, or attributes. Despite the utility of DCMs for providing fine-grained and actionable feedback with shorter assessments, they have are not widely used in applied settings, in part due to a lack of user-friendly software. Using R and Stan, measr (said: “measure”) simplifies the process of estimating and evaluating DCMs. Users can specify different DCM subtypes, define prior distributions, and estimate the model using the rstan or cmdstanr interface to Stan. You can then easily examine model parameters, calculate model fit metrics, compare competing models, and evaluate the reliability of the attributes.

Installation

You can install the released version of measr from CRAN with:

install.packages("measr")

To install the development version of measr from GitHub use:

# install.packages("remotes")
remotes::install_github("wjakethompson/measr")

Because measr is based on Stan, a C++ compiler is required. For Windows, the Rtools program comes with a C++ compiler. On Mac, it’s recommended that you install Xcode. For additional instructions and help setting up the compilers, see the RStan installation help page.

Usage

We can estimate a DCM using measr_dcm(). This function only requires a data set of item responses and a Q-matrix defining which attributes are measured by each item. We also identify any respondent or item identifier columns. Other arguments can be specified to customize the type of model to estimates (see ?measr_dcm()).

To demonstrate measr’s functionality, example data sets are included. Here we use the Examination of Certificate of Proficiency in English (ECPE; Templin & Hoffman, 2013) data (see ?ecpe for details). Note that by default, measr uses a full Markov chain Monte Carlo (MCMC) estimation with Stan, which can be time and computationally intensive. For a quicker estimation, we can use Stan’s optimizer instead of MCMC by adding method = "optim" to the function call. However, please not that some functionality will be lost when using the optimizer (e.g., the calculation of relative fit criteria requires the use of MCMC).

library(measr)

model <- measr_dcm(data = ecpe_data, resp_id = "resp_id",
                   qmatrix = ecpe_qmatrix, item_id = "item_id")

Once a model has been estimated, we can then add and evaluate model fit. This can done through absolute model fit, relative model fit (information criteria), or reliability indices. Model parameters, respondent classifications, and results of the model fit analyses can then be extracted using measr_extract().

model <- add_fit(model, method = "m2")
model <- add_criterion(model, criterion = "loo")
model <- add_reliability(model)

measr_extract(model, "m2")
#> # A tibble: 1 × 3
#>      m2    df     pval
#>   <dbl> <int>    <dbl>
#> 1  506.   325 4.37e-10

Contributions are welcome. To ensure a smooth process, please review the Contributing Guide. Please note that the measr project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.

measr's People

Contributors

andrjohns avatar wjakethompson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

measr's Issues

JOSS Review

Hi! @chartgerink asked me to review this package for JOSS and focus particularly on the Stan implementation. I am not a content expert on DCMs or IRT, so I will focus on the Bayesian modeling side. Overall, code all seems appropriate. Below are some thoughts and questions I had. Some of these may be non-issues and stem from my ignorance of common practice in the field.

  • In the DINA model code, why is each slip and guess parameter provided its own prior? Can the user specify priors for each individual item? In the measrprior() function, only a single specification for guess and slip parameters can be provided, so it may not be necessary to specify these separately in the Stan model. Unless there is some benefit to doing so, consider vectorizing the parameter list.
  • In the DINA model code, what is the motivation behind a B(5,25) prior for the slip and guess parameters. This puts the prior mode of each parameter at roughly 0.14. Is this plausible for users who may be working with smaller pilot sets and who keep default priors? This is particularly important in light of my previous point.
  • In the LCDM model code, why are interactions bounded at the minimum of the main effects?
  • For all likelihoods in the Stan models, the many nested for loops may slow things down significantly. Consider reorganizing the Stan data into a R x C matrix to allow for vectorized operations. This will speed things up and avoid the need for nested looping. Note however, this would represent a significant refactor, so take this is a suggestion to improve performance rather than a prerequisite for publication.

Open issues:

  • Vectorize priors in DINA model
  • Double-check DINA priors
  • Check constraints on interactions effects in LCDM
  • Vectorize likelihood functions?

testthat self-test fails with package dependency issues

Running the "Test" from the build window in RStudio fails with the following error messages:

==> devtools::test()

ℹ Testing measr
Error in load_imports(path) : The packages "dplyr" (>=
1.1.1) and "tidyr" (>= 1.3.0)
are required.
Calls: <Anonymous> ... load_imports -> deps_check_installed -> check_installed
Execution halted

Exited with status 1.

I have the tidyverse packages installed.

Additional `measr_extract()` features

  • More informative error messages for unknown what

Additional extracts:

  • Add attribute names to what = "strc_param" (e.g., combo of current what = "strc_param" and what = "classes")
  • Attribute base rates (via summing over classes - see ECPE case study)
  • Pi matrix

Release measr 0.1.0

First release:

Prepare for release:

  • devtools::build_readme()
  • urlchecker::url_check()
  • devtools::check(remote = TRUE, manual = TRUE)
  • devtools::check_win_devel()
  • rhub::check_for_cran()
  • Review pkgdown reference index for, e.g., missing topics
  • Draft blog post

Submit to CRAN:

  • usethis::use_version('minor')
  • devtools::submit_cran()
  • Approve email

Wait for CRAN...

  • Accepted 🎉
  • usethis::use_github_release()
  • usethis::use_dev_version()
  • usethis::use_news_md()
  • Finish blog post
  • Tweet
  • Add link to blog post in pkgdown news menu

Refining model object

Add some fit measures by default?

  • Add some fit measures by default? Maybe determined by the simulation study
  • Automatically include respondent probabilities
    • Need to balance "analysis of this data set" vs. "calibrating a model for future use." If we're just calibrating to score future data, then we are probably less interested in the respondent probabilities for the specific data set used to estimate the model.

Check prior specifications

Need to throw an error if user specifies a prior for a class or coef that is not present in the model (e.g., specifying the class = "slip" for the LCDM).

Release measr 0.1.0

First release:

Prepare for release:

  • git pull
  • Check if any deprecation processes should be advanced, as described in Gradual deprecation
  • devtools::build_readme()
  • urlchecker::url_check()
  • devtools::check(remote = TRUE, manual = TRUE)
  • devtools::check_win_devel()
  • rhub::check_for_cran()
  • git push
  • Draft blog post

Submit to CRAN:

  • usethis::use_version('minor')
  • devtools::submit_cran()
  • Approve email

Wait for CRAN...

  • Accepted 🎉
  • git push
  • usethis::use_github_release()
  • usethis::use_dev_version()
  • usethis::use_news_md()
  • git push
  • Finish blog post
  • Tweet
  • Add link to blog post in pkgdown news menu

Release measr 0.3.0

Prepare for release:

  • git pull
  • Check current CRAN check results
  • Check if any deprecation processes should be advanced, as described in Gradual deprecation
  • Polish NEWS
  • devtools::build_readme()
  • urlchecker::url_check()
  • devtools::check(remote = TRUE, manual = TRUE)
  • devtools::check_win_devel()
  • rhub::check_for_cran()
  • rhub::check(platform = 'ubuntu-rchk')
  • rhub::check_with_sanitizers()
  • revdepcheck::revdep_check(num_workers = 4)
  • Update cran-comments.md
  • git push
  • Draft blog post

Submit to CRAN:

  • usethis::use_version('minor')
  • devtools::submit_cran()
  • Approve email

Wait for CRAN...

  • Accepted 🎉
  • git push
  • usethis::use_github_release()
  • usethis::use_dev_version()
  • git push
  • Finish blog post
  • Tweet
  • Add link to blog post in pkgdown news menu

Release measr 1.0.0

Prepare for release:

  • git pull
  • Check current CRAN check results
  • Polish NEWS
  • urlchecker::url_check()
  • devtools::build_readme()
  • devtools::check(remote = TRUE, manual = TRUE)
  • devtools::check_win_devel()
  • revdepcheck::revdep_check(num_workers = 4)
  • Update cran-comments.md
  • git push
  • Draft blog post
  • Run data-raw/stan-scripts.R to update precompiled Stan code
  • Update rstan and StanHeaders versions in .github/workflows/R-CMD-check.yaml and .github/workflows/test-coverage.yaml

Submit to CRAN:

  • usethis::use_version('major')
  • devtools::submit_cran()
  • Approve email

Wait for CRAN...

  • Accepted 🎉
  • Add preemptive link to blog post in pkgdown news menu
  • usethis::use_github_release()
  • usethis::use_dev_version(push = TRUE)
  • Finish blog post
  • Tweet

Release measr 0.2.0

First release:

Prepare for release:

  • git pull
  • Check if any deprecation processes should be advanced, as described in Gradual deprecation
  • devtools::build_readme()
  • urlchecker::url_check()
  • devtools::check(remote = TRUE, manual = TRUE)
  • devtools::check_win_devel()
  • rhub::check_for_cran()
  • rhub::check(platform = 'ubuntu-rchk')
  • rhub::check_with_sanitizers()
  • git push
  • Draft blog post

Submit to CRAN:

  • usethis::use_version('minor')
  • devtools::submit_cran()
  • Approve email

Wait for CRAN...

  • Accepted 🎉
  • git push
  • usethis::use_github_release()
  • usethis::use_dev_version()
  • usethis::use_news_md()
  • git push
  • Finish blog post
  • Tweet
  • Add link to blog post in pkgdown news menu

Model summary

Provide summary function that shows:

  • Item parameters
  • Item response probabilities
  • Attribute proficiency base rates
  • Attribute profile proportions
  • Attributes correlations

Perhaps show preview of each, with guidance to use measr_extract() to pull out the full results.

Pre-compiled models

For LCDM, we could specify all possible parameters, and then use an expanded Q-matrix (i.e., with interaction terms calculated) to zero out relevant parameters (e.g., l1_212 = raw_l1_212 * Q[2, {column}].

Would need to also consider how to pass user-specified priors. rstanarm uses pre-compiled models and allows user-specified priors, so maybe look at implementation here: https://github.com/stan-dev/rstanarm/tree/master/src/stan_files

Model evaluation

Testing assumptions of models

  • Item responses are independent, conditional on profile

Fit indices

  • MAD or RMSEA for each item

User interface

  • Add interpretations to output (e.g., "ppp less than 0.05 indicates adequate fit")
  • Add links in output to references?

Iter/warmup edge case

Fix edge case where iter (or iter_sampling) is defined and warmup (or iter_warmup) is not.

Visualizing results

Add functions to easily visualize results? Maybe this spins off into ggmeasr, which gets called internally?

Some initial ideas:

  • Conditional probabilities
  • PPMCs
  • Methods for bayesplot?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.