samer@0
|
1 /*
|
samer@0
|
2 * Copyright (c) 2002, Samer Abdallah, King's College London.
|
samer@0
|
3 * All rights reserved.
|
samer@0
|
4 *
|
samer@0
|
5 * This software is provided AS iS and WITHOUT ANY WARRANTY;
|
samer@0
|
6 * without even the implied warranty of MERCHANTABILITY or
|
samer@0
|
7 * FITNESS FOR A PARTICULAR PURPOSE.
|
samer@0
|
8 */
|
samer@0
|
9
|
samer@0
|
10 package samer.models;
|
samer@0
|
11
|
samer@0
|
12 import samer.core.*;
|
samer@0
|
13 import samer.core.types.*;
|
samer@0
|
14 import samer.maths.*;
|
samer@0
|
15 import samer.maths.opt.*;
|
samer@0
|
16 import samer.tools.*;
|
samer@0
|
17
|
samer@0
|
18 /**
|
samer@0
|
19 Differential scaler: scales and offsets each element of a vector
|
samer@0
|
20 independently aiming to match a given prior model. This is
|
samer@0
|
21 like ICA using a diagonal weight matrix, with a 'zero-mean'
|
samer@0
|
22 normalisation built in, though it doesn't actually the mean to
|
samer@0
|
23 do this, but some statistic based on the prior model.
|
samer@0
|
24 */
|
samer@0
|
25
|
samer@0
|
26 public class AlignedGaussian extends AnonymousTask implements Model
|
samer@0
|
27 {
|
samer@0
|
28 private int n;
|
samer@0
|
29 private Vec x;
|
samer@0
|
30 private VVector s;
|
samer@0
|
31 private VVector w; // vector of multipliers
|
samer@0
|
32 private VDouble E;
|
samer@0
|
33 private VDouble logA;
|
samer@0
|
34
|
samer@0
|
35 double [] _x, _s, _g, _w, _m, phi;
|
samer@0
|
36
|
samer@0
|
37 public AlignedGaussian( Vec input) { this(input.size()); setInput(input); }
|
samer@0
|
38 public AlignedGaussian( int N)
|
samer@0
|
39 {
|
samer@0
|
40 n = N;
|
samer@0
|
41
|
samer@0
|
42 x = null;
|
samer@0
|
43 w = new VVector("w",n); w.addSaver();
|
samer@0
|
44 s = new VVector("s",n);
|
samer@0
|
45 E = new VDouble("E");
|
samer@0
|
46 logA = new VDouble("log|A|",0);
|
samer@0
|
47
|
samer@0
|
48
|
samer@0
|
49 _s = s.array();
|
samer@0
|
50 _w = w.array();
|
samer@0
|
51 _g = new double[n];
|
samer@0
|
52 phi = null;
|
samer@0
|
53 reset();
|
samer@0
|
54 }
|
samer@0
|
55
|
samer@0
|
56 public int getSize() { return n; }
|
samer@0
|
57 public VVector output() { return s; }
|
samer@0
|
58 public VVector weights() { return w; }
|
samer@0
|
59 public void setInput(Vec in) { x=in; _x=x.array(); }
|
samer@0
|
60 public void reset() { reset(1.0); }
|
samer@0
|
61 public void reset(double k) {
|
samer@0
|
62 Mathx.setAll(_w,k); w.changed();
|
samer@0
|
63 logA.set(-sumlog(_w));
|
samer@0
|
64 }
|
samer@0
|
65
|
samer@0
|
66 public String toString() { return "AlignedGaussian("+x+")"; }
|
samer@0
|
67 private static double sumlog(double [] x) {
|
samer@0
|
68 double S=0;
|
samer@0
|
69 for (int i=0; i<x.length; i++) S += Math.log(x[i]);
|
samer@0
|
70 return S;
|
samer@0
|
71 }
|
samer@0
|
72
|
samer@0
|
73 public void dispose()
|
samer@0
|
74 {
|
samer@0
|
75 logA.dispose();
|
samer@0
|
76 w.dispose();
|
samer@0
|
77 s.dispose();
|
samer@0
|
78 super.dispose();
|
samer@0
|
79 }
|
samer@0
|
80
|
samer@0
|
81 public void infer() { Mathx.mul(_s,_x,_w); s.changed(); }
|
samer@0
|
82 public void compute() {
|
samer@0
|
83 Mathx.mul(_g,_s,_w);
|
samer@0
|
84 E.set(0.5*Mathx.norm2(_s)+logA.value);
|
samer@0
|
85 }
|
samer@0
|
86
|
samer@0
|
87 public double getEnergy() { return E.value; }
|
samer@0
|
88 public double [] getGradient() { return _g; }
|
samer@0
|
89
|
samer@0
|
90 public Functionx functionx() {
|
samer@0
|
91 return new Functionx() {
|
samer@0
|
92 double [] s=new double[n];
|
samer@0
|
93
|
samer@0
|
94 public void dispose() {}
|
samer@0
|
95 public void evaluate(Datum P) { P.f=evaluate(P.x,P.g); }
|
samer@0
|
96 public double evaluate(double [] x, double [] g) {
|
samer@0
|
97 Mathx.mul(s,x,_w);
|
samer@0
|
98 Mathx.mul(g,s,_w);
|
samer@0
|
99 return 0.5*Mathx.norm2(s); // +logA.value;
|
samer@0
|
100 }
|
samer@0
|
101 };
|
samer@0
|
102 }
|
samer@0
|
103
|
samer@0
|
104 public void starting() { logA.set(-sumlog(_w)); }
|
samer@0
|
105 public void stopping() {}
|
samer@0
|
106 public void run() { infer(); compute(); }
|
samer@0
|
107 }
|
samer@0
|
108
|