CNN分类-卷积神经网络(Convolutional Neural Network)
源代码
CNN分类的用途介绍
什么是卷积神经网络(CNN)?
卷积神经网络(Convolutional Neural Network,简称CNN)是一种深度学习模型,特别擅长处理具有网格结构的数据,如图像。CNN通过卷积层、池化层和全连接层等结构,能够自动提取数据中的空间特征,广泛应用于计算机视觉和图像处理领域。
CNN的主要用途和应用场景
-
图像分类
-
目标检测
- 应用示例:在图像中定位并识别多个物体,如自动驾驶中的行人和车辆检测。
- 解释:CNN能够识别图像中不同物体的位置和类别,实现精确的目标检测。
-
图像分割
- 应用示例:将图像分割成不同的区域,如医学影像中的器官分割。
- 解释:CNN通过像素级的分类,实现对图像的精细分割。
-
人脸识别
- 应用示例:识别和验证个人身份,如手机解锁、安防监控。
- 解释:CNN能够提取人脸特征,实现高准确度的人脸识别和验证。
-
图像生成
- 应用示例:生成逼真的图像,如生成对抗网络(GAN)中的图像合成。
- 解释:CNN能够学习图像的分布特征,生成高质量的新图像。
-
视频分析
- 应用示例:视频内容识别、行为分析、异常检测。
- 解释:CNN结合时间序列分析,能够处理和分析视频中的动态信息。
-
医疗影像分析
- 应用示例:自动检测癌症、分析X光片和MRI图像。
- 解释:CNN能够辅助医生快速、准确地分析医疗影像,提升诊断效率和准确性。
-
自动驾驶
- 应用示例:环境感知、路径规划、障碍物检测。
- 解释:CNN用于处理车辆周围的视觉信息,实现自动驾驶系统的感知与决策。
CNN的优势
- 自动特征提取:无需手工设计特征,CNN能够自动学习和提取数据中的有用特征。
- 空间不变性:通过卷积和池化操作,CNN具有一定的平移不变性,能够识别不同位置的物体。
- 参数共享:卷积核在整个输入数据上共享参数,减少了模型的参数数量,提升了训练效率。
- 深层结构:多层的网络结构能够捕捉数据中的复杂模式和高层次特征。
CNN的局限性
- 计算资源需求高:深层CNN需要大量的计算资源和内存,训练时间较长。
- 对旋转和尺度变化敏感:虽然CNN具有一定的平移不变性,但对旋转和尺度变化仍然敏感。
- 需要大量标注数据:训练高性能的CNN通常需要大量的标注数据,获取和标注数据成本较高。
- 过拟合风险:深层模型容易在小数据集上过拟合,需要有效的正则化和数据增强技术。
总结
卷积神经网络(CNN)作为深度学习领域的核心模型,在图像处理、计算机视觉、医疗诊断、自动驾驶等多个领域展现出强大的性能。通过其独特的结构和自动特征提取能力,CNN能够高效、准确地处理和分析复杂的视觉数据。然而,随着技术的发展,如何优化CNN的结构、提升其泛化能力、减少计算资源消耗,仍然是研究和应用中的重要课题。
带有详细中文注释的Matlab代码
%% 初始化
clear % 清除工作区中的所有变量
close all % 关闭所有打开的图形窗口
clc % 清除命令窗口的内容
warning off % 关闭警告信息%% 读取数据
res = xlsread('数据集.xlsx'); % 从Excel文件中读取数据,存储在变量res中%% 分析数据
num_class = length(unique(res(:, end))); % 计算类别数,假设最后一列为类别标签
num_dim = size(res, 2) - 1; % 计算特征维度(总列数减去类别列)
num_res = size(res, 1); % 计算样本总数,每一行代表一个样本
num_size = 0.7; % 设置训练集占数据集的比例为70%
res = res(randperm(num_res), :); % 随机打乱数据集顺序(提高模型泛化能力)
% 如果不需要打乱数据,可以注释掉上行代码
flag_conusion = 1; % 标志位为1,启用混淆矩阵绘制(要求Matlab 2018及以上版本)%% 设置变量存储数据
P_train = []; % 初始化训练集输入特征
P_test = []; % 初始化测试集输入特征
T_train = []; % 初始化训练集目标输出
T_test = []; % 初始化测试集目标输出%% 划分数据集
for i = 1 : num_classmid_res = res((res(:, end) == i), :); % 提取当前类别的所有样本mid_size = size(mid_res, 1); % 当前类别的样本数量mid_tiran = round(num_size * mid_size); % 计算当前类别的训练样本数量(四舍五入)% 将当前类别的训练样本添加到训练集P_train = [P_train; mid_res(1: mid_tiran, 1: end - 1)]; % 训练集输入特征(除最后一列)T_train = [T_train; mid_res(1: mid_tiran, end)]; % 训练集目标输出(最后一列)% 将当前类别的测试样本添加到测试集P_test = [P_test; mid_res(mid_tiran + 1: end, 1: end - 1)]; % 测试集输入特征T_test = [T_test; mid_res(mid_tiran + 1: end, end)]; % 测试集目标输出
end%% 数据转置
P_train = P_train'; % 转置训练集输入特征,使每列代表一个样本
P_test = P_test'; % 转置测试集输入特征
T_train = T_train'; % 转置训练集目标输出
T_test = T_test'; % 转置测试集目标输出%% 得到训练集和测试样本个数
M = size(P_train, 2); % 训练集样本数量
N = size(P_test , 2); % 测试集样本数量%% 数据归一化
[P_train, ps_input] = mapminmax(P_train, 0, 1); % 将训练集输入特征归一化到[0,1]范围
P_test = mapminmax('apply', P_test, ps_input); % 使用相同的归一化参数处理测试集输入特征t_train = categorical(T_train)'; % 将训练集目标输出转换为分类类型,并转置
t_test = categorical(T_test )'; % 将测试集目标输出转换为分类类型,并转置%% 数据平铺
% 将数据平铺成1维数据是一种处理方式
% 也可以平铺成2维数据,以及3维数据,需要修改对应模型结构
% 但是应该始终和输入层数据结构保持一致
p_train = double(reshape(P_train, num_dim, 1, 1, M)); % 将训练集数据重塑为4D张量,适应CNN输入
p_test = double(reshape(P_test , num_dim, 1, 1, N)); % 将测试集数据重塑为4D张量,适应CNN输入%% 构造网络结构
layers = [imageInputLayer([num_dim, 1, 1]) % 输入层,输入尺寸为[num_dim, 1, 1]convolution2dLayer([2, 1], 16, 'Padding', 'same') % 卷积层,卷积核大小为2x1,生成16个卷积核,填充方式为'same'batchNormalizationLayer % 批归一化层,加速训练和稳定网络reluLayer % ReLU激活层,引入非线性maxPooling2dLayer([2, 1], 'Stride', [2, 1]) % 最大池化层,池化窗口大小为2x1,步长为[2, 1]convolution2dLayer([2, 1], 32, 'Padding', 'same') % 卷积层,卷积核大小为2x1,生成32个卷积核,填充方式为'same'batchNormalizationLayer % 批归一化层reluLayer % ReLU激活层fullyConnectedLayer(num_class) % 全连接层,输出神经元数量等于类别数softmaxLayer % Softmax层,将输出转换为概率分布classificationLayer]; % 分类层,计算分类损失%% 参数设置
options = trainingOptions('adam', ... % 使用Adam优化器'MaxEpochs', 500, ... % 最大训练次数为500'InitialLearnRate', 1e-3, ... % 初始学习率为0.001'L2Regularization', 1e-4, ... % L2正则化参数,防止过拟合'LearnRateSchedule', 'piecewise', ... % 学习率调度方式为分段'LearnRateDropFactor', 0.1, ... % 学习率下降因子为0.1'LearnRateDropPeriod', 400, ... % 每经过400个epoch,学习率下降'Shuffle', 'every-epoch', ... % 每个epoch后打乱数据集'ValidationPatience', Inf, ... % 关闭验证'Plots', 'training-progress', ... % 绘制训练过程图'Verbose', false); % 关闭详细训练信息输出%% 训练模型
net = trainNetwork(p_train, t_train, layers, options); % 使用训练集数据和定义的网络结构训练CNN模型%% 预测模型
t_sim1 = predict(net, p_train); % 使用训练集数据进行预测,得到预测概率
t_sim2 = predict(net, p_test ); % 使用测试集数据进行预测,得到预测概率%% 反归一化
% 注意:由于使用的是分类层,predict函数输出的是类别概率,因此无需反归一化
% 这里使用vec2ind可能不适用于categorical类型,可以直接转换为类别索引
T_sim1 = vec2ind(t_sim1'); % 将训练集预测概率转换为类别索引
T_sim2 = vec2ind(t_sim2'); % 将测试集预测概率转换为类别索引%% 性能评价
error1 = sum((T_sim1 == T_train)) / M * 100 ; % 计算训练集准确率
error2 = sum((T_sim2 == T_test )) / N * 100 ; % 计算测试集准确率%% 绘制网络分析图
analyzeNetwork(layers) % 绘制网络结构图,便于理解网络层级和参数%% 绘图
figure
plot(1: M, T_train, 'r-*', 1: M, T_sim1, 'b-o', 'LineWidth', 1) % 绘制训练集真实值与预测值对比图
legend('真实值', '预测值')
xlabel('预测样本')
ylabel('预测结果')
title({'训练集预测结果对比'; ['准确率=' num2str(error1) '%']}) % 设置图形标题,显示准确率
grid on % 显示网格figure
plot(1: N, T_test, 'r-*', 1: N, T_sim2, 'b-o', 'LineWidth', 1) % 绘制测试集真实值与预测值对比图
legend('真实值', '预测值')
xlabel('预测样本')
ylabel('预测结果')
title({'测试集预测结果对比'; ['准确率=' num2str(error2) '%']}) % 设置图形标题,显示准确率
grid on % 显示网格%% 混淆矩阵
if flag_conusion == 1figurecm_train = confusionchart(T_train, T_sim1); % 绘制训练集混淆矩阵cm_train.Title = '训练集混淆矩阵';cm_train.ColumnSummary = 'column-normalized'; % 列归一化显示cm_train.RowSummary = 'row-normalized'; % 行归一化显示figurecm_test = confusionchart(T_test, T_sim2); % 绘制测试集混淆矩阵cm_test.Title = '测试集混淆矩阵';cm_test.ColumnSummary = 'column-normalized'; % 列归一化显示cm_test.RowSummary = 'row-normalized'; % 行归一化显示
end
代码详细说明与注释
1. 初始化部分
clear
close all
clc
warning off
- 功能:清理工作环境,确保代码在干净的环境中运行。
clear
:清除所有变量,释放内存。close all
:关闭所有打开的图形窗口。clc
:清空命令窗口内容。warning off
:关闭所有警告信息,避免干扰输出。
2. 读取数据
res = xlsread('数据集.xlsx');
- 功能:从Excel文件中读取数据。
- 假设数据集位于“数据集.xlsx”文件中,每一行代表一个样本,最后一列为类别标签。
3. 分析数据
num_class = length(unique(res(:, end)));
num_dim = size(res, 2) - 1;
num_res = size(res, 1);
num_size = 0.7;
res = res(randperm(num_res), :);
flag_conusion = 1;
- 功能:
- 计算类别数(
num_class
),即数据集中不同类别的数量。 - 计算特征维度(
num_dim
),即数据集中除去类别标签的特征数量。 - 计算样本总数(
num_res
)。 - 设置训练集占数据集的比例为70%(
num_size
)。 - 随机打乱数据集顺序,增加模型的泛化能力。
- 设置标志位
flag_conusion
为1,表示启用混淆矩阵绘制。
- 计算类别数(
4. 设置变量存储数据
P_train = []; P_test = [];
T_train = []; T_test = [];
- 功能:初始化训练集和测试集的输入特征(
P_train
、P_test
)及目标输出(T_train
、T_test
)。
5. 划分数据集
for i = 1 : num_classmid_res = res((res(:, end) == i), :);mid_size = size(mid_res, 1);mid_tiran = round(num_size * mid_size);P_train = [P_train; mid_res(1: mid_tiran, 1: end - 1)];T_train = [T_train; mid_res(1: mid_tiran, end)];P_test = [P_test; mid_res(mid_tiran + 1: end, 1: end - 1)];T_test = [T_test; mid_res(mid_tiran + 1: end, end)];
end
- 功能:
- 按类别循环,将每个类别的数据按比例划分为训练集和测试集。
- 训练集输入特征和目标输出分别存储在
P_train
和T_train
中。 - 测试集输入特征和目标输出分别存储在
P_test
和T_test
中。
6. 数据转置
P_train = P_train';
P_test = P_test';
T_train = T_train';
T_test = T_test';
- 功能:将数据转置,使每列代表一个样本,符合Matlab神经网络工具箱的输入要求。
7. 得到训练集和测试样本个数
M = size(P_train, 2);
N = size(P_test , 2);
- 功能:获取训练集(
M
)和测试集(N
)的样本数量。
8. 数据归一化
[P_train, ps_input] = mapminmax(P_train, 0, 1);
P_test = mapminmax('apply', P_test, ps_input);t_train = categorical(T_train)';
t_test = categorical(T_test )';
- 功能:
9. 数据平铺
% 将数据平铺成1维数据是一种处理方式
% 也可以平铺成2维数据,以及3维数据,需要修改对应模型结构
% 但是应该始终和输入层数据结构保持一致
p_train = double(reshape(P_train, num_dim, 1, 1, M));
p_test = double(reshape(P_test , num_dim, 1, 1, N));
- 功能:
- 将训练集和测试集的数据重塑为4D张量,适应CNN的输入要求。
- 这里将数据平铺成1维数据,形成[num_dim, 1, 1, M]和[num_dim, 1, 1, N]的形状。
10. 构造网络结构
layers = [imageInputLayer([num_dim, 1, 1]) % 输入层,输入尺寸为[num_dim, 1, 1]convolution2dLayer([2, 1], 16, 'Padding', 'same') % 卷积层,卷积核大小为2x1,生成16个卷积核,填充方式为'same'batchNormalizationLayer % 批归一化层,加速训练和稳定网络reluLayer % ReLU激活层,引入非线性maxPooling2dLayer([2, 1], 'Stride', [2, 1]) % 最大池化层,池化窗口大小为2x1,步长为[2, 1]convolution2dLayer([2, 1], 32, 'Padding', 'same') % 卷积层,卷积核大小为2x1,生成32个卷积核,填充方式为'same'batchNormalizationLayer % 批归一化层reluLayer % ReLU激活层fullyConnectedLayer(num_class) % 全连接层,输出神经元数量等于类别数softmaxLayer % Softmax层,将输出转换为概率分布classificationLayer]; % 分类层,计算分类损失
- 功能:定义卷积神经网络的各个层级结构。
- imageInputLayer:定义输入层,输入尺寸为[num_dim, 1, 1],适用于1维数据。
- convolution2dLayer:定义卷积层,卷积核大小为2x1,生成16个和32个卷积核,使用’same’填充保持输出尺寸。
- batchNormalizationLayer:批归一化层,帮助加速训练和稳定网络。
- reluLayer:ReLU激活层,引入非线性,提高模型表达能力。
- maxPooling2dLayer:最大池化层,池化窗口大小为2x1,步长为[2, 1],减少特征图尺寸。
- fullyConnectedLayer:全连接层,输出神经元数量等于类别数,用于最终分类。
- softmaxLayer:Softmax层,将全连接层的输出转换为概率分布。
- classificationLayer:分类层,计算分类损失并进行反向传播。
11. 参数设置
options = trainingOptions('adam', ... % 使用Adam优化器'MaxEpochs', 500, ... % 最大训练次数为500'InitialLearnRate', 1e-3, ... % 初始学习率为0.001'L2Regularization', 1e-4, ... % L2正则化参数,防止过拟合'LearnRateSchedule', 'piecewise', ... % 学习率调度方式为分段'LearnRateDropFactor', 0.1, ... % 学习率下降因子为0.1'LearnRateDropPeriod', 400, ... % 每经过400个epoch,学习率下降'Shuffle', 'every-epoch', ... % 每个epoch后打乱数据集'ValidationPatience', Inf, ... % 关闭验证'Plots', 'training-progress', ... % 绘制训练过程图'Verbose', false); % 关闭详细训练信息输出
- 功能:设置训练选项,定义训练过程中的参数和行为。
- ‘adam’:选择Adam优化器,加速收敛。
- ‘MaxEpochs’:设置最大训练次数为500。
- ‘InitialLearnRate’:设置初始学习率为0.001。
- ‘L2Regularization’:设置L2正则化参数为1e-4,防止模型过拟合。
- ‘LearnRateSchedule’:设置学习率调度方式为分段。
- ‘LearnRateDropFactor’:学习率下降因子为0.1。
- ‘LearnRateDropPeriod’:每经过400个epoch,学习率下降。
- ‘Shuffle’:每个epoch后打乱数据集,提升模型泛化能力。
- ‘ValidationPatience’:关闭验证,不进行早停策略。
- ‘Plots’:绘制训练过程图,实时监控训练进展。
- ‘Verbose’:关闭详细训练信息输出,减少控制台信息量。
12. 训练模型
net = trainNetwork(p_train, t_train, layers, options);
- 功能:使用训练集数据和定义的网络结构训练CNN模型。
p_train
:训练集输入数据。t_train
:训练集目标输出。layers
:定义的网络层级结构。options
:训练选项参数。
13. 预测模型
t_sim1 = predict(net, p_train);
t_sim2 = predict(net, p_test );
- 功能:
- 使用训练好的CNN模型对训练集和测试集进行预测,得到预测概率。
t_sim1
:训练集的预测概率。t_sim2
:测试集的预测概率。
14. 反归一化
% 注意:由于使用的是分类层,predict函数输出的是类别概率,因此无需反归一化
% 这里使用vec2ind可能不适用于categorical类型,可以直接转换为类别索引
T_sim1 = vec2ind(t_sim1'); % 将训练集预测概率转换为类别索引
T_sim2 = vec2ind(t_sim2'); % 将测试集预测概率转换为类别索引
- 功能:将预测概率转换为类别索引。
vec2ind
:将概率向量转换为类别索引,取概率最大的类别作为预测结果。- 注意:由于
predict
输出的是概率分布,需确保转换方法与输出格式匹配。
15. 性能评价
error1 = sum((T_sim1 == T_train)) / M * 100 ; % 计算训练集准确率
error2 = sum((T_sim2 == T_test )) / N * 100 ; % 计算测试集准确率
- 功能:
- 计算训练集和测试集的分类准确率(百分比)。
error1
:训练集准确率。error2
:测试集准确率。
16. 绘制网络分析图
analyzeNetwork(layers)
- 功能:绘制网络结构图,便于理解网络层级和参数设置。
17. 绘图
figure
plot(1: M, T_train, 'r-*', 1: M, T_sim1, 'b-o', 'LineWidth', 1) % 绘制训练集真实值与预测值对比图
legend('真实值', '预测值')
xlabel('预测样本')
ylabel('预测结果')
title({'训练集预测结果对比'; ['准确率=' num2str(error1) '%']}) % 设置图形标题,显示准确率
grid on % 显示网格figure
plot(1: N, T_test, 'r-*', 1: N, T_sim2, 'b-o', 'LineWidth', 1) % 绘制测试集真实值与预测值对比图
legend('真实值', '预测值')
xlabel('预测样本')
ylabel('预测结果')
title({'测试集预测结果对比'; ['准确率=' num2str(error2) '%']}) % 设置图形标题,显示准确率
grid on % 显示网格
- 功能:
18. 混淆矩阵
if flag_conusion == 1figurecm_train = confusionchart(T_train, T_sim1); % 绘制训练集混淆矩阵cm_train.Title = '训练集混淆矩阵';cm_train.ColumnSummary = 'column-normalized'; % 列归一化显示cm_train.RowSummary = 'row-normalized'; % 行归一化显示figurecm_test = confusionchart(T_test, T_sim2); % 绘制测试集混淆矩阵cm_test.Title = '测试集混淆矩阵';cm_test.ColumnSummary = 'column-normalized'; % 列归一化显示cm_test.RowSummary = 'row-normalized'; % 行归一化显示
end
- 功能:
总结
通过上述代码,您可以使用Matlab实现一个基于卷积神经网络(CNN)的分类模型。详细的中文注释帮助您理解每一步的具体操作和实现逻辑。该CNN模型适用于各种分类任务,特别是在处理具有空间特征的数据(如图像)时表现出色。根据具体需求,您可以调整网络结构、卷积核大小、神经元数量和训练参数,以优化模型性能和适应不同的应用场景。