-
Notifications
You must be signed in to change notification settings - Fork 92
/
gpPosteriorMeanVar.m
119 lines (106 loc) · 3.5 KB
/
gpPosteriorMeanVar.m
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
function [mu, varsigma] = gpPosteriorMeanVar(model, X);
% GPPOSTERIORMEANVAR Mean and variances of the posterior at points given by X.
% FORMAT
% DESC returns the posterior mean and variance for a given set of
% points.
% ARG model : the model for which the posterior will be computed.
% ARG x : the input positions for which the posterior will be
% computed.
% RETURN mu : the mean of the posterior distribution.
% RETURN sigma : the variances of the posterior distributions.
%
% SEEALSO : gpCreate, gpPosteriorMeanCovar, gpPosteriorGradMeanVar
%
% COPYRIGHT : Neil D. Lawrence, 2005, 2006, 2009
% GP
model.m = gpComputeM(model);
if ~isfield(model, 'alpha')
model = gpComputeAlpha(model);
end
maxMemory = 1000000;
switch model.approx
case 'ftc'
chunkSize = ceil(maxMemory/model.N);
case {'dtc', 'dtcvar', 'fitc', 'pitc'}
chunkSize = ceil(maxMemory/model.k);
end
mu = zeros(size(X, 1), model.d);
if nargout > 1
varsigma = zeros(size(X, 1), model.d);
end
startVal = 1;
endVal = chunkSize;
if endVal>size(X, 1)
endVal = size(X, 1);
end
while startVal <= size(X, 1)
indices = startVal:endVal;
% Compute kernel for new point.
switch model.approx
case 'ftc'
KX_star = kernCompute(model.kern, model.X, X(indices, :));
case {'dtc', 'dtcvar', 'fitc', 'pitc'}
KX_star = kernCompute(model.kern, model.X_u, X(indices, :));
end
% Compute mean, using precomputed alpha vector.
if ~isfield(model, 'isMissingData') || ~model.isMissingData ...
| ~strcmp(model.approx, 'ftc')
mu(indices, :) = KX_star'*model.alpha;
else
for i = 1:model.d
mu(indices, i) = KX_star(model.indexPresent{i}, :)' ...
*model.alpha(model.indexPresent{i}, i);
end
end
% Compute variances if requried.
if nargout > 1
if ~isfield(model, 'isSpherical') || model.isSpherical
% Compute diagonal of kernel for new point.
diagK = kernDiagCompute(model.kern, X(indices, :));
switch model.approx
case 'ftc'
Kinvk = model.invK_uu*KX_star;
case {'dtc', 'dtcvar', 'fitc', 'pitc'}
Kinvk = (model.invK_uu - (1/model.beta)*model.Ainv)*KX_star;
end
varsig = diagK - sum(KX_star.*Kinvk, 1)';
if isfield(model, 'beta')
varsig = varsig + (1/model.beta);
end
varsigma(indices, :) = repmat(varsig, 1, model.d);
else
diagK = kernDiagCompute(model.kern, X(indices, :));
for i = 1:model.d
ind = model.indexPresent{i};
switch model.approx
case 'ftc'
Kinvk = model.invK_uu{i}*KX_star(ind, :);
otherwise
error(['Non-spherical not yet implemented for any approximation ' ...
'other than ''ftc''']);
end
varsigma(indices, i) = diagK - sum(KX_star(ind, :).*Kinvk, 1)';
end
end
end
% Rescale the mean
mu(indices,:) = mu(indices, :).*repmat(model.scale, length(indices), 1);
% Add the bias back in.
mu(indices, :) = mu(indices, :) + repmat(model.bias, length(indices), 1);
% If the mean function is present, add it it.
if isfield(model, 'meanFunction') && ~isempty(model.meanFunction)
mu(indices, :) = mu(indices, :) + modelOut(model.meanFunction, ...
X(indices, :));
end
% rescale the variances
if nargout > 1
varsigma(indices, :) = varsigma(indices, :).* ...
repmat(model.scale.*model.scale, length(indices), 1);
end
% Prepare for the next chunk.
startVal = endVal + 1;
endVal = endVal + chunkSize;
if endVal > size(X, 1)
endVal = size(X, 1);
end
end