about summary refs log tree commit diff
path: root/sourcecodes/bnt-master/BNT/CPDs/@mlp_CPD/update_ess.m
blob: 353a0b5c760c75b84d1adfa037cf584d5c7049f6 (plain)
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
% UPDATE_ESS Update the Expected Sufficient Statistics of a CPD (MLP)
% CPD = update_ess(CPD, family_marginal, evidence, node_sizes, cnodes, hidden_bitv)
%
% fmarginal = overall posterior distribution of self and its parents
% fmarginal(i1,i2...,ik,s)=prob(Pa1=i1,...,Pak=ik, self=s| X)
% 
% => 1) prob(self|Pa1,...,Pak)=fmarginal/prob(Pa1,...,Pak) with prob(Pa1,...,Pak)=sum{s,fmarginal}
%       [self estimation -> CPD.self_vals]
% 	  2) prob(Pa1,...,Pak) [SCG weights -> CPD.eso_weights]
%
% Hidden_bitv is ignored

% Written by Pierpaolo Brutti

if ~adjustable_CPD(CPD), return; end

dom = fmarginal.domain;                              
cdom = myintersect(dom, cnodes);                     
assert(~any(isemptycell(evidence(cdom))));           
ns(cdom)=1;

self = dom(end);                                  
ps=dom(1:end-1);                                     
dpdom=mysetdiff(ps,cdom);                            

dnodes = mysetdiff(1:length(ns), cnodes);            

ddom = myintersect(ps, dnodes);                      %
if isempty(evidence{self}),                          % if self is hidden in what follow we must 
    ddom = myintersect(dom, dnodes);                 % consider its dimension
end                                                  % 

odom = dom(~isemptycell(evidence(dom)));    
hdom = dom(isemptycell(evidence(dom)));              % hidden parents in domain
 
dobs = myintersect(ddom, odom);             
dvals = cat(1, evidence{dobs});             
ens = ns;                                            % effective node sizes              
ens(dobs) = 1;                              
                                            
dpsz=prod(ns(dpdom));
S=prod(ens(ddom));
subs = ind2subv(ens(ddom), 1:S);
mask = find_equiv_posns(dobs, ddom);
for i=1:length(mask),
    subs(:,mask(i)) = dvals(i);
end
supportedQs = subv2ind(ns(ddom), subs);

Qarity = prod(ns(ddom));
if isempty(ddom),                      
  Qarity = 1;                         
end                                
fullm.T = zeros(Qarity, 1);
fullm.T(supportedQs) = fmarginal.T(:);

% For dynamic (recurrent) net-------------------------------------------------------------
% ----------------------------------------------------------------------------------------
high=size(evidence,1);                                  % slice height
ss_ns=ns(1:high);                                       % single slice nodes sizes
pos=self;                                               %
slice_num=0;                                            %
while pos>high,                                         % 
    slice_num=slice_num+1;                              % find active slice
    pos=pos-high;                                       % pos=self posistion into a single slice
end                                                     %

last_dim=pos-1;                                         % 
if isempty(evidence{self}),                             % 
    last_dim=pos;                                       %
end                                                     % last_dim=last reshaping dimension      
reg=dom-slice_num*high;
dex=myintersect(reg(find(reg>=0)), [1:last_dim]);       %           
rs_dim=ss_ns(dex);                                      % reshaping dimensions

if slice_num>0,
    act_slice=[]; past_ancest=[];                       %
    act_slice=slice_num*high+[1:high];                  % recover the active slice nodes
    % past_ancest=mysetdiff(ddom, act_slice);
    past_ancest=mysetdiff(ps, act_slice);               % recover ancestors contained into past slices
    app=ns(past_ancest);
    rs_dim=[app(:)' rs_dim(:)'];                        %
end                                                     %
if length(rs_dim)==1, rs_dim=[1 rs_dim]; end            %
if size(rs_dim,1)~=1, rs_dim=rs_dim';    end            %

fullm.T=reshape(fullm.T, rs_dim);                       % reshaping the marginal

% ----------------------------------------------------------------------------------------
% ----------------------------------------------------------------------------------------

% X = cts parent, R = discrete self

% 1) observations vector -> CPD.parents_vals -------------------------------------------------
x = cat(1, evidence{cdom});

% 2) weights vector -> CPD.eso_weights -------------------------------------------------------
if isempty(evidence{self}) % R is hidden
    sum_over=length(rs_dim);
    app=sum(fullm.T, sum_over);    
    pesi=reshape(app,[dpsz,1]);
    clear app;
else
    pesi=reshape(fullm.T,[dpsz,1]);
end

assert(approxeq(sum(pesi),1));

% 3) estimate (if R is hidden) or recover (if R is obs) self'value----------------------------
if isempty(evidence{self})              % R is hidden    
    app=mk_stochastic(fullm.T);         % P(self|Pa1,...,Pak)=fmarginal/prob(Pa1,...,Pak)
    app=reshape(app,[dpsz ns(self)]);   % matrix size: prod{j,ns(Paj)} x ns(self)      
    r=app;
    clear app;
else
    r = zeros(dpsz,ns(self));
    for i=1:dpsz
        if pesi(i)~=0, r(i,evidence{self}) = 1; end
    end
end
for i=1:dpsz
    if pesi(i) ~=0, assert(approxeq(sum(r(i,:)),1)); end
end

CPD.nsamples = CPD.nsamples + 1;            
CPD.parent_vals(CPD.nsamples,:) = x(:)';
for i=1:dpsz
    CPD.eso_weights(CPD.nsamples,:,i)=pesi(i);
    CPD.self_vals(CPD.nsamples,:,i) = r(i,:); 
end