--- title: "Bayesian Network and Local Dependence Models" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Bayesian Network and Local Dependence Models} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5, out.width = "100%" ) ``` > **Note**: Most examples in this vignette are shown with `eval=FALSE` to keep CRAN build times short. For full rendered output, see the [pkgdown site](https://kosugitti.github.io/exametrika/articles/network-models.html). ```{r library, message=FALSE, warning=FALSE} library(exametrika) library(igraph) ``` ## Bayesian Network Model (BNM) BNM represents conditional probabilities between items in a network format. A Directed Acyclic Graph (DAG) must be provided via `adj_matrix`, `adj_file`, or `g` (igraph object). ### Creating the Graph ```{r setup-igraph, message=FALSE, warning=FALSE} DAG <- matrix( c( "Item01", "Item02", "Item02", "Item03", "Item02", "Item04", "Item03", "Item05", "Item04", "Item05" ), ncol = 2, byrow = TRUE ) # Graph object g <- igraph::graph_from_data_frame(DAG) g # Adjacency matrix adj_mat <- as.matrix(igraph::get.adjacency(g)) print(adj_mat) ``` ### Running BNM ```{r model-bnm, message=FALSE, warning=FALSE} result.BNM <- BNM(J5S10, adj_matrix = adj_mat) result.BNM ``` ### Structure Learning with Genetic Algorithm `BNM_GA()` searches for a DAG suitable for the data using a genetic algorithm: ```{r model-ga-bnm, eval=FALSE} BNM_GA(J5S10, population = 20, Rs = 0.5, Rm = 0.002, maxParents = 2, maxGeneration = 100, crossover = 2, elitism = 2 ) ``` ### Structure Learning with PBIL ```{r model-pbil-bnm, eval=FALSE} BNM_PBIL(J5S10, population = 20, Rs = 0.5, Rm = 0.005, maxParents = 2, alpha = 0.05, estimate = 4 ) ``` ## Local Dependence Latent Rank Analysis (LDLRA) LDLRA combines LRA and BNM to analyze how item dependency networks change across latent ranks. A graph must be specified for each rank. ### Setting Up Rank-Specific Graphs Graphs can be provided via CSV file, adjacency matrix list, or igraph object list: ```{r setup-ldlra-dag, message=FALSE, warning=FALSE} DAG_dat <- matrix(c( "From", "To", "Rank", "Item01", "Item02", 1, "Item04", "Item05", 1, "Item01", "Item02", 2, "Item02", "Item03", 2, "Item04", "Item05", 2, "Item08", "Item09", 2, "Item08", "Item10", 2, "Item09", "Item10", 2, "Item08", "Item11", 2, "Item01", "Item02", 3, "Item02", "Item03", 3, "Item04", "Item05", 3, "Item08", "Item09", 3, "Item08", "Item10", 3, "Item09", "Item10", 3, "Item08", "Item11", 3, "Item02", "Item03", 4, "Item04", "Item06", 4, "Item04", "Item07", 4, "Item05", "Item06", 4, "Item05", "Item07", 4, "Item08", "Item10", 4, "Item08", "Item11", 4, "Item09", "Item11", 4, "Item02", "Item03", 5, "Item04", "Item06", 5, "Item04", "Item07", 5, "Item05", "Item06", 5, "Item05", "Item07", 5, "Item09", "Item11", 5, "Item10", "Item11", 5, "Item10", "Item12", 5 ), ncol = 3, byrow = TRUE) edgeFile <- tempfile(fileext = ".csv") write.csv(DAG_dat, edgeFile, row.names = FALSE, quote = TRUE) ``` ### Running LDLRA ```{r model-ldlra, eval=FALSE} result.LDLRA <- LDLRA(J12S5000, ncls = 5, adj_file = edgeFile) result.LDLRA ``` ```{r plot-ldlra, eval=FALSE} plot(result.LDLRA, type = "IRP", nc = 4, nr = 3) plot(result.LDLRA, type = "TRP") plot(result.LDLRA, type = "LRD") ``` ```{r cleanup-ldlra, include=FALSE} if (exists("edgeFile")) unlink(edgeFile) ``` ### Structure Learning for LDLRA with PBIL `LDLRA_PBIL()` learns item-interaction graphs for each rank automatically: ```{r model-pbil-ldlra, eval=FALSE} result.LDLRA.PBIL <- LDLRA_PBIL(J35S515, seed = 123, ncls = 5, method = "R", elitism = 1, successiveLimit = 15 ) result.LDLRA.PBIL ``` ## Local Dependence Biclustering (LDB) LDB combines biclustering with Bayesian network models, analyzing relationships between item fields within each rank. ```{r setup-ldb, message=FALSE, warning=FALSE} conf <- c( 1, 6, 6, 8, 9, 9, 4, 7, 7, 7, 5, 8, 9, 10, 10, 9, 9, 10, 10, 10, 2, 2, 3, 3, 5, 5, 6, 9, 9, 10, 1, 1, 7, 9, 10 ) edges_data <- data.frame( "From Field (Parent) >>>" = c( 6, 4, 5, 1, 1, 4, 3, 4, 6, 2, 4, 4, 3, 6, 4, 1, 7, 9, 6, 7 ), ">>> To Field (Child)" = c( 8, 7, 8, 7, 2, 5, 5, 8, 8, 4, 6, 7, 5, 8, 5, 8, 10, 10, 8, 9 ), "At Class/Rank (Locus)" = c( 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 ) ) edgeFile <- tempfile(fileext = ".csv") write.csv(edges_data, file = edgeFile, row.names = FALSE) ``` ```{r model-ldb, eval=FALSE} result.LDB <- LDB(U = J35S515, ncls = 5, conf = conf, adj_file = edgeFile) result.LDB ``` ```{r plot-ldb, eval=FALSE} plot(result.LDB, type = "Array") plot(result.LDB, type = "TRP") plot(result.LDB, type = "LRD") plot(result.LDB, type = "RMP", students = 1:9, nc = 3, nr = 3) plot(result.LDB, type = "FRP", nc = 3, nr = 2) ``` FieldPIRP visualizes correct answer counts for each rank and field: ```{r plot-ldb-fieldpirp, eval=FALSE} plot(result.LDB, type = "FieldPIRP") ``` ```{r cleanup-ldb, include=FALSE} if (exists("edgeFile")) unlink(edgeFile) ``` ## Bicluster Network Model (BINET) BINET combines biclustering with class-level network analysis. Unlike LDB where nodes are fields, in BINET the nodes represent classes. ```{r setup-binet, message=FALSE, warning=FALSE} conf <- c( 1, 5, 5, 5, 9, 9, 6, 6, 6, 6, 2, 7, 7, 11, 11, 7, 7, 12, 12, 12, 2, 2, 3, 3, 4, 4, 4, 8, 8, 12, 1, 1, 6, 10, 10 ) edges_data <- data.frame( "From Class (Parent) >>>" = c( 1, 2, 3, 4, 5, 7, 2, 4, 6, 8, 10, 6, 6, 11, 8, 9, 12 ), ">>> To Class (Child)" = c( 2, 4, 5, 5, 6, 11, 3, 7, 9, 12, 12, 10, 8, 12, 12, 11, 13 ), "At Field (Locus)" = c( 1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 5, 7, 8, 8, 9, 9, 12 ) ) edgeFile <- tempfile(fileext = ".csv") write.csv(edges_data, file = edgeFile, row.names = FALSE) ``` ```{r model-binet, eval=FALSE} result.BINET <- BINET( U = J35S515, ncls = 13, nfld = 12, conf = conf, adj_file = edgeFile ) print(result.BINET) ``` ```{r plot-binet, eval=FALSE} plot(result.BINET, type = "Array") plot(result.BINET, type = "TRP") plot(result.BINET, type = "LRD") plot(result.BINET, type = "RMP", students = 1:9, nc = 3, nr = 3) plot(result.BINET, type = "FRP", nc = 3, nr = 2) ``` LDPSR shows Passing Student Rates for locally dependent classes: ```{r plot-binet-ldpsr, eval=FALSE} plot(result.BINET, type = "LDPSR", nc = 3, nr = 2) ``` ```{r cleanup-binet, include=FALSE} if (exists("edgeFile")) unlink(edgeFile) ``` ## Model Comparison | Model | Nodes | Locus | Key Feature | |-------|-------|-------|-------------| | **LDLRA** | Items | Rank | Item dependencies change across ranks | | **LDB** | Fields | Rank | Field-level dependencies within ranks | | **BINET** | Classes | Field | Class transitions within fields | ## Reference Shojima, K. (2022). *Test Data Engineering*. Springer.