
简介这份资源面向机械故障诊断与模式识别方向的学习者和研究人员提供基于支持向量机SVM的故障诊断与分类预测完整Matlab源码。数据源自西储大学轴承诊断数据集并已完成特征提取可直接用于分类实验运行环境为Matlab2023适合具备一定机器学习基础、希望快速复现SVM分类流程的读者。压缩包共71个文件约1.31MB包含m脚本、mat数据文件、libsvm核心源码c、cpp、h、java、py等多语言实现、mexw64二进制文件及readme说明覆盖训练、预测、参数寻优与结果可视化等环节。目前已有153人学习下载。读者可借助完整工程结构理解SVM在轴承故障分类中的建模思路参考混淆矩阵绘制脚本与数据组织方式快速搭建自己的诊断实验并在此基础上调整核函数与参数以对比分类效果。1. 从一份轴承数据说起这套 SVM 源码到底能跑出什么西储大学轴承数据在故障诊断圈子里几乎是绕不开的公开数据集很多人拿它做特征提取之后下一步就卡在分类器上。这份资源给的就是那一步的完整落地一个基于 libsvm-3.3 的 Matlab 工程输入是已经提取好的特征数据data.mat输出是分类预测结果和混淆矩阵图1.png、2.png核心脚本是 SVM.m配套 zjyanseplotConfMat.m 负责画混淆矩阵。运行环境写的是 Matlab2023实测 2023a 及以上版本基本都能跑通。它解决的不是从振动信号开始做特征提取的问题而是特征已经有了怎么用支持向量机做故障诊断分类预测的问题。适合两类人一类是课程设计或毕设需要快速拿到可复现分类结果的另一类是已经做过特征工程、想找一个干净 SVM 基线做对比的。压缩包里 libsvm-3.3 是完整源码目录不是只给个 mex 文件这意味着你能看到 svm-train.c、svm-predict.c、svm-scale.c 这些底层实现想改核函数或者调参数都有得改。2. libsvm-3.3 在 Matlab 里的编译链路mex 到底怎么过2.1 为什么不是直接调 fitcsvmMatlab 自带的 fitcsvm 从 2015 年左右就开始逐步替代旧版 svmtrain但这份资源用的是 libsvm-3.3 的 Matlab 接口不是 Statistics Toolbox 里的 fitcsvm。两者差别不小libsvm 是台湾林智仁团队维护的 C 实现支持多分类one-vs-one、多种核函数、交叉验证而且跨平台一致性好fitcsvm 更贴近 Matlab 生态但多分类策略和参数命名跟 libsvm 不一样。选 libsvm 的理由很实际你在网上找到的绝大多数 SVM 故障诊断论文和代码用的都是 libsvm 接口参数是 -c、-g、-t 这一套。如果你后面要复现别人的结果或者要把代码移植到 Pythonlibsvm 也有 Python 接口用 libsvm 比 fitcsvm 省事。代价就是得先编译 mex 文件。2.2 编译前的目录确认libsvm-3.3 目录下有个 matlab 子目录里面是 make.m 和一堆 .c 文件。编译之前先确认三件事Matlab 的 mex 编译器配置好了运行 mex -setup 能看到 C 编译器、当前工作目录切到 libsvm-3.3\matlab、系统 PATH 里没有冲突的 libsvm 旧版本。% 切到 libsvm 的 matlab 接口目录 cd(libsvm-3.3/matlab); % 检查 mex 编译器是否可用 mex -setup C; % 执行编译生成 svmtrain.mexw64 / svmpredict.mexw64 make;make.m 里实际做的事是依次编译 svmtrain.c、svmpredict.c、svm_model_matlab.c 等文件链接 libsvm 的 svm.cpp。编译成功后当前目录会出现 svmtrain.mexw64 和 svmpredict.mexw64Windows 64 位或者 .mexa64Linux。如果报错 Cannot find compiler说明 mex 没配好先解决编译器问题再往下走。参数说明make.m 不带参数但如果你要指定编译器可以在 make 之前设置 mex -setup C 选好。编译产物跟 Matlab 版本绑定2023a 编译出来的 mex 文件在 2020b 上不一定能加载换版本要重新 make。2.3 把 libsvm 路径加进搜索路径编译完只是第一步SVM.m 要能调到 svmtrain 和 svmpredict得把 libsvm-3.3\matlab 加到 Matlab 的搜索路径里。常见做法是在 SVM.m 开头用 addpath 临时加或者用 pathtool 永久加。% 在 SVM.m 开头加路径避免每次手动设置 addpath(genpath(libsvm-3.3/matlab)); % 验证接口可用 which svmtrain which svmpredict如果 which svmtrain 返回的是空或者指向了别的工具箱说明路径没加对或者被同名函数覆盖了。Matlab 旧版本自带 svmtrainStatistics Toolbox会跟 libsvm 的 svmtrain 冲突。解决办法是确保 libsvm 路径在搜索路径最前面或者用 rehash toolboxcache 刷新缓存。3. 从 data.mat 到混淆矩阵SVM.m 的完整执行链路3.1 数据加载与标签格式data.mat 里存的是西储大学轴承数据经过特征提取后的特征矩阵和标签。libsvm 对输入格式有硬性要求特征矩阵是 m×n 的 double 矩阵m 个样本n 个特征标签是 m×1 的向量且标签必须是整数或者能转成整数的数值。如果标签是字符串比如 Normal、InnerRace得先转成数字编码。% 加载特征数据 load(data.mat); % 假设 data.mat 里有 X特征矩阵和 Y标签向量 % 检查维度是否匹配 assert(size(X,1) length(Y), 样本数与标签数不一致); % 如果标签是字符串转成数字 if iscell(Y) || ischar(Y) [Y_num, label_map] grp2idx(Y); Y Y_num; end % 归一化libsvm 官方建议把特征缩放到 [-1,1] 或 [0,1] [X_norm, ps] mapminmax(X, 0, 1); X_norm X_norm;这里有个容易翻车的点mapminmax 默认按行归一化而 libsvm 要求按列每个特征一列。所以上面先转置再归一化再转回来。如果你不做归一化特征量纲差异大的时候比如一个特征是 0.001 量级另一个是 1000 量级SVM 的核函数计算会被大量纲特征主导分类效果直接崩掉。libsvm 的 README 里专门有一节讲 scaling建议用 svm-scale 或者手动缩放到 [-1,1]。3.2 训练集/测试集划分与参数寻优SVM.m 里通常会用随机划分或者交叉验证来评估模型。libsvm 的 svmtrain 自带交叉验证选项-v 参数可以直接输出交叉验证准确率。但更常见的做法是自己划分训练集和测试集在训练集上做参数寻优再用测试集验证。% 随机划分70% 训练30% 测试 rng(42); % 固定随机种子保证可复现 n size(X_norm, 1); idx randperm(n); train_idx idx(1:round(0.7*n)); test_idx idx(round(0.7*n)1:end); X_train X_norm(train_idx, :); Y_train Y(train_idx); X_test X_norm(test_idx, :); Y_test Y(test_idx); % 用网格搜索找最优 c 和 g best_acc 0; best_c 1; best_g 1; for c 2.^(-5:2:15) for g 2.^(-15:2:5) cmd [-c , num2str(c), -g , num2str(g), -t 2 -q]; model svmtrain(Y_train, X_train, cmd); [pred, acc, ~] svmpredict(Y_test, X_test, model, -q); if acc(1) best_acc best_acc acc(1); best_c c; best_g g; end end end参数说明-c 是惩罚系数 C控制对误分类的容忍度C 越大越容易过拟合-g 是 RBF 核的 gamma控制单个样本的影响范围gamma 越大越容易过拟合-t 2 表示 RBF 核故障诊断里 RBF 核用得最多因为特征和类别边界通常是非线性的-q 是 quiet 模式不打印训练过程。网格搜索的范围 2^(-5:2:15) 和 2^(-15:2:5) 是 libsvm 官方 FAQ 里推荐的粗搜范围实际用的时候可以在这个范围里先粗搜再细搜。3.3 混淆矩阵可视化zjyanseplotConfMat.m 是画混淆矩阵的辅助函数输入是真实标签和预测标签输出是带颜色映射的混淆矩阵图。1.png 和 2.png 大概率就是不同参数或者不同核函数下的混淆矩阵截图。% 用最优参数训练最终模型 cmd [-c , num2str(best_c), -g , num2str(best_g), -t 2 -q]; model svmtrain(Y_train, X_train, cmd); % 在测试集上预测 [pred, acc, ~] svmpredict(Y_test, X_test, model, -q); % 画混淆矩阵 figure; zjyanseplotConfMat(Y_test, pred); title([Test Accuracy: , num2str(acc(1)), %]);混淆矩阵的对角线是正确分类的样本数非对角线是误分类。故障诊断里最怕的是把某类故障全部分错比如把内圈故障全判成外圈故障这时候混淆矩阵上会看到一整行或者一整列的非对角线数值特别大。看到这种情况先检查特征提取是不是有问题再考虑换核函数或者调参数。4. 避坑与排查跑 SVM 故障诊断时最容易翻车的五个地方4.1 现象svmtrain 报 Undefined function原因libsvm 的 mex 文件没编译或者路径没加对或者被 Matlab 自带的 svmtrain 覆盖了。解决先确认 libsvm-3.3\matlab 目录下有 svmtrain.mexw64 文件然后 which svmtrain 看指向哪里如果是空或者指向 toolbox用 addpath(genpath(libsvm-3.3/matlab)) 加路径再用 rehash toolboxcache 刷新。如果还是不行检查 Matlab 版本和 mex 文件是否匹配换版本要重新 make。4.2 现象训练准确率 99%测试准确率 60%原因过拟合。常见原因是 C 太大、gamma 太大或者特征维度远大于样本数。解决先把 C 和 gamma 的搜索范围调小比如 C 从 2^(-5) 到 2^5gamma 从 2^(-10) 到 2^0。如果还是过拟合考虑降维PCA 或者特征选择或者增加样本数。libsvm 的交叉验证选项 -v 可以帮你判断是不是过拟合如果交叉验证准确率远低于训练准确率基本就是过拟合。4.3 现象混淆矩阵里某一类全部预测错原因类别不平衡。西储大学数据里正常样本通常远多于故障样本如果直接训练SVM 会倾向于把样本判成多数类。解决用 libsvm 的 -w 参数给不同类别加权或者对多数类做欠采样、对少数类做过采样。libsvm 的 -wi 参数可以给第 i 类设置权重权重比通常设成类别样本数的反比。% 假设类别 1 有 100 个样本类别 2 有 20 个样本 % 给类别 2 更高的权重 cmd [-c , num2str(best_c), -g , num2str(best_g), ... -t 2 -w1 1 -w2 5 -q];4.4 现象归一化之后准确率反而下降了原因归一化把某些有物理意义的特征差异抹掉了或者归一化方式不对按行而不是按列。解决先确认归一化是按列做的。如果按列归一化之后效果还是差试试不做归一化或者换一种缩放方式比如 z-score 标准化。不是所有特征工程场景都适合 min-max 归一化有时候原始特征的量纲差异本身就是有信息量的。4.5 现象换了一台机器跑结果完全不一样原因随机种子没固定或者 Matlab 版本不同导致 mex 文件不兼容或者 libsvm 版本不同。解决在代码开头用 rng(42) 固定随机种子。换机器的时候重新 make 一遍 mex 文件。如果换了 libsvm 版本比如从 3.3 换到 3.24参数默认值和实现细节可能有变化最好保持版本一致。5. 进阶技巧用交叉验证选参数用决策值看置信度5.1 用 libsvm 自带的交叉验证做参数寻优前面用的是手动划分训练集/测试集做网格搜索更稳的做法是用交叉验证。libsvm 的 svmtrain 加 -v 参数会返回交叉验证准确率不用自己划分。% 用 5 折交叉验证做网格搜索 best_cv_acc 0; for c 2.^(-5:2:15) for g 2.^(-15:2:5) cmd [-c , num2str(c), -g , num2str(g), ... -t 2 -v 5 -q]; cv_acc svmtrain(Y, X_norm, cmd); if cv_acc best_cv_acc best_cv_acc cv_acc; best_c c; best_g g; end end end注意 -v 模式下 svmtrain 返回的是交叉验证准确率不是模型。找到最优参数之后再用全部数据训练最终模型。这样选出来的参数比手动划分更可靠尤其是样本量不大的时候。5.2 用决策值判断分类置信度svmpredict 的第三个返回值是决策值decision values可以拿来判断模型对每个样本的置信度。决策值绝对值越大模型越确信接近 0 的样本模型比较犹豫。[pred, acc, dec_values] svmpredict(Y_test, X_test, model); % 找出决策值绝对值最小的 10 个样本 [~, sort_idx] sort(abs(dec_values), ascend); uncertain_idx sort_idx(1:min(10, length(sort_idx))); % 这些样本是模型最不确定的可以重点检查 fprintf(最不确定的样本索引); disp(uncertain_idx);故障诊断里这个技巧很实用如果模型对某些样本特别不确定可能是这些样本的特征提取有问题或者它们本身就是边界样本。把这些样本挑出来单独看往往能发现数据里的异常。5.3 核函数选择的一个经验RBF 核-t 2是默认选择但不是唯一选择。如果特征维度很高比如几百维线性核-t 0可能效果更好而且训练速度快得多。如果特征有明显的周期性或者局部结构可以试试 sigmoid 核-t 3但 sigmoid 核在 libsvm 里不是正定核参数选不好容易出问题。我一般会先用线性核跑一遍看准确率能到多少。如果线性核和 RBF 核准确率差不多就用线性核因为可解释性更好训练也快。如果线性核明显差一截再上 RBF 核调参数。5.4 保存和加载模型训练好的模型可以保存下来下次直接加载不用重新训练。% 保存模型 save(svm_model.mat, model); % 下次加载 load(svm_model.mat); [pred, acc, ~] svmpredict(Y_test, X_test, model, -q);注意模型文件跟 libsvm 版本绑定换版本可能加载失败。如果要在不同机器之间迁移最好把训练数据和参数一起保存在新机器上重新训练。从那以后我每次跑 SVM 分类之前都强制走一遍归一化检查 → 参数粗搜 → 交叉验证 → 混淆矩阵这四步少一步都可能翻车。希望帮到你。本文还有配套的精品资源点击获取