在处理语音信号、心电图、振动监测等一维时序数据时,传统机器学习方法往往需要复杂的特征工程。而卷积神经网络(CNN)能够自动提取时域特征,大大简化了分类流程。下面我将分享用MATLAB实现一维CNN分类的完整流程,包含多个实际项目中积累的优化技巧。
对于采样率固定的时序信号,一维卷积核在时间维度上的滑动能够有效捕捉局部模式。相比二维CNN处理图像:
提示:虽然示例使用MATLAB的imageInputLayer处理一维数据,但本质上是通过[1×N]的二维卷积核实现一维卷积,这与PyTorch的Conv1d底层原理一致。
一维信号分类的首要挑战是数据格式统一。假设我们处理的是心电信号:
matlab复制% 生成模拟数据:200个正常样本(正弦波)和200个异常样本(添加噪声)
fs = 1000; % 采样率1kHz
t = 0:1/fs:1-1/fs; % 1秒时长
normal_data = sin(2*pi*5*t) + 0.1*randn(200,1000);
abnormal_data = sawtooth(2*pi*5*t) + 0.3*randn(200,1000);
% 添加标签(二分类)
labels = [ones(200,1); zeros(200,1)];
关键细节:
小样本情况下,可通过以下方法扩充数据:
matlab复制% 时移增强(最大偏移50个采样点)
augmented_data = zeros(size(normal_data));
for i = 1:size(normal_data,1)
shift = randi([-50 50]);
augmented_data(i,:) = circshift(normal_data(i,:), shift);
end
% 添加高斯噪声
noise_level = 0.05;
noisy_data = normal_data + noise_level*std(normal_data(:))*randn(size(normal_data));
实测发现,对ECG信号使用时移+噪声组合增强,可使测试准确率提升8-12%。
matlab复制layers = [
imageInputLayer([1 1000 1], 'Normalization', 'zscore')
convolution2dLayer([1 25], 32, 'Padding', 'same')
batchNormalizationLayer
leakyReluLayer(0.1) % 负区间斜率设为0.1
maxPooling2dLayer([1 5], 'Stride', [1 2])
convolution2dLayer([1 15], 64, 'Padding', 'same')
batchNormalizationLayer
leakyReluLayer(0.1)
maxPooling2dLayer([1 5], 'Stride', [1 2])
dropoutLayer(0.5) % 添加dropout防止过拟合
globalAveragePooling2dLayer
fullyConnectedLayer(2)
softmaxLayer
classificationLayer];
参数选择依据:
对于复杂信号分类,可尝试:
matlab复制% 残差连接
resLayers = [
convolution2dLayer([1 15], 64, 'Padding', 'same')
batchNormalizationLayer
reluLayer
convolution2dLayer([1 15], 64, 'Padding', 'same')
batchNormalizationLayer
additionLayer(2) % 残差相加
reluLayer];
lgraph = layerGraph();
lgraph = addLayers(lgraph, resLayers);
lgraph = connectLayers(lgraph, 'input', 'add/in2');
matlab复制options = trainingOptions('adam', ...
'InitialLearnRate', 0.001, ...
'LearnRateSchedule', 'piecewise', ...
'LearnRateDropPeriod', 10, ...
'LearnRateDropFactor', 0.7, ...
'MaxEpochs', 50, ...
'MiniBatchSize', 64, ...
'Shuffle', 'every-epoch', ...
'ValidationPatience', 5, ...
'ValidationFrequency', 30, ...
'Verbose', true, ...
'Plots', 'training-progress');
学习率设置经验:
matlab复制vars = [
optimizableVariable('InitialLearnRate', [1e-4, 1e-2], 'Transform', 'log')
optimizableVariable('NumFilters', [16, 128], 'Type', 'integer')
optimizableVariable('DropoutProb', [0.1, 0.8])];
results = bayesopt(@(params)trainCNN(params,train_x,train_y), vars, ...
'MaxTime', 60*60); % 优化1小时
优化后典型结果:
matlab复制[pred, scores] = classify(net, test_x);
% 计算混淆矩阵
confMat = confusionmat(test_y, pred);
disp(confMat);
% 绘制ROC曲线
[X,Y,T,AUC] = perfcurve(test_y, scores(:,2), 1);
figure; plot(X,Y);
xlabel('False Positive Rate');
ylabel('True Positive Rate');
title(['ROC Curve (AUC = ' num2str(AUC) ')']);
% 计算F1-score
precision = confMat(2,2)/(confMat(2,2)+confMat(1,2));
recall = confMat(2,2)/(confMat(2,2)+confMat(2,1));
F1 = 2*(precision*recall)/(precision+recall);
matlab复制new_net = compressNetwork(net, 'TargetFramework', 'TensorRT');
matlab复制codegen classify -args {ones(1,1000,1,'single')} -config:dll
matlab复制buffer = zeros(1,1000); % 环形缓冲区
while true
newData = acquireData(); % 获取新数据
buffer = [buffer(2:end), newData];
if mod(length(buffer),100)==0
pred = classify(net, reshape(buffer,[1,1000,1]));
end
end
现象:训练初期loss变为NaN
解决方法:
'GradientThreshold', 1'Normalization', 'zscore')现象:训练准确率>95%但验证集<70%
对策:
matlab复制layers = [
...
dropoutLayer(0.5)
l2Regularization(0.01) % L2正则化
...
];
将网络最后层修改为:
matlab复制fullyConnectedLayer(5) % 假设5分类
softmaxLayer
classificationLayer
数据标签需转换为1-5的整数类别,建议使用dummyvar函数生成one-hot编码。
在Intel i7-11800H + RTX3060平台上的实测数据:
| 网络类型 | 参数量 | 推理时延(ms) | 准确率 |
|---|---|---|---|
| 基础CNN | 28K | 1.2 | 92.5% |
| ResNet | 156K | 3.8 | 94.7% |
| 轻量CNN | 12K | 0.7 | 89.3% |
对于实时性要求高的场景(如>100Hz采样率),建议:
这个框架已成功应用于工业振动监测和语音指令识别项目,核心在于根据信号特性调整卷积核尺寸和网络深度。当处理特别长的序列(>10k采样点)时,可以先用STFT变换后再输入CNN,能显著降低计算量。