samer@0
|
1 /*
|
samer@0
|
2 * Copyright (c) 2000, 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 import samer.core.*;
|
samer@0
|
12 import samer.maths.*;
|
samer@0
|
13 import samer.tools.*;
|
samer@0
|
14 import java.util.*;
|
samer@0
|
15
|
samer@0
|
16 /**
|
samer@0
|
17 Collect statistics about a vector: accumulates
|
samer@0
|
18 sums and sums of products, then computes mean
|
samer@0
|
19 and covariance.
|
samer@0
|
20
|
samer@0
|
21 This is NOT a model! Computing energies and probabilities
|
samer@0
|
22 directly from the first and second moments is horrible, since
|
samer@0
|
23 you need the inverse of the covariance matrix. You could,
|
samer@0
|
24 however, use this to train a Gaussian model.
|
samer@0
|
25 */
|
samer@0
|
26
|
samer@0
|
27 public class GaussianStats extends NullTask
|
samer@0
|
28 {
|
samer@0
|
29 VVector vector;
|
samer@0
|
30 VVector sumx;
|
samer@0
|
31 Matrix sumxx;
|
samer@0
|
32 int n, count;
|
samer@0
|
33 double [] _sumx, x;
|
samer@0
|
34 double [][] _sumxx;
|
samer@0
|
35 double [] sig;
|
samer@0
|
36
|
samer@0
|
37 public GaussianStats(VVector vec) throws Exception
|
samer@0
|
38 {
|
samer@0
|
39 n=vec.size();
|
samer@0
|
40 sumx = new VVector("t1",n); // first moment: sum
|
samer@0
|
41 sumxx = new Matrix("t2",n,n); // second moment: sum products
|
samer@0
|
42
|
samer@0
|
43 _sumx=sumx.array();
|
samer@0
|
44 _sumxx=sumxx.getArray();
|
samer@0
|
45 x=vec.array();
|
samer@0
|
46 vector=vec;
|
samer@0
|
47 sig= new double[n];
|
samer@0
|
48
|
samer@0
|
49 }
|
samer@0
|
50
|
samer@0
|
51 public void dispose() {
|
samer@0
|
52 sumx.dispose();
|
samer@0
|
53 sumxx.dispose();
|
samer@0
|
54 }
|
samer@0
|
55
|
samer@0
|
56 public void getMean(VVector mu) { getMean(mu.array()); mu.changed(); }
|
samer@0
|
57 public void getMean(double [] mu) { Mathx.mul(mu, _sumx, 1.0/count); }
|
samer@0
|
58 public void getCovariance(Matrix C) {
|
samer@0
|
59 // compute mean products
|
samer@0
|
60 C.assign(sumxx);
|
samer@0
|
61 C.timesEquals(1.0/count);
|
samer@0
|
62
|
samer@0
|
63 // subtract square mean from mean square
|
samer@0
|
64 double [][] _C=C.getArray();
|
samer@0
|
65
|
samer@0
|
66 for (int i=0; i<n; i++) {
|
samer@0
|
67 double tmp=_sumx[i]/count; // diagonal
|
samer@0
|
68 for (int j=0; j<i; j++) { // off diagonal
|
samer@0
|
69 _C[i][j] -= tmp*(_sumx[j]/count);
|
samer@0
|
70 _C[j][i] = _C[i][j];
|
samer@0
|
71 }
|
samer@0
|
72 _C[i][i] -= tmp*tmp;
|
samer@0
|
73 }
|
samer@0
|
74 C.changed();
|
samer@0
|
75 }
|
samer@0
|
76
|
samer@0
|
77 public void getCorrelation(Matrix R) {
|
samer@0
|
78 // compute mean products
|
samer@0
|
79 R.assign(sumxx);
|
samer@0
|
80 R.timesEquals(1.0/count);
|
samer@0
|
81
|
samer@0
|
82 double [][] _R=R.getArray();
|
samer@0
|
83
|
samer@0
|
84 // first get std devs and put 1s down diagonal
|
samer@0
|
85 for (int i=0; i<n; i++) {
|
samer@0
|
86 double tmp=_sumx[i]/count; // diagonal
|
samer@0
|
87 sig[i] = Math.sqrt(_R[i][i] - tmp*tmp);
|
samer@0
|
88 _R[i][i]=1;
|
samer@0
|
89 }
|
samer@0
|
90
|
samer@0
|
91 for (int i=0; i<n; i++) {
|
samer@0
|
92 double tmp=_sumx[i]/count;
|
samer@0
|
93 for (int j=0; j<i; j++) { // off diagonal
|
samer@0
|
94 _R[i][j] -= tmp*(_sumx[j]/count);
|
samer@0
|
95 _R[i][j] /= sig[i]*sig[j];
|
samer@0
|
96 _R[j][i] = _R[i][j];
|
samer@0
|
97 }
|
samer@0
|
98 }
|
samer@0
|
99 R.changed();
|
samer@0
|
100 }
|
samer@0
|
101
|
samer@0
|
102 public void reset() {
|
samer@0
|
103 Mathx.zero(_sumx);
|
samer@0
|
104 sumxx.zero(); count=0;
|
samer@0
|
105 }
|
samer@0
|
106
|
samer@0
|
107 public void starting() {}
|
samer@0
|
108 public void stopping() {}
|
samer@0
|
109 public void run()
|
samer@0
|
110 {
|
samer@0
|
111 Mathx.add(_sumx,x);
|
samer@0
|
112
|
samer@0
|
113 for (int i=0; i<n; i++) {
|
samer@0
|
114 double [] a=_sumxx[i];
|
samer@0
|
115 double k=x[i];
|
samer@0
|
116 for (int j=0; j<=i; j++) {
|
samer@0
|
117 a[j] += k*x[j];
|
samer@0
|
118 }
|
samer@0
|
119 }
|
samer@0
|
120 sumx.changed();
|
samer@0
|
121 sumxx.changed();
|
samer@0
|
122 count++;
|
samer@0
|
123 }
|
samer@0
|
124 }
|
samer@0
|
125
|