使用MATLAB sequentialfs从94×263特征向量选特征时出错求助
解决sequentialfs结合二次判别分析时的SVD NaN/Inf错误
我遇到过类似的问题,虽然你的原始数据没有NaN/Inf,但在特征选择过程中,二次判别分析(QDA)的协方差矩阵计算很容易出现数值问题——尤其是当某个特征子集里存在线性相关特征,或者某类样本在部分特征上的方差趋近于0时,会导致SVD分解失败,抛出你看到的错误。下面是几个可行的解决思路:
1. 在评价函数中加入数值稳定性检查
可以在调用classify前先排查有问题的特征子集,避免错误中断,同时定位问题所在:
X = FEATUREVECTOR; y = LABELS; c = cvpartition(y,'k',10); opts = statset('display','iter'); fun = @(XT,yT,Xt,yt) ... begin % 检查每个类的协方差矩阵稳定性 classes = unique(yT); for cls = classes cls_idx = yT == cls; cls_cov = cov(XT(cls_idx,:)); % 条件数过大说明协方差矩阵接近奇异 if cond(cls_cov) > 1e10 warning('Class %s has nearly singular covariance matrix in current feature subset', num2str(cls)); return Inf; % 返回大误差,让sequentialfs跳过这个子集 end % 检查是否有方差为0的特征 cls_var = var(XT(cls_idx,:)); if any(cls_var < 1e-12) warning('Class %s has zero-variance feature in current subset', num2str(cls)); return Inf; end end % 正常计算分类错误数 pred = classify(Xt,XT,yT,'quadratic'); return sum(~strcmp(yt,pred)); end; [fs,history] = sequentialfs(fun,X,y,'cv',c,'options',opts);
2. 先改用线性判别分析验证
如果只是想先验证特征选择流程是否正常,可以把classify的判别类型改成'linear'(LDA),它的数值稳定性更好:
fun = @(XT,yT,Xt,yt)(sum(~strcmp(yt,classify(Xt,XT,yT,'linear'))));
如果线性判别能正常运行,那基本可以确定是QDA在特定特征子集上的数值问题。
3. 对特征做预处理
预处理能从根源减少数值问题:
- 标准化特征:把每个特征缩放到均值为0、方差为1,平衡不同特征的数值范围:
X = zscore(FEATUREVECTOR); % 标准化后再进行特征选择 y = LABELS; - 移除低方差特征:提前剔除那些方差几乎为0的特征,避免它们进入后续的特征子集:
var_threshold = 1e-6; feature_vars = var(FEATUREVECTOR); X = FEATUREVECTOR(:, feature_vars > var_threshold); y = LABELS;
4. 限制特征子集的大小
如果选择的特征数量过多,更容易出现协方差矩阵奇异的情况,可以用'maxfeatures'参数限制最大特征数:
[fs,history] = sequentialfs(fun,X,y,'cv',c,'options',opts,'maxfeatures',50); % 根据你的数据调整这个值
5. 使用正则化的二次判别分析
MATLAB的classify函数的QDA没有正则化,但可以用fitcdiscr代替,它支持正则化来处理奇异协方差矩阵:
fun = @(XT,yT,Xt,yt) ... begin % 带正则化的QDA,Regularization取值0-1,越大正则化越强 qda_model = fitcdiscr(XT,yT,'DiscrimType','quadratic','Regularization',0.1); pred = predict(qda_model,Xt); return sum(~strcmp(yt,pred)); end;
你可以调整Regularization参数来平衡模型稳定性和性能。
内容的提问来源于stack exchange,提问作者Sakib Mostafa
相关产品推荐
相关产品推荐

