Processing math: 100%
Skip to contents
library(bncounterfactuals)
library(bnlearn)

Persuasive Explanations

Persuasive explanations of a classifier output given an input X are a tuple <S,C>, where S is a set of sufficient explanations and C is a set of counterfactual explanations. Sufficient explanations are subsets of the explanatory variables such that, if they have the same values as in the original input X, the output of the classifier will remain the same regardless of the value of the rest of the variables. Counterfactual explanations are the opposite: value assignations to a subset of the explanatory variables such that, if they all have different values from the original assignation in X, and the other variables remain with the same value, the output changes.

BFS_SFX

BFS_SFX (Koopman and Renooij 2021) is an algorithm to find sufficient explanations for the output of a Bayesian Network, but may also be used for almost any classifier. Below is a use example, where one sufficient explanation is obtained for the output “Fallot”: with XrayReport = “Oligaemic”, it is enough to get the same output: “Fallot”. Note that given the use of an approximate inference algorithm with few available variables, this explanation may change due to the inherent randomness of the algorithm.

set.seed(40)
download.file("https://www.bnlearn.com/bnrepository/child/child.rda",
              "child.rda", "auto", quiet = TRUE)
load("child.rda")  # Load CHILD Bayesian Network
evidence = data.frame(
  LVHReport=factor(x = "yes", levels = dimnames(bn$LVHreport$prob)[[1]]),
  LowerBodyO2=factor(x = "5-12", levels = dimnames(bn$LowerBodyO2$prob)[[1]]),
  CO2Report=factor(x = "<7.5", levels = dimnames(bn$CO2Report$prob)[[1]]),
  XrayReport=factor(x = "Oligaemic", levels = dimnames(bn$XrayReport$prob)[[1]])
)
target <- predict(object = bn, node = bn$Disease$node, data = evidence,
                 method = "bayes-lw")
print("Classification input (see dataframe):")
#> [1] "Classification input (see dataframe):"
print(evidence)
#>   LVHReport LowerBodyO2 CO2Report XrayReport
#> 1       yes        5-12      <7.5  Oligaemic
print("Classification output:")
#> [1] "Classification output:"
print(target)
#> [1] Fallot
#> Levels: PFC TGA Fallot PAIVS TAPVD Lung
expected <- factor("TGA", levels = levels(target))
print("Expected output was:")
#> [1] "Expected output was:"
print(expected)
#> [1] TGA
#> Levels: PFC TGA Fallot PAIVS TAPVD Lung
predict_f <- function(df) {
  predict(object = bn, node = bn$Disease$node, data = df, method = "bayes-lw", n = 500000)}
print("Sufficient explanation for the output:")
#> [1] "Sufficient explanation for the output:"
str(bfs_sfx(predict_f, evidence, target, expected))
#> List of 1
#>  $ :List of 1
#>   ..$ XrayReport: Factor w/ 5 levels "Normal","Oligaemic",..: 2

BFS_CFX

BFS_CFX (Koopman and Renooij 2021) is an algorithm to find counterfactual explanations for the output of a Bayesian Network, but may also be used for almost any classifier. It is applied in a similar fashion to BFS_CFX (shown above). The output for the next example gives possible counterfactual explanations that would have given the output “TGA” if the rest of the variables maintain the same values.

print("Classification input (see dataframe):")
#> [1] "Classification input (see dataframe):"
print(evidence)
#>   LVHReport LowerBodyO2 CO2Report XrayReport
#> 1       yes        5-12      <7.5  Oligaemic
print("Classification output:")
#> [1] "Classification output:"
print(target)
#> [1] Fallot
#> Levels: PFC TGA Fallot PAIVS TAPVD Lung
print("Expected output was:")
#> [1] "Expected output was:"
print(expected)
#> [1] TGA
#> Levels: PFC TGA Fallot PAIVS TAPVD Lung
print("Counterfactual explanations for the output:")
#> [1] "Counterfactual explanations for the output:"
str(bfs_cfx(predict_f, evidence, target, expected))
#> List of 4
#>  $ :List of 1
#>   ..$ XrayReport: Factor w/ 5 levels "Normal","Oligaemic",..: 1
#>  $ :List of 1
#>   ..$ XrayReport: Factor w/ 5 levels "Normal","Oligaemic",..: 3
#>  $ :List of 1
#>   ..$ XrayReport: Factor w/ 5 levels "Normal","Oligaemic",..: 4
#>  $ :List of 2
#>   ..$ LowerBodyO2: Factor w/ 3 levels "<5","5-12","12+": 1
#>   ..$ XrayReport : Factor w/ 5 levels "Normal","Oligaemic",..: 5

BFS_SFX_CFX

BFS_SFX_CFX (Koopman and Renooij 2021) is a combination of both algorithms above that computes at the same time counterfactual and sufficient explanations of an outcome. The different pairs that can be formed with the sufficient explanations and the counterfactual explanations are called persuasive explanations. The algorithm is used similarly to both above:

print("Classification input (see dataframe):")
#> [1] "Classification input (see dataframe):"
print(evidence)
#>   LVHReport LowerBodyO2 CO2Report XrayReport
#> 1       yes        5-12      <7.5  Oligaemic
print("Classification output:")
#> [1] "Classification output:"
print(target)
#> [1] Fallot
#> Levels: PFC TGA Fallot PAIVS TAPVD Lung
print("Expected output was:")
#> [1] "Expected output was:"
print(expected)
#> [1] TGA
#> Levels: PFC TGA Fallot PAIVS TAPVD Lung
print("Persuasive explanations for the output:")
#> [1] "Persuasive explanations for the output:"
str(bfs_sfx_cfx(predict_f, evidence, target, expected))
#> List of 2
#>  $ sfxs:List of 1
#>   ..$ :List of 1
#>   .. ..$ XrayReport: Factor w/ 5 levels "Normal","Oligaemic",..: 2
#>  $ cfxs:List of 4
#>   ..$ :List of 1
#>   .. ..$ XrayReport: Factor w/ 5 levels "Normal","Oligaemic",..: 1
#>   ..$ :List of 1
#>   .. ..$ XrayReport: Factor w/ 5 levels "Normal","Oligaemic",..: 3
#>   ..$ :List of 1
#>   .. ..$ XrayReport: Factor w/ 5 levels "Normal","Oligaemic",..: 4
#>   ..$ :List of 2
#>   .. ..$ LowerBodyO2: Factor w/ 3 levels "<5","5-12","12+": 1
#>   .. ..$ XrayReport : Factor w/ 5 levels "Normal","Oligaemic",..: 5

Using a helper function for bnlearn

A wrapper function is provided to use this algorithm with a Bayesian Network as implemented in bnlearn (Scutari, Silander, and Ness 2021). The main advantage is that it allows to set a threshold for classification of the MLE. Currently setting a threshold for each label is not allowed, and it is planned to make a change to include this feature soon, as it is a limited policy.

# Predict most likely label if posterior prob > 0.20 else predict TGA
predict_f <- bnlearn_predict_wrapper(bn, bn$Disease$node, "bayes-lw",
                                     threshold=0.20, default="TGA")
print(bfs_sfx(predict_f, evidence, target, expected))
#> [[1]]
#> [[1]]$CO2Report
#> [1] <7.5
#> Levels: <7.5 >=7.5
#> 
#> [[1]]$XrayReport
#> [1] Oligaemic
#> Levels: Normal Oligaemic Plethoric Grd_Glass Asy/Patchy
#> 
#> 
#> [[2]]
#> [[2]]$LVHReport
#> [1] yes
#> Levels: yes no
#> 
#> [[2]]$XrayReport
#> [1] Oligaemic
#> Levels: Normal Oligaemic Plethoric Grd_Glass Asy/Patchy
Koopman, Tara, and Silja Renooij. 2021. “Persuasive Contrastive Explanations for Bayesian Networks.” In European Conference on Symbolic and Quantitative Approaches with Uncertainty, 229–42. Springer.
Scutari, Marco, Tomi Silander, and Robert Ness. 2021. Bnlearn: Bayesian Network Structure Learning, Parameter Learning and Inference. https://www.bnlearn.com/.