bmihaljevic / bnclassify

Learning Discrete Bayesian Network Classifiers from Data
18 stars 10 forks source link

Decomposable scores #46

Open bmihaljevic opened 4 years ago

bmihaljevic commented 4 years ago

Hay que implementar varias cosas para family_score funcione con un número arbitrario de padres. Según lo que pone en la página 818 de Koller, el cambio del score actual al añadir un arco from -> to es:

delta score = family_score(to, c(from, parents, class), dataset) - family_score(to, c(parents, class), dataset)

donde parents son las predictoras padres de to en el grafo actual. La función tiene tres argumentos: family_score(x, y, dataset). El family_score puede ser la log verosimilitud, el BIC o el AIC. En base a la página 805 de Koller, la log verosimilitud es

     `loglik(x, y, dataset) = N · (mutual_information(x; y) − entropy(x)).`

El BIC y el AIC entonces serían:

  BIC(x, y, dataset) = N · (mutual_information(x; y) − entropy(x)) - log(N) / 2 * df. 
          AIC(x, y, dataset) = N · (mutual_information(x; y) − entropy(x)) - df. 

Para que esto se pueda calcular, hay que calcular mutual_information(x; y), entropy(x) y df (degrees of freedom). entropy(x) es fácil: utilizaentropy::entropy(xyz_freqs, method = "ML", unit = unit, verbose = F) (ver la función cmi_table()). Para df hay que adaptar la función cmi_degrees_of_freedom para que acepte matrices con mas de 3 dimensiones dimensiones. La formula es análoga y, por eficiencia, yo lo dejaría como:

stopifnot(length(dm) >= 3L)
 if (length(dm) == 3L)  {#    
Compute degrees of freedom. 
 return (dm[1] - 1) * (dm[2] - 1) * dm[3])
}
else {
return (prod(dim[-length(dim)] - 1) * dim[length(dim)])
}

Finalmente, hay que calcular mutual_information(x; y), donde y puede ser un vector de variables. Para ello hay que tomar en cuenta todas las posibles combinaciones de los padres, y. Para cada posible combinación, a, se calcula la entropía empírica de x filtrando los casos donde y == a y se multiplica por la probabilidad empírica de a. Finalmente se suma todo lo obtenido.

La manera más fácil de comprobar que se ha implementado correctamente es comparar el BIC(x, dataset) de un naive Bayes o un ODE con lo que se obtiene con los family_score().