如何在MATLAB中用前两个主成分绘制fitcsvm()结果并投影超平面
理解SvmModel.W的维度问题
你遇到的SvmModel.W是455×1而非预期的30×1,核心原因是Matlab的fitcsvm默认使用对偶形式的SMO求解器——这里的W其实是对偶解里的拉格朗日乘子(α系数),只有支持向量对应的α值非零,其余样本的α都是0。你想要的30×1权重向量w是原始特征空间的解,需要从对偶结果推导出来。
计算原始特征空间的w和b
对于线性SVM,原始权重向量w可以通过支持向量、对应标签和α系数计算得到,偏置b则可以直接从模型中提取:
% 提取支持向量、对应标签和有效α系数 sv = SvmModel.SupportVectors; % 支持向量,维度:支持向量数量×30 sv_y = SvmModel.Y(SvmModel.IsSupportVector); % 支持向量的标签 alpha = SvmModel.W(SvmModel.IsSupportVector); % 仅保留支持向量的α系数 % 计算原始特征空间的权重向量w(30×1) w = sv' * (alpha .* sv_y); % 获取模型的偏置b b = SvmModel.Bias;
这样就能得到你预期的30×1的w和1×1的b了。
将超平面投影到PCA的2D空间并绘制
你的PCA代码已经完成了数据的降维投影,接下来要把30维的超平面映射到前两个主成分的空间中:
- 首先明确PCA的转换关系:
score = (X - mu) * coeff,反过来原始特征x可以表示为x = mu + score * coeff'。 - 原始空间的超平面方程是
w'*(x - mu) + b = 0,代入x的表达式后可简化为:w'*(score * coeff') + b = 0 → (coeff * w)' * score + b = 0 - 提取前两个主成分的系数,计算投影后的权重向量
w_proj,再转换成2D空间的直线方程:
% 计算投影到前两个主成分的权重向量 w_proj = coeff(:,1:2)' * w; % 生成超平面在2D空间的点 s1_min = min(score(:,1)); s1_max = max(score(:,1)); s1_line = linspace(s1_min, s1_max, 100); % 生成x轴的采样点 s2_line = (-w_proj(1)*s1_line - b) / w_proj(2); % 计算对应的y轴值 % 绘制超平面 plot(s1_line, s2_line, 'k--', 'LineWidth', 1.5);
完整整合代码
把上述步骤加到你的原有代码中,最终完整代码如下:
[coeff, score, ~, ~, ~, mu]=pca(X); gscatter(score(:,1),score(:,2),Y,'br','.'); hold on; plot(score(SvmModel.IsSupportVector,1), score(SvmModel.IsSupportVector,2),'go'); % 计算原始特征空间的w和b sv = SvmModel.SupportVectors; sv_y = SvmModel.Y(SvmModel.IsSupportVector); alpha = SvmModel.W(SvmModel.IsSupportVector); w = sv' * (alpha .* sv_y); b = SvmModel.Bias; % 投影并绘制超平面 w_proj = coeff(:,1:2)' * w; s1_min = min(score(:,1)); s1_max = max(score(:,1)); s1_line = linspace(s1_min, s1_max, 100); s2_line = (-w_proj(1)*s1_line - b) / w_proj(2); plot(s1_line, s2_line, 'k--', 'LineWidth', 1.5); hold off; legend('Class 0','Class 1','Support Vectors','Hyperplane');
额外小技巧
如果你不想手动推导w,可以在调用fitcsvm时指定原始形式的求解器,直接得到30×1的权重向量:
SvmModel = fitcsvm(X,Y,'Solver','L2QP'); % 用原始形式求解,SvmModel.W直接是30×1的w
这种情况下后续的投影步骤完全一致,无需再计算w。
内容的提问来源于stack exchange,提问作者havakok
相关产品推荐
相关产品推荐

