Files
tunmnlu/task_2/others-answer/omsa-main/ISYE-8803-OAN/hw5/bsplineSmoothDecompauto.m
louiscklaw 9035c1312b update,
2025-02-01 02:09:32 +08:00

164 lines
3.5 KiB
Matlab

function [yhat,a] = bsplineSmoothDecompauto(y,B,Ba,lambda,gamma,maxIter,errtol)
%% Smooth decomposition methods
%
%
% Parameters:
% -----------------
% y : Signal/image to be decomposed
% B : Basis for mean
% Ba : Basis for anomalies
% lambda : Smoothing Parameter, the algorithm will decide if empty
% gamma : Sparsity Parameter, the algorithm will decide if empty
% -----------------
% Output:
% -----------------
% yhat : mean
% a : Anomalies
% This code is created by Hao Yan? June 8th, 2017
% If you have any questions, please contact HaoYan@asu.edu
% Paper: Yan, Hao, Kamran Paynabar, and Jianjun Shi. "Anomaly detection in images with smooth background via smooth-sparse decomposition." Technometrics 59.1 (2017): 102-114.
%% Test & prepare the variables
%---
plus0 = @(x) (x>0).*x;
% default parameters setup
if nargin<7
errtol = 1e-6;
if nargin<6
maxIter = 20;
end
end
isAutoLambda = isempty(lambda);
isAutoGamma = isempty(gamma);
sizey = size(y);
ndim = sum(sizey~=1);
if ndim == 1
Lbs = 2*norm(Ba{1})^2;
X = zeros(size(Ba{1},2),1);
BetaA = zeros(size(Ba{1},2),1);
elseif ndim == 2
Lbs = 2*norm(Ba{1})^2*norm(Ba{2})^2;
X = zeros(size(Ba{1},2),size(Ba{2},2));
BetaA = zeros(size(Ba{1},2),size(Ba{2},2));
end
if numel(lambda) == 1
lambda = ones(ndim,1)*lambda;
end
SChange = 1e10;
H = cell(ndim,1);
a = zeros(size(y));
C = cell(ndim,1);
Z = cell(ndim,1);
for idim = 1:ndim
Li = sqrtm(B{idim}'*B{idim});
Li = Li + 1e-8*eye(size(Li));
Di = diff(eye(size(B{idim},2)),1);
[Ui,C{idim},~] = svd((Li')\(Di'*Di)/(Li));
Z{idim} = B{idim}/(Li')*Ui;
end
iIter = 0;
t = 1;
%
while SChange > errtol && iIter < maxIter
iIter = iIter + 1;
Sold = a;
BetaSold = BetaA;
told = t;
gcv = @(x) splinegcv(x,y,C,Z,0,[]);
if isAutoLambda && iIter==1
lambda = fminbnd(gcv,1e-2,1e3);
lambda = ones(ndim,1)*lambda;
end
% %
for idim = 1:ndim
H{idim} = Z{idim}*diag(1./(ones(size(C{idim},1),1) + lambda(idim)*diag(C{idim})))*Z{idim}';
end
if ndim == 1
yhat = H{1}*(y-a);
BetaSe = X + 2/Lbs*Ba{1}'*(y -Ba{1}*X - yhat);
elseif ndim == 2
yhat = H{1}*(y-a)*H{2};
BetaSe = X + 2/Lbs*Ba{1}'*(y -Ba{1}*X*Ba{2}' - yhat)*Ba{2};
end
maxYe = max(abs(BetaSe(:)));
%
if isAutoGamma && mod(iIter,5)==1
gamma = graythresh(abs(BetaSe)/maxYe)*maxYe*Lbs;
end
BetaA = wthresh(BetaSe,'h',gamma/Lbs); % change 'h' to 's' for softthresholding
if ndim == 1
a = Ba{1} *BetaA;
elseif ndim==2
a = Ba{1} *BetaA* Ba{2}';
end
t = (1+sqrt(1+4*told^2))/2;
if iIter==1
X = BetaA;
else
X = BetaA+(told-1)/t*(BetaA-BetaSold);
end
SChange = sum(sum(sum((a - Sold).^2)));
end
end
function [ GCVscore ] = splinegcv( lambda,Y,C,Z,nmiss,W )
% Estimate Generalized Cross-validation value
ndim = sum(size(Y)~=1);
H = cell(ndim,1);
dfi = zeros(ndim,1);
for idim = 1:ndim
%%
H{idim} = Z{idim}*diag(1./(ones(size(C{idim},1),1) + lambda*diag(C{idim})))*Z{idim}';
dfi(idim) = sum(1./(1+lambda*diag(C{idim})));
end
df = prod(dfi);
if ndim == 1
Yhat = H{1}*Y;
elseif ndim == 2
Yhat = H{1}*Y*H{2};
elseif ndim >= 3
Yhat = double(ttm(tensor(Y),H));
end
if(isempty(W))
RSS = sum(sum(sum((Y-Yhat).^2)));
else
RSS = sum(sum(sum((Y-Yhat).*W.*(Y-Yhat))));
end
n = numel(Y);
GCVscore = RSS/(n-nmiss)/(1-df/n)^2;
end