Mercurial > forge
changeset 8899:1106a98d5bbd octave-forge
Initial commit.
author | asnelt |
---|---|
date | Mon, 14 Nov 2011 14:47:03 +0000 |
parents | 5a1af02811c1 |
children | eaef0b2ef2e8 |
files | main/statistics/INDEX main/statistics/inst/monotone_smooth.m |
diffstat | 2 files changed, 149 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/main/statistics/INDEX Sun Nov 13 21:14:56 2011 +0000 +++ b/main/statistics/INDEX Mon Nov 14 14:47:03 2011 +0000 @@ -45,8 +45,9 @@ combnk Experimental design fullfact ff2n -Linear regression +Regression anovan + monotone_smooth princomp regress Plots
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/statistics/inst/monotone_smooth.m Mon Nov 14 14:47:03 2011 +0000 @@ -0,0 +1,147 @@ +## Copyright (C) 2011 Nir Krakauer +## +## 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 3 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{yy} =} monotone_smooth (@var{x}, @var{y}, @var{h}) +## Produce a smooth monotone increasing approximation to a sampled functional dependence y(x) using a kernel method. +## (An Epanechnikov smoothing kernel is applied to y(x); this is integrated to yield the monotone increasing form. See Reference 1 for details.) +## +## @subheading Arguments +## +## @itemize @bullet +## @item +## @var{x} is a vector of values of the independent variable. +## +## @item +## @var{y} is a vector of values of the dependent variable, of the same size as @var{x}. For best performance, it is recommended that the @var{y} already be fairly smooth, e.g. by applying a kernel smoothing to the original values if they are noisy. +## +## @item +## @var{h} is the kernel bandwidth to use. If @var{h} is not given, a "reasonable" value is computed. +## +## @end itemize +## +## @subheading Return values +## +## @itemize @bullet +## @item +## @var{yy} is the vector of smooth monotone increasing function values at @var{x}. +## +## @end itemize +## +## @subheading Examples +## +## @example +## @group +## x = 0:0.1:10; +## y = (x .^ 2) + 3 * randn(size(x)); %typically non-monotonic from the added noise +## ys = ([y(1) y(1:(end-1))] + y + [y(2:end) y(end)])/3; %crudely smoothed via moving average, but still typically non-monotonic +## yy = monotone_smooth(x, ys); %yy is monotone increasing in x +## plot(x, y, '+', x, ys, x, yy) +## @end group +## +## @end example +## +## @subheading References +## +## @enumerate +## @item +## Holger Dette, Natalie Neumeyer and Kay F. Pilz (2006), A simple nonparametric estimator of a strictly monotone regression function, @cite{Bernoulli}, 12:469-490 +## @item +## Regine Scheder (2007), R Package 'monoProc', Version 1.0-6, @url{http://cran.r-project.org/web/packages/monoProc/monoProc.pdf} (The implementation here is based on the monoProc function mono.1d) +## @end enumerate +## @end deftypefn + +## Author: Nir Krakauer <nkrakauer@ccny.cuny.edu> +## Description: Nonparametric monotone increasing regression + +function yy = monotone_smooth(x, y, h) + +if nargin < 2 || ~isnumeric(x) || ~isnumeric(y) + print_usage (); +endif + +n = numel(x); + +%reshape x to be a vector +x = x(:); + +%set filter bandwidth at a reasonable default value, if not specified +if nargin < 3 || ~isscalar(h) + s = std(x); + h = s / (n^0.2); +end + +x_min = min(x); +x_max = max(x); + +y_min = min(y); +y_max = max(y); + +%transform range of x to [0, 1] +xl = (x - x_min) / (x_max - x_min); + +yy = ones(size(y)); + +%Epanechnikov smoothing kernel (with finite support) +%K_epanech_kernel = @(z) (3/4) * ((1 - z).^2) .* (abs(z) < 1); + + +K_epanech_int = @(z) mean(((abs(z) < 1)/2) - (3/4) * (z .* (abs(z) < 1) - (1/3) * (z.^3) .* (abs(z) < 1)) + (z < -1)); + +%integral of kernels up to t +monotone_inverse = @(t) K_epanech_int((y - t) / h); + + + +%find the value of the monotone smooth function at each point in x +niter_max = 150; %maximum number of iterations for estimating each value (should not be reached in most cases) +for l = 1:n + + tmax = y_max; + tmin = y_min; + wmin = monotone_inverse(tmin); + wmax = monotone_inverse(tmax); + if (wmax == wmin) + yy(l) = tmin; + else + wt = xl(l); + iter_max_reached = 1; + for i = 1:niter_max + wt_scaled = (wt - wmin) / (wmax - wmin); + tn = tmin + wt_scaled * (tmax - tmin) ; + wn = monotone_inverse(tn); + wn_scaled = (wn - wmin) / (wmax - wmin); + %if (abs(wt-wn) < 1E-4) || (tn < (y_min-0.1)) || (tn > (y_max+0.1)) %%criterion for break in the R code -- replaced by the following line to hopefully be less dependent on the scale of y + if (abs(wt_scaled-wn_scaled) < 1E-4) || (wt_scaled < -0.1) || (wt_scaled > 1.1) + iter_max_reached = 0; + break + end + if wn > wt + tmax = tn; + wmax = wn; + else + tmin = tn; + wmin = wn; + end + end + if iter_max_reached + warning(['at x = ' num2str(x(l)) ', maximum number of iterations reached without convergence; approximation may not be optimal']) + end + yy(l) = tmin + (wt - wmin) * (tmax - tmin) / (wmax - wmin); + end +end + + +