clc;
close all;
clear;
%% 参数设置
excelFilePath = 'C:\Users\Desktop\心音数据\训练数据.xlsx'; % Excel文件的路径
dataFolder = 'C:\Users\Desktop\心音数据\处理心音'; % 心音文件的文件夹路径
desiredSamplesPerLabel = 100; % 您希望从每个标签中挑选的样本数量
%% 步骤1: 从Excel读取数据(指定没有列名)
dataTable = readtable(excelFilePath, 'ReadVariableNames', false);
%% 提取文件名和标签(使用列索引)
fileNames = dataTable.Var1; % 第一列为文件名
labels = dataTable.Var2; % 第二列为标签
%% 初始化存储所有文件路径和对应标签的数组
paths = {}; % 存储所有文件路径
labelsArray = []; % 存储与paths对应的标签
%% 计算每个标签可用的最大样本数,并确定实际的样本数
maxSamplesLabel0 = sum(labels == 0);
maxSamplesLabel1 = sum(labels == 1);
actualSamplesPerLabel = min([desiredSamplesPerLabel, maxSamplesLabel0, maxSamplesLabel1]);
%% 对每个标签进行处理
for label = [0, 1]
% 筛选当前标签的所有文件名
labelFileNames = fileNames(labels == label);
% 随机选择实际的样本数
idx = randperm(length(labelFileNames), actualSamplesPerLabel);
selectedFileNames = labelFileNames(idx);
% 步骤2: 生成完整路径
fullPaths = fullfile(dataFolder, selectedFileNames);
% 将当前标签的路径添加到总路径数组中
paths = [paths; fullPaths];
% 生成与当前路径匹配的标签数组
currentLabels = repmat(label, length(fullPaths), 1);
% 将当前标签添加到总标签数组中
labelsArray = [labelsArray; currentLabels];
end
%% 验证结果
% disp(paths);
% disp(labelsArray);
%%
MFCCFeatures = collectMFCCFeatures(paths);
% 假设您的总数据集大小
totalSamples = size(MFCCFeatures, 1);
% 创建一个分区对象,指定分割比例
cv = cvpartition(totalSamples, 'HoldOut', 0.2); % 这里0.2意味着20%的数据将用作验证集
% 索引训练集和验证集
idxTrain = training(cv);
idxValidation = test(cv);
% 分割MFCC特征为训练集和验证集
XTrain = MFCCFeatures(idxTrain, :, :, :);
XValidation = MFCCFeatures(idxValidation, :, :, :);
% 分割标签为训练集和验证集,并转换为categorical类型
YTrain = categorical(labelsArray(idxTrain));
YValidation = categorical(labelsArray(idxValidation));
%%
layers = [
imageInputLayer([13 249 3]) % 输入层,输入尺寸匹配MFCC特征尺寸
convolution2dLayer(3, 8, 'Padding','same') % 卷积层
batchNormalizationLayer % 批标准化层
reluLayer % ReLU激活层
maxPooling2dLayer(2, 'Stride',2) % 最大池化层
convolution2dLayer(3, 16, 'Padding','same') % 另一个卷积层
batchNormalizationLayer % 批标准化层
reluLayer % ReLU激活层
maxPooling2dLayer(2, 'Stride',2) % 最大池化层
fullyConnectedLayer(64) % 全连接层
reluLayer % ReLU激活层
fullyConnectedLayer(2) % 全连接层,输出类别数量假设为2
softmaxLayer % Softmax激活层
classificationLayer]; % 分类输出层
% 设置训练选项
options = trainingOptions('sgdm', ...
'InitialLearnRate',0.01, ...
'MaxEpochs',10, ...
'Shuffle','every-epoch', ...
'ValidationData',{XValidation,YValidation}, ...
'ValidationFrequency',20, ...
'Verbose',false, ...
'Plots','training-progress');
% 训练CNN模型
% 注意:你需要将XTrain和YTrain替换为你的实际训练数据和标签
model = trainNetwork(XTrain,YTrain,layers,options);
% 使用训练好的模型进行预测或评估
% YPred = classify(model, XTest);
% accuracy = sum(YPred == YTest)/numel(YTest); % 计算准确率
我运行这个代码就会报错,错误提示如下
错误使用 trainNetwork
X 和 Y 中的观测值数量不一致。
出错 yiweixunlian (第 110 行)
model = trainNetwork(XTrain,YTrain,layers,options);
当我运行这段代码时就会报错,可是我已经检查过XTrain和YTrain的大小了,请问各位问题出在了哪儿啊?这是我其中涉及到的函数
function [mfcc, mfcc_delta, mfcc_delta2] = extractMFCCFeatures(audioFilePath)
% 读取音频文件
[audio_data, Fs] = audioread(audioFilePath);
% 计算MFCC特征
n_mfcc = 13;
% 提取MFCC特征
mfcc = melcepst(audio_data, Fs, 'M', n_mfcc);
% 计算一阶差分和二阶差分
mfcc_delta = diff(mfcc, 1, 1);
mfcc_delta2 = diff(mfcc, 2, 1);
% 为了保持维度一致性,对差分结果进行零填充
mfcc_delta = [zeros(1, size(mfcc, 2)); mfcc_delta]; % 在开始处填充零
mfcc_delta2 = [zeros(2, size(mfcc, 2)); mfcc_delta2]; % 在开始处填充两行零
end
function [features] = collectMFCCFeatures(paths)
numFiles = length(paths);
n_mfcc = 13; % 假设MFCC系数数量为13
maxFrames = 0; % 用于记录最大时间帧数
% 假设最大时间帧数,用于测试
maxFrames = 249; % 硬编码为249进行测试
% 初始化特征数组
features = zeros(numFiles, n_mfcc, maxFrames, 3); % [numSamples, n_mfcc, numFrames, 3]
% 再次遍历以填充特征数组
for i = 1:numFiles
[mfcc, mfcc_delta, mfcc_delta2] = extractMFCCFeatures(paths{i});
% 对差分结果进行零填充以匹配最大时间帧数
numCurrentFrames = size(mfcc, 1); % 当前MFCC的时间帧数
paddingSize = maxFrames - numCurrentFrames; % 需要填充的零的数量
% 根据需要填充零
paddedMFCC = [mfcc; zeros(paddingSize, n_mfcc)];
paddedDelta = [mfcc_delta; zeros(paddingSize, n_mfcc)];
paddedDelta2 = [mfcc_delta2; zeros(paddingSize, n_mfcc)];
% 填充特征数组,注意转置
features(i,:,1:maxFrames,1) = paddedMFCC';
features(i,:,1:maxFrames,2) = paddedDelta';
features(i,:,1:maxFrames,3) = paddedDelta2';
end
end
