1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
function KLdiv = KL_divergence(bnetP, bnetQ)
% KL_DIVERGENCE computes the Kullback-Leibler divergence between two BNET distributions
% KLdiv = KL_divergence(bnetP, bnetQ)
%
% Output :
% div = sum_x P(x).log(P(x)/Q(x))
%
% Rem :
% This version is optimized for speed, but can use too many memory
% ==> if you have a memory problem, use kl_divergence2 instead
%
% ONLY FOR TABULAR NODES
% Make sure that you have done the params learning.
%
% V1.1 : 8 oct 2004 (Ph. Leray - philippe.leray@univ-nantes.fr)
N = size(bnetP.dag,1);
N2 = size(bnetQ.dag,1);
ns= bnetP.node_sizes;
ns2= bnetQ.node_sizes;
if N~=N2, error('size of dags must be the same'), end
if ns~=ns2, error('node sizes of dags must be the same'), end
tiny = exp(-700);
KLdiv=0;
inst = ind2subv(ns, 1:prod(ns));
%Px=1; Qx=1;
for i=1:N,
ps = parents(bnetP.dag, i);
%e = bnetP.equiv_class(i);
%[tmp Px(:,i)] = prob_node(bnetP.CPD{e}, inst(:,i)', inst(:,ps)');
[tmp Px(:,i)] = prob_node(bnetP.CPD{i}, inst(:,i)', inst(:,ps)');
ps = parents(bnetQ.dag, i);
%e = bnetQ.equiv_class(i);
%[tmp Qx(:,i)] = prob_node(bnetQ.CPD{e}, inst(:,i)', inst(:,ps)');
[tmp Qx(:,i)] = prob_node(bnetQ.CPD{i}, inst(:,i)', inst(:,ps)');
end
Px=prod(Px,2);
Px = Px + (Px==0)*tiny; % replace 0s by tiny
Qx=prod(Qx,2);
Qx = Qx + (Qx==0)*tiny; % replace 0s by tiny
%%%%% Faut-il diviser par le nb de configurations possibles ? (sum => mean)
KLdiv = sum(Px.*log(Px./Qx));
%end
|