CDSS

Cord Hockemeyer

Content

Introduction

The CDSS package (course dependent skill structures) provides a way to quickly develop a rough competence structure for an existing course. The basic idea is to identify, for each lesson of the course, the skills taught by that lesson and required for understanding that lessons, respectively. The interesting point is that only the direct prerequisite skills have to be specified.

From this skill assignment, attribution functions (and possibly also attribution relations) can be derived on the level of both, skills and learning objects. These are then the basis for deriving and further processing skills spaces and learning object spaces using functions, e.g., of the kstMatrix package. On the other side, it is also possible to derive a skill map through the cdss_sa2mu() function which grounds a connection to the CbKST package.

The resulting structures may well need further, manual refinement, e.g. with respect to falsely equivalent skills (see below).

Skill assignment data files

Information on the assignment of skills to learning objects can be specified in the three most standard spreadsheet file formats (CSV, ODS, and XLSX). For ODS and XLSX files, two sheets are expected specifying assignment of taught and required skills respectively. For the CSV case, two distinct files are expected because CSV does not support for multi-sheet files.

Each sheet (or CSV each file) contains a table with two columns, learning object id and skill id. For each skill assigned to a learning object, there is a separate row. The table must contain a header row.

Example

The CDSS package provides example data files in the extdata directory.

fpath <- system.file("extdata", package="CDSS")
sa <- cdss_read_skill_assignment(paste0(fpath, "/SkillAssignment.ods"))
sa
#> $taught
#>    a b c d e f g
#> l1 1 0 0 0 0 0 0
#> l2 0 1 0 0 0 0 0
#> l3 0 0 1 0 0 0 0
#> l4 0 0 1 0 0 0 0
#> l5 0 0 0 1 0 0 0
#> l6 0 0 0 0 1 0 0
#> l7 0 0 0 0 0 1 1
#> l8 0 0 0 0 0 1 1
#> 
#> $required
#>    a b c d e f g
#> l1 0 0 0 0 0 0 0
#> l2 0 0 0 0 0 0 0
#> l3 1 0 0 0 0 0 0
#> l4 0 1 0 0 0 0 0
#> l5 0 1 0 0 0 0 0
#> l6 0 0 1 0 0 0 0
#> l7 0 0 0 1 1 0 0
#> l8 0 0 0 1 0 0 0
#> 
#> attr(,"class")
#> [1] "cdss_sa" "list"

By default, skill assignments which do not hold certain properties, are rejected. This behavior can be changed by setting the optional parameter warnonly to TRUE.

cdss_read_skill_assignment_ods(paste0(fpath, "/ErroneousSkillAssignment.ods"), warnonly=TRUE)
#> Warning in cdss_read_skill_assignment_ods(paste0(fpath, "/ErroneousSkillAssignment.ods"), : 'cdss_read_skill_assignment_ods' is deprecated.
#> Use 'cdss_read_skill_assignment' instead.
#> See help("Deprecated")
#> $taught
#>    c1 c2 c3 c5 c4 c6 c7
#> l1  1  0  0  0  0  0  0
#> l2  0  1  0  0  0  0  0
#> l3  0  0  1  0  0  0  0
#> l4  0  0  1  0  0  0  0
#> l5  0  0  0  1  0  0  0
#> l6  0  0  0  0  1  0  0
#> l7  0  0  0  0  0  1  0
#> l8  0  0  0  0  0  0  0
#> 
#> $required
#>    c1 c2 c3 c5 c4 c6 c7
#> l1  0  0  0  0  0  0  0
#> l2  0  0  0  0  0  0  0
#> l3  1  0  0  0  0  0  0
#> l4  0  1  0  0  0  0  0
#> l5  0  1  0  0  0  0  0
#> l6  0  0  1  0  0  0  0
#> l7  0  0  0  1  1  1  1
#> l8  0  0  0  1  0  0  0
#> 
#> attr(,"class")
#> [1] "cdss_sa" "list"   
#> [1] "Not all skills are taught by learning objects: "
#> [1] "c7"
#> [1] "Some skills are taught by and required for the same learning object: "
#> [1] "l7"
#> [1] "Not all learning objects teach something: "
#> [1] "l8"
#> [1] "The assignment tables are not skill assignment compliant!"
#> $taught
#>    c1 c2 c3 c5 c4 c6 c7
#> l1  1  0  0  0  0  0  0
#> l2  0  1  0  0  0  0  0
#> l3  0  0  1  0  0  0  0
#> l4  0  0  1  0  0  0  0
#> l5  0  0  0  1  0  0  0
#> l6  0  0  0  0  1  0  0
#> l7  0  0  0  0  0  1  0
#> l8  0  0  0  0  0  0  0
#> 
#> $required
#>    c1 c2 c3 c5 c4 c6 c7
#> l1  0  0  0  0  0  0  0
#> l2  0  0  0  0  0  0  0
#> l3  1  0  0  0  0  0  0
#> l4  0  1  0  0  0  0  0
#> l5  0  1  0  0  0  0  0
#> l6  0  0  1  0  0  0  0
#> l7  0  0  0  1  1  1  1
#> l8  0  0  0  1  0  0  0
#> 
#> attr(,"class")
#> [1] "cdss_sa" "list"

Workflow

Figure 1 shows an overall view of the possible workflow(s) within the CDSS package including the interfacing points to the kstMatrix and CbKST packages.

Figure 1: CDSS workflow

Figure 1: CDSS workflow

Deriving skill structures

There are two ways to derive the skill structure from the skill assignment, through an attribution function or through a skill (multi) map. Both ways lead to the same skill structure. Further processing then has to be done using functions from the kstMatrix and CbKSTpackages.

Example

af <- cdss_skill_sa2af(sa) # Attribution function
af
#>    Skill a b c d e f g
#> 2      a 1 0 0 0 0 0 0
#> 3      b 0 1 0 0 0 0 0
#> 4      c 1 0 1 0 0 0 0
#> 5      c 0 1 1 0 0 0 0
#> 6      d 0 1 0 1 0 0 0
#> 7      e 0 0 1 0 1 0 0
#> 8      f 0 0 0 1 1 1 1
#> 9      f 0 0 0 1 0 1 1
#> 10     g 0 0 0 1 1 1 1
#> 11     g 0 0 0 1 0 1 1
plot(kmspace(kmbasis(kmclosure(af))))

FIgure 2: Derived skill space

mu <- cdss_sa2mu(sa) # Skill multi map
mu
#>   LO a b c d e f g
#> 1 l1 1 0 0 0 0 0 0
#> 2 l2 0 1 0 0 0 0 0
#> 3 l3 1 0 1 0 0 0 0
#> 4 l4 0 1 1 0 0 0 0
#> 5 l5 0 1 0 1 0 0 0
#> 6 l6 1 0 1 0 1 0 0
#> 7 l6 0 1 1 0 1 0 0
#> 8 l8 0 1 0 1 0 1 1
#> 9 l7 0 1 1 1 1 1 1
plot(kmspace(kmbasis(cbkst_competencestructure(mu))))

FIgure 3: Dweriving a skill space through the skill multi map

Deriving LO structures

For LO structures, things are similar to but still slightly different from skill structures. Again, we have two ways to derive an LO space but the meaning of the LO states is different and thus are the spaces. The straightforward definition of an LO state would be the set of LOs the learner has visited. The respective LO space is achieved using the attribution function way. For a skill (multi) map, however, the LO state of a learner is the set of LOs whose (required and taught) skills this learner has. One can also have a look at the possible learning paths through the LO space.

Example

laf <- cdss_lo_sa2af(sa) # Attribution function
laf
#>    LO l1 l2 l3 l4 l5 l6 l7 l8
#> 2  l1  1  0  0  0  0  0  0  0
#> 3  l2  0  1  0  0  0  0  0  0
#> 4  l3  1  0  1  0  0  0  0  0
#> 5  l4  0  1  0  1  0  0  0  0
#> 6  l5  0  1  0  0  1  0  0  0
#> 7  l6  0  0  1  0  0  1  0  0
#> 8  l6  0  0  0  1  0  1  0  0
#> 9  l7  0  0  0  0  1  1  1  0
#> 10 l8  0  0  0  0  1  0  0  1
lospc <- kmspace(kmbasis(kmclosure(laf)))
plot(lospc)

FIgure 4: LO space derived through the attribution function

lp <- kmlearningpaths(lospc)
length(lp)
#> [1] 340
lp[[1]]
#> [[1]]
#> [1] "∅"
#> 
#> [[2]]
#> [1] "{l1}"
#> 
#> [[3]]
#> [1] "{l1, l2}"
#> 
#> [[4]]
#> [1] "{l1, l2, l3}"
#> 
#> [[5]]
#> [1] "{l1, l2, l3, l4}"
#> 
#> [[6]]
#> [1] "{l1, l2, l3, l4, l5}"
#> 
#> [[7]]
#> [1] "{l1, l2, l3, l4, l5, l6}"
#> 
#> [[8]]
#> [1] "{l1, l2, l3, l4, l5, l6, l8}"
#> 
#> [[9]]
#> [1] "{l1, l2, l3, l4, l5, l6, l7, l8}"
#> 
#> attr(,"class")
#> [1] "kmlearningpath" "list"
lp[[2]]
#> [[1]]
#> [1] "∅"
#> 
#> [[2]]
#> [1] "{l1}"
#> 
#> [[3]]
#> [1] "{l1, l2}"
#> 
#> [[4]]
#> [1] "{l1, l2, l3}"
#> 
#> [[5]]
#> [1] "{l1, l2, l3, l4}"
#> 
#> [[6]]
#> [1] "{l1, l2, l3, l4, l5}"
#> 
#> [[7]]
#> [1] "{l1, l2, l3, l4, l5, l6}"
#> 
#> [[8]]
#> [1] "{l1, l2, l3, l4, l5, l6, l7}"
#> 
#> [[9]]
#> [1] "{l1, l2, l3, l4, l5, l6, l7, l8}"
#> 
#> attr(,"class")
#> [1] "kmlearningpath" "list"
plot(kmspace(kmbasis(cbkst_performancestructure(mu)))) # Skill multi map

FIgure 5: LO space derived through the skill multi map

The latter LO space has 37 states while the former one has 42 states.

Limitations of the CDSS approach

Course-dependence of the obtained skill structure

CDSS stands for course-dependent skill structures. This means that a different course teaching the same set of skills will most probably lead to a different skill structure. That is, we do not give a perfect solution but rather a starting point for further development of the structure.

Possibly falsely equivalent skills

It may often occur that one learning object teaches multiple skills. If there are no other learning objects teaching these skills in different combinations, they will be deemed as equivalent although this may just be a course-dependent artifact. In this case, a refinement o the obrtained skill space may well be reasonable. The functions of the kstMatrix package offer the right tools for this. In our example space, e.g., the skills f and g are equivalent. We remedy this by determining the intersection of this space with a second one which makes f a prerequisite of g.

sf <- kmclosure(af) # Surmise function
bas <- kmbasis(sf)
plot(kmbasis(bas))

FIgure 6: Refining a basis

extbas <- matrix(c(1,0,1,1), nrow=2, byrow=TRUE)
colnames(extbas) <- c("f", "g")
class(extbas) <- unique(c("kmbasis", "kmfamset", class(extbas)))
extbas
#>      f g
#> [1,] 1 0
#> [2,] 1 1
#> attr(,"class")
#> [1] "kmbasis"  "kmfamset" "matrix"   "array"
newbas <-kmrefine(bas, extbas)
newbas
#>       a b c d e f g
#>  [1,] 1 0 0 0 0 0 0
#>  [2,] 0 1 0 0 0 0 0
#>  [3,] 1 0 1 0 0 0 0
#>  [4,] 0 1 1 0 0 0 0
#>  [5,] 0 1 0 1 0 0 0
#>  [6,] 1 0 1 0 1 0 0
#>  [7,] 0 1 1 0 1 0 0
#>  [8,] 0 1 0 1 0 1 0
#>  [9,] 0 1 0 1 0 1 1
#> attr(,"class")
#> [1] "kmfamset" "matrix"   "array"
class(newbas)
#> [1] "kmfamset" "matrix"   "array"
plot(newbas)

FIgure 7: Refined basis