% function [OptWave] = CARS_Cloud(X,y,N,f,cv)
%%%%%%% input %%%%%%%
% X: 光谱矩阵(行样本数,列波长变量)
% y: 化学值
% f: 最大主成分数
% cv:交互验证数量
% N: 迭代次数
%%%%%%% output %%%%%%%
% OptWave:最优波长变量组合序号
%%
clear all
clc;
clear all;
X=load('C:\Users\admin\Desktop\X.mat');%导入mat类型文件
X=cell2mat(struct2cell(X));
Y=load('C:\Users\admin\Desktop\Y.mat');%导入mat类型文件
Y=cell2mat(struct2cell(Y));
if nargin < 3 & nargin ==2
N = 100;
f = 10;
cv = 10;
elseif nargin < 4 & nargin ==3
f = 10;
cv = 10;
else nargin < 5 & nargin ==4
cv = 10;
end
%% 基本参数设置
N = 100;
f = 10;
cv = 10;
p = 0.8;
[m,n] =size(X); % 提取光谱的行和列
a = (n/2)^(1/(N-1)); % 常数a
k = (1/(N-1))*(log(n/2)); % 常数k
cal_num = round(m*p); % 校正集数量
val_num = m - cal_num; % 验证集数量
b2 = 1:n; % 开始波长序号
x = X;
y=Y ;
D = [b2;X]; % 在吸光度矩阵上面加上波长序号
WaveData = []; % 每次选择的波长变量序号矩阵
Coeff = []; % 每次运行的系数矩阵
%% 迭代计算
h = waitbar(0,'正在迭代计算...');
WaveNum = [];
for i = 1:100
r(i) = a * exp(-1*k*i); % 波长点保留率
wave_num = round(r(i) * n); % 被保留的波长数量
WaveNum = [WaveNum;wave_num]; % 每次迭代保留波长序号
cal_index = randperm(m,cal_num); % 校正集序号
wave_index = b2(1:wave_num); % 选择的波长序号
xcal = x(cal_index,wave_index); % 校正集光谱
ycal = y(cal_index); % 校正集化学值
x = x(:,wave_index); % 更新校正集光谱阵
D = D(:,wave_index); % 更新带波长序号的光谱矩阵
d=D(1,:); % 每次选择的波长变量序号矩阵
wnum = n - wave_num ; % 没有被选择的波长变量数量
if wnum > 0
d = [d,zeros(1,wnum)]; % 没有被选择的数量后面补0
end
WaveData = [WaveData;d]; % 每次选择的波长变量序号矩阵
% 如果光谱波长点数量小于主成分数量,那么主成分数量等于波长点数量
if wave_num < f
f = wave_num ;
end
[xl,yl,xs,yl,beta] = plsregress(xcal,ycal,f);
b = abs(beta(2:end));
[b1,b2] = sort(b,'descend');
coef = beta(2:end);
coeff = coef(b2);
cb = coeff(1:wave_num);
if wnum > 0
cb = [cb;zeros(wnum,1)]; % 没有被选择的数量后面补0
end
Coeff = [Coeff,cb];
[rmsecv,press,rindex] = PC_Cross_Validation(xcal,ycal,f,cv); % 选择最佳主成分
[RMSECV(i)] = Cross_Validation(xcal,ycal,rindex,cv); % 计算交互验证标准偏差
waitbar(i/N,h);
end
close(h)
CoeffData = Coeff';
%% 按顺序将被选波长和回归系数进行排列
WAVE = []; % 波长矩阵按顺序排列
COEFF = []; % 回归系数矩阵按顺序排列
% 先按照每行排列,将被选择的变量序号放在行序号中,没有被选择的补0
for i = 1:size(WaveData,1)
wd = WaveData(i,:);
cd = CoeffData(i,:);
WD = zeros(1,length(wd));
CO = zeros(1,length(wd));
for j = 1:length(wd)
ind = find (wd == j);
if isempty(ind) == 1
WD (j) = 0; % 序号补0
CO (j) = 0; % 回归系数补0
else
WD (j) = wd(ind); % 不为0的放在自己序号上
CO (j) = cd(ind); % 不为0的放在自己序号上
end
end
WAVE = [WAVE;WD]; % 波长矩阵按顺序排列
COEFF = [COEFF;CO]; % 回归系数矩阵按顺序排列
end
%% 选择最优迭代次数
[MinSecv,MinIndex] = min(RMSECV); % 求最小RMSECV值
Optimal = WAVE(MinIndex,:);
[bochang,boindex] = find(Optimal ~= 0);
OptWave = boindex; % 最终波长变量组合
%% 画图
figure;
plot(1:N,WaveNum,'LineWidth',2)
xlabel('蒙特卡罗迭代次数')
ylabel('被选择的波长数量')
title(['最佳迭代次数:',num2str(MinIndex),'次'])
figure;
plot(1:N,RMSECV,'LineWidth',2)
xlabel('蒙特卡罗迭代次数')
ylabel('RMSECV')
figure;
plot(COEFF)
xlabel('蒙特卡罗迭代次数')
ylabel('各变量系数值')
xx = MinIndex;
yy = get(gca,'ylim');
hold on
plot([xx,xx],yy,'r-*','LineWidth',2)
%%
submatrix = zeros(75,21); %目标矩阵大小
for i = 1:21 %108指要选的变量数
submatrix(:,i) = X(:,OptWave(1,i));
end