近红外高光谱特征波段提取算法

近红外高光谱特征波段提取算法 近红外高光谱特征波段提取算法高光谱数据这玩意儿就像个话痨每次采集动不动就几百个波段处理起来能把人整懵。咱今天聊聊怎么从这些光谱波段里揪出真正有用的主儿省得被数据量拖垮。特征波段提取这事儿说白了就是给数据脱衣服留下关键部位。先整点实战代码热热身。拿经典的SPA连续投影算法开刀这货擅长找互不相关的特征波段。上代码import numpy as np from sklearn.linear_model import LinearRegression def spa(X, y, n_selected): n_samples, n_features X.shape candidate list(range(n_features)) selected [] corr [np.abs(np.corrcoef(X[:,i], y)[0,1]) for i in candidate] first np.argmax(corr) selected.append(candidate[first]) candidate.remove(candidate[first]) for _ in range(n_selected-1): P [] # 投影向量存储 for j in candidate: X_proj X[:, j].reshape(-1,1) # 对已选波段做正交投影 for k in selected: proj_vec X[:,k].reshape(-1,1) reg LinearRegression().fit(proj_vec, X_proj) X_proj X_proj - reg.predict(proj_vec) P.append(np.linalg.norm(X_proj)) # 挑投影残差最大的 selected.append(candidate[np.argmax(P)]) candidate.remove(selected[-1]) return np.array(selected)这段代码有个骚操作——每次把候选波段往已选波段空间投影专治波段间的多重共线性。注意第17行的循环投影相当于在已选特征构成的空间里做残差筛选这样选出来的波段携带新信息量最大。不过时间复杂度是O(n²)数据量大了得悠着点用。近红外高光谱特征波段提取算法接下来看看CARS竞争性自适应重加权采样这算法模仿达尔文进化论通过自适应加权和蒙特卡罗采样筛选变量。核心代码如下def cars(X, y, N50): n_samples, n_vars X.shape coef_hist [] remain_idx np.arange(n_vars) for _ in range(N): # 蒙特卡罗采样 sample_idx np.random.choice(len(y), int(0.8*len(y))) X_sub X[sample_idx][:, remain_idx] y_sub y[sample_idx] # PLS回归计算权重 pls PLSRegression(n_components3) pls.fit(X_sub, y_sub) coef np.abs(pls.coef_.flatten()) coef_hist.append(coef) # 自适应指数衰减筛选 keep_num int(len(remain_idx) * 0.9) cutoff np.exp(-(_1)/N * 5) # 指数衰减阈值 coef_std np.std(coef) survival_idx np.where(coef cutoff*coef_std)[0] if len(survival_idx) keep_num: survival_idx np.argsort(-coef)[:keep_num] remain_idx remain_idx[survival_idx] return remain_idx这里有两个关键点第12行的指数衰减阈值控制筛选强度初期大刀阔斧砍变量后期精细调整第14行的标准差缩放让筛选标准自适应变化。注意采样时用了80%的数据这样既保持随机性又避免过拟合。不过要注意PLS组件数别设太高不然容易引入噪声。最后说说UVE无信息变量消除这货通过添加噪声变量来判定真实变量的重要性from scipy.stats import ttest_ind def uve(X, y, noise_ratio0.2): n_samples, n_vars X.shape # 添加随机噪声矩阵 noise np.random.randn(n_samples, int(n_vars*noise_ratio)) X_aug np.hstack([X, noise]) # 计算变量稳定性 coefs [] for _ in range(100): # 蒙特卡罗循环 idx np.random.choice(n_samples, n_samples//2) model LinearRegression().fit(X_aug[idx], y[idx]) coefs.append(model.coef_) # T检验筛选 real_vars [] for i in range(X_aug.shape[1]): stat, p ttest_ind([c[i] for c in coefs], np.zeros(len(coefs))) if p 0.05 and i n_vars: real_vars.append(i) return np.array(real_vars)这个算法的神来之笔是添加人工噪声作为参照系。第12行的蒙特卡罗采样配合T检验专门检测变量回归系数的稳定性。注意噪声变量的比例可以调数据噪声大时适当提高比例。但有个坑——可能把重要但波动大的变量误杀这时候得配合其他方法交叉验证。这几种方法各有利弊SPA适合快速筛选核心变量CARS在稳定性上更胜一筹UVE擅长去伪存真。实际项目里我常玩组合技——先用SPA粗筛再用CARS细选最后UVE补刀。不过要注意别陷入算法崇拜有时候物理化学背景知识选出来的波段比算法更靠谱毕竟光谱特征峰的位置不是随机分布的。