PnodeLnAlphas: Access the combination function slope parameters for a Pnode

PnodeLnAlphasR Documentation

Access the combination function slope parameters for a Pnode

Description

In constructing a conditional probability table using the discrete partial credit framework (see calcDPCTable), the effective thetas for each parent variable are combined into a single effect theta using a combination rule. The expression PnodeAlphas(node) accesses the slope parameters associated with the combination function PnodeRules(node). The expression PnodeLnAlphas(node) which is used in mapDPC.

Usage

PnodeLnAlphas(node)
PnodeLnAlphas(node) <- value
PnodeAlphas(node)
PnodeAlphas(node) <- value
## Default S3 method:
PnodeAlphas(node)
## Default S3 replacement method:
PnodeAlphas(node) <- value

Arguments

node

A Pnode object.

value

A numeric vector of (log) slope parameters or a list of such vectors (see details). The length of the vector depends on the combination rules (see PnodeRules). If a list, it should have length one less than the number of states in node. For PnodeAlphas(node) <- value, value should only contain positive numbers.

Details

Following the framework laid out in Almond (2015), the function calcDPCTable calculates a conditional probability table using the following steps:

  1. Each set of parent variable states is converted to a set of continuous values called effective thetas (see PnodeParentTvals). These are built into an array, eTheta, using expand.grid where each column represents a parent variable and each row a possible configuration of parents.

  2. For each state of the node except the last, the set of effective thetas is filtered using the local Q-matrix, PnodeQ(node) = Q. Thus, the actual effect thetas for state s is eTheta[,Q[s,]].

  3. For each state of the node except the last, the corresponding rule is applied to the effective thetas to get a single effective theta for each row of the table. This step is essentially calls the expression: do.call(rules[[s]], list(eThetas[,Q[s,]]), PnodeAlphas(node)[[s]], PnodeBetas(node)[[s]]).

  4. The resulting set of effective thetas are converted into conditional probabilities using the link function PnodeLink(node).

The function PnodeRules accesses the function used in step 3. It should should be the name of a function or a function with the general signature of a combination function described in Compensatory. The compensatory function is a useful model for explaining the roles of the slope parameters, alpha. Let theta_{i,j} be the effective theta value for the jth parent variable on the ith row of the effective theta table, and let alpha_{j} be the corresponding slope parameter. Then the effective theta for that row is:

Z(theta_{i}) = (alpha_1theta_{i,1}+\ldots+alpha_Jtheta_{J,1})/C - beta ,

where C=\sqrt(J) is a variance stabilization constant and beta is a value derived from PnodeBetas. The functions Conjunctive and Disjunctive are similar replacing the sum with a min or max respectively.

In general, when the rule is one of Compensatory, Conjunctive, or Disjunctive, the the value of PnodeAlphas(node) should be a vector of the same length as the number of parents. As a special case, if it is a vector of length 1, then a model with a common slope is used. This looks the same in calcDPCTable but has a different implication in mapDPC where the parameters are constrained to be the same.

The rules OffsetConjunctive, and OffsetDisjunctive, work somewhat differently, in that they assume there is a single slope and multiple intercepts. Thus, the OffsetConjunctive has equation:

Z(theta_{i}) = alpha min(theta_{i,1}-beta_1, \ldots,theta_{J,1}-beta_{J}) .

In this case the assumption is that PnodeAlphas(node) will be a scalar and PnodeBetas(node) will be a vector of length equal to the number of parents.

If the value of PnodeLink is partialCredit, then the link function can be different for each state of the node. (If it is gradedResponse then the curves need to be parallel and the slopes should be the same.) If the value of PnodeAlphas(node) is a list (note: list, not numeric vector or matrix), then a different set of slopes is used for each state transition. (This is true whether PnodeRules(node) is a single function or a list of functions. Note that if there is a different rule for each transition, they could require different numbers of slope parameters.) The function calcDPCTable assumes the states are ordered from highest to lowest, and no transition is needed into the lowest state.

Node that if the value of PnodeQ(node) is not a matrix of all TRUE values, then the effective number of parents for each state transition could be different. In this case the value of PnodeAlphas(node) should be a list of vectors of different lengths (corresponding to the number of true entries in each row of PnodeQ(node)).

Finally, note that if we want the conditional probability table associated with node to be monotonic, then the PnodeAlphas(node) must be positive. To ensure this, mapDPC works with the log of the slopes, not the raw slopes. Similarly, calcDPCTable expects the log slope parameters as its lnAlphas argument, not the raw slopes. For that reason PnodeLnAlphas(node) is considered the primary function and a default method for PnodeAlphas(node) which simply takes exponents (or logs in the setter) is provided. Note that a sensible range for the slope parameters is usually between 1/2 and 2, with 1 (0 on the log scale) as a sensible first pass value.

Value

A list of numeric vectors giving the slopes for the combination function of each state transition. The vectors may be of different lengths depending on the value of PnodeRules(node) and PnodeQ(node). If the slopes are the same for all transitions (as is required with the gradedResponse link function) then a single numeric vector instead of a list is returned.

Note that the setter form may destructively modify the Pnode object (this depends on the implementation).

Note

The functions PnodeLnAlphas and PnodeLnAlphas<- are abstract generic functions, and need specific implementations. The default methods for the functions PnodeAlphas and PnodeAlphas<-. Depend on PnodeLnAlphas and PnodeLnAlphas<-, respectively. See the PNetica-package for an example.

The values of PnodeLink, PnodeRules, PnodeQ, PnodeParentTvals, PnodeLnAlphas, and PnodeBetas all need to be consistent for this to work correctly, but no error checking is done on any of the setter methods.

Author(s)

Russell Almond

References

Almond, R. G. (2015) An IRT-based Parameterization for Conditional Probability Tables. Paper presented at the 2015 Bayesian Application Workshop at the Uncertainty in Artificial Intelligence Conference.

Almond, R.G., Mislevy, R.J., Steinberg, L.S., Williamson, D.M. and Yan, D. (2015) Bayesian Networks in Educational Assessment. Springer. Chapter 8.

See Also

Pnode, PnodeQ, PnodeRules, PnodeLink, PnodeBetas, BuildTable, PnodeParentTvals, maxCPTParam calcDPCTable, mapDPC Compensatory, OffsetConjunctive

Examples

## Not run: 
library(PNetica) ## Requires implementation
sess <- NeticaSession()
startSession(sess)

tNet <- CreateNetwork("TestNet",sess)


theta1 <- NewDiscreteNode(tNet,"theta1",
                         c("VH","High","Mid","Low","VL"))
PnodeStateValues(theta1) <- effectiveThetas(PnodeNumStates(theta1))
PnodeProbs(theta1) <- rep(1/PnodeNumStates(theta1),PnodeNumStates(theta1))
theta2 <- NewDiscreteNode(tNet,"theta2",
                         c("VH","High","Mid","Low","VL"))
PnodeStateValues(theta2) <- effectiveThetas(PnodeNumStates(theta2))
PnodeProbs(theta2) <- rep(1/PnodeNumStates(theta1),PnodeNumStates(theta2))

partial3 <- NewDiscreteNode(tNet,"partial3",
                            c("FullCredit","PartialCredit","NoCredit"))
PnodeParents(partial3) <- list(theta1,theta2)

## Usual way to set rules is in constructor
partial3 <- Pnode(partial3,rules="Compensatory", link="partialCredit")
PnodePriorWeight(partial3) <- 10
BuildTable(partial3)

## slopes of 1 for both transitions
PnodeLnAlphas(partial3) <- c(0,0)
BuildTable(partial3)

## log slope 0 = slope 1
stopifnot(
   all(abs(PnodeAlphas(partial3) -1) <.0001)
)

## Make Skill 1 more important than Skill 2
PnodeLnAlphas(partial3) <- c(.25,-.25)
BuildTable(partial3)

## Make Skill 1 more important for the transition to ParitalCredit
## And Skill 2 more important for the transition to FullCredit
PnodeLnAlphas(partial3) <- list(FullCredit=c(-.25,.25),
                                PartialCredit=c(.25,-.25))
BuildTable(partial3)


## Set up so that first skill only needed for first transition, second
## skill for second transition; Adjust alphas to match
PnodeQ(partial3) <- matrix(c(TRUE,TRUE,
                             TRUE,FALSE), 2,2, byrow=TRUE)
PnodeLnAlphas(partial3) <- list(FullCredit=c(-.25,.25),
                                PartialCredit=0)
BuildTable(partial3)

## Using OffsetConjunctive rule requires single slope
PnodeRules(partial3) <- "OffsetConjunctive"
## Single slope parameter for each transition
PnodeLnAlphas(partial3) <- 0
PnodeQ(partial3) <- TRUE
PnodeBetas(partial3) <- c(0,1)
BuildTable(partial3)

## Separate slope parameter for each transition;  
## Note this will only different from the previous transition when
## mapDPC is called.  In the former case, it will learn a single slope
## parameter, in the latter, it will learn a different slope for each
## transition. 
PnodeLnAlphas(partial3) <- list(0,0)
BuildTable(partial3)


DeleteNetwork(tNet)

## End(Not run)

ralmond/Peanut documentation built on Sept. 19, 2023, 8:27 a.m.