[ed273d]: inst / rgdtsmcore.m Maximize Restore History

Download this file

rgdtsmcore.m    169 lines (157 with data), 5.6 kB

  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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
## Copyright (C) 2008 Jonathan Stickel
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; If not, see <http://www.gnu.org/licenses/>.
## -*- texinfo -*-
##@deftypefn {Function File} {[@var{xhat}, @var{yhat}] =} rgdtsmcore (@var{x}, @var{y}, @var{d}, @var{lambda}, [@var{options}])
##
## Smooths @var{y} vs. @var{x} values by Tikhonov regularization.
## Although this function can be used directly, the more feature rich
## function "regdatasmooth" should be used instead. In addition to
## @var{x} and @var{y}, required input includes the smoothing derivative
## @var{d} and the regularization parameter @var{lambda}. The smooth
## curve is returned as @var{xhat}, @var{yhat}. The generalized cross
## validation variance @var{v} may also be returned.
##
## Currently supported input options are (multiple options are allowed):
##
##@table @code
## @item "gridx"
## use an equally spaced @var{xhat} vector for the smooth curve rather
## than @var{x}; this option is implied if either the "Nhat" or "range"
## options are used
## @item "Nhat", @var{value}
## number of equally spaced smoothed points (default = 100)
## @item "range", @var{value}
## two element vector [min,max] giving the desired output range of
## @var{xhat}; if not provided or if the provided range is less than
## the range of the data, the default is the min and max of @var{x}
## @item "weights", @var{vector}
## A vector of weighting values for fitting each point in the data.
## @item "relative"
## use relative differences for the goodnes of fit term. Conflicts
## with the "weights" option.
## @item "midpointrule"
## use the midpoint rule for the integration terms rather than a direct sum
##@end table
##
## References: Anal. Chem. (2003) 75, 3631; AIChE J. (2006) 52, 325
##@end deftypefn
function [xhat, yhat, v] = rgdtsmcore (x, y, d, lambda, varargin)
## options: gridx, Nhat, range, relative, midpointrule
## add an option to allow an arbitrary, monotonic xhat to be provided?
## Defaults if not provided
Nhat = 100;
range = [min(x),max(x)];
gridx = 0;
weights = 0;
relative = 0;
midpr = 0;
## parse the provided options
if ( length(varargin) )
for i = 1:length(varargin)
arg = varargin{i};
if ischar(arg)
switch arg
case "gridx"
gridx = 1;
case "Nhat"
gridx = 1;
Nhat = varargin{i+1};
case "range"
gridx = 1;
range = varargin{i+1};
case "weights"
weights = 1;
weightv = varargin{i+1};
case "relative"
relative = 1;
case "midpointrule"
midpr = 1;
otherwise
printf("Option '%s' is not implemented;\n", arg)
endswitch
endif
endfor
endif
if (gridx & midpr)
warning("midpointrule is not used if mapping to regular spaced x")
midpr = 0;
endif
if (weights & relative)
warning("relative differences is used if a weighting vector is provided")
endif
N = length(x);
## construct xhat, M, D
if (gridx)
xmin = min(range(1),min(x));
xmax = max(range(2),max(x));
dx = (xmax-xmin)/(Nhat-1);
xhat = (xmin:dx:xmax)';
## M is the mapping matrix yhat -> y
M = speye(Nhat);
idx = round((x - xmin) / dx) + 1;
M = M(idx,:);
## note: this D does not include dx^(-d), but scaled by delta below
D = diff(speye(Nhat),d);
else
Nhat = N;
xhat = x;
M = speye(N);
D = ddmat(x,d);
endif
## construct "weighting" matrices W and U
if (weights)
## use arbitrary weighting as provided
W = diag(weightv);
elseif (relative)
## use relative differences
Yinv = spdiag(1./y);
W = Yinv^2;
else
W = speye(N);
endif
## use midpoint rule integration (rather than simple sums)
if (midpr)
Bhat = spdiag(-ones(N-1,1),-1) + spdiag(ones(N-1,1),1);
Bhat(1,1) = -1;
Bhat(N,N) = 1;
B = 1/2*spdiag(Bhat*x);
if ( floor(d/2) == d/2 ) # test if d is even
dh = d/2;
Btilda = B(dh+1:N-dh,dh+1:N-dh);
else # d is odd
dh = ceil(d/2);
Btilda = B(dh:N-dh,dh:N-dh);
endif
W = W*B;
U = Btilda;
else
## W = W*speye(Nhat);
U = speye(Nhat-d);
endif
## Smoothing
delta = trace(D'*D)/Nhat^(2+d); # using "relative" or other weighting affects this!
yhat = (M'*W*M + lambda*delta^(-1)*D'*U*D) \ M'*W*y;
#[R,P,S] = splchol(M'*W*M + lambda*delta^(-1)*D'*U*D);
#yhat = S*(R'\(R\(S'*M'*W*y)));
## Computation of hat diagonal and cross-validation
if (nargout > 2)
## from AIChE J. (2006) 52, 325
## note: chol factorization does not help speed up the computation of H;
## should implement Eiler's partial H computation if many point smoothing by GCV is needed
##H = M*(S*(R'\(R\(S'*M'*W))));
H = M*((M'*W*M + lambda*delta^(-1)*D'*U*D)\M'*W);
## note: this is variance, squared of the standard error that Eilers uses
v = (M*yhat - y)'*(M*yhat - y)/N / (1 - trace(H)/N)^2;
endif
endfunction