samer@0
|
1 % azeromean - additive normalisation arrow
|
samer@0
|
2 %
|
samer@0
|
3 % azeromean ::
|
samer@0
|
4 % options {
|
samer@0
|
5 % offset :: real /0 ~'initial offsets';
|
samer@0
|
6 % rate :: nonneg/1e-7 ~'offset adaptation rate';
|
samer@0
|
7 % tension :: real /0 ~'smoothing strength';
|
samer@0
|
8 % }
|
samer@0
|
9 % -> arrow({[[N]]},{[[N]]},azeromean_state).
|
samer@0
|
10
|
samer@0
|
11 function o=azeromean(model,varargin)
|
samer@37
|
12 opts=options('offset',nan,'rate',1e-7,'tension',0,varargin{:});
|
samer@0
|
13 score=scorefn(model);
|
samer@0
|
14
|
samer@0
|
15 rate=opts.rate;
|
samer@0
|
16 if opts.tension>0
|
samer@0
|
17 tension=opts.tension;
|
samer@0
|
18 o=loop(@update_t,@(s)repmat_to(opts.offset,[s(1),1]));
|
samer@0
|
19 else
|
samer@0
|
20 o=loop(@update,@(s)repmat_to(opts.offset,[s(1),1]));
|
samer@0
|
21 end
|
samer@0
|
22
|
samer@0
|
23 function [y,offset]=update(x,offset)
|
samer@0
|
24 nans=isnan(offset);
|
samer@0
|
25 offset(nans)=x(nans);
|
samer@0
|
26 y = x-repmat(offset,1,size(x,2));
|
samer@42
|
27 delta = rate*sum(score(y),2);
|
samer@42
|
28 delta(~isfinite(delta))=0;
|
samer@42
|
29 offset = offset + delta;
|
samer@0
|
30 end
|
samer@0
|
31
|
samer@0
|
32 function [y,offset]=update_t(x,offset)
|
samer@0
|
33 nans=isnan(offset);
|
samer@0
|
34 offset(nans)=x(nans);
|
samer@0
|
35 w = size(x,2);
|
samer@0
|
36 y = x;
|
samer@0
|
37 for i=1:w
|
samer@0
|
38 y(:,i)=y(:,i)-offset;
|
samer@42
|
39 delta = rate*(score(y(:,i))+reg(offset));
|
samer@42
|
40 delta(~isfinite(delta))=0;
|
samer@42
|
41 offset = offset + delta;
|
samer@0
|
42 end
|
samer@0
|
43 end
|
samer@0
|
44
|
samer@0
|
45 function g=reg(h)
|
samer@0
|
46 zz=zeros(1,size(h,2));
|
samer@0
|
47 g=tension*[zz;diff(h,2,1);zz];
|
samer@0
|
48 end
|
samer@0
|
49 end
|