当前位置: 首页 > article >正文

CNN分类-卷积神经网络(Convolutional Neural Network)

CNN分类-卷积神经网络(Convolutional Neural Network)

源代码

CNN分类的用途介绍

什么是卷积神经网络(CNN)?

卷积神经网络(Convolutional Neural Network,简称CNN)是一种深度学习模型,特别擅长处理具有网格结构的数据,如图像。CNN通过卷积层、池化层和全连接层等结构,能够自动提取数据中的空间特征,广泛应用于计算机视觉和图像处理领域。

CNN的主要用途和应用场景

  1. 图像分类

    • 应用示例:识别和分类图像中的物体,如猫、狗、车辆等。
    • 解释:通过学习图像中的特征,CNN能够将图像准确分类到不同的类别中。
  2. 目标检测

    • 应用示例:在图像中定位并识别多个物体,如自动驾驶中的行人和车辆检测。
    • 解释:CNN能够识别图像中不同物体的位置和类别,实现精确的目标检测。
  3. 图像分割

    • 应用示例:将图像分割成不同的区域,如医学影像中的器官分割。
    • 解释:CNN通过像素级的分类,实现对图像的精细分割。
  4. 人脸识别

    • 应用示例:识别和验证个人身份,如手机解锁、安防监控。
    • 解释:CNN能够提取人脸特征,实现高准确度的人脸识别和验证。
  5. 图像生成

    • 应用示例:生成逼真的图像,如生成对抗网络(GAN)中的图像合成。
    • 解释:CNN能够学习图像的分布特征,生成高质量的新图像。
  6. 视频分析

    • 应用示例:视频内容识别、行为分析、异常检测。
    • 解释:CNN结合时间序列分析,能够处理和分析视频中的动态信息。
  7. 医疗影像分析

    • 应用示例:自动检测癌症、分析X光片和MRI图像。
    • 解释:CNN能够辅助医生快速、准确地分析医疗影像,提升诊断效率和准确性。
  8. 自动驾驶

    • 应用示例:环境感知、路径规划、障碍物检测。
    • 解释: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_class
    mid_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 == 1
    figure
    cm_train = confusionchart(T_train, T_sim1); % 绘制训练集混淆矩阵
    cm_train.Title = '训练集混淆矩阵';
    cm_train.ColumnSummary = 'column-normalized'; % 列归一化显示
    cm_train.RowSummary = 'row-normalized';       % 行归一化显示
        
    figure
    cm_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_trainP_test)及目标输出(T_trainT_test)。
5. 划分数据集
for i = 1 : num_class
    mid_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_trainT_train中。
    • 测试集输入特征和目标输出分别存储在P_testT_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 )';
  • 功能
    • 使用mapminmax函数将输入特征归一化到[0,1]范围,提升训练效果。
    • 使用相同的归一化参数处理测试集输入特征。
    • 将类别标签转换为分类类型(categorical),并转置,适应分类任务的要求。
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 % 显示网格
  • 功能
    • 绘制训练集和测试集的真实值与预测值对比图,直观展示分类效果。
    • 在图形标题中显示分类准确率。
    • legend:添加图例,区分真实值和预测值。
    • xlabelylabel:设置X轴和Y轴标签。
    • title:设置图形标题,显示准确率。
    • grid on:显示网格,便于观察数据趋势。
18. 混淆矩阵
if flag_conusion == 1
    figure
    cm_train = confusionchart(T_train, T_sim1); % 绘制训练集混淆矩阵
    cm_train.Title = '训练集混淆矩阵';
    cm_train.ColumnSummary = 'column-normalized'; % 列归一化显示
    cm_train.RowSummary = 'row-normalized';       % 行归一化显示
        
    figure
    cm_test = confusionchart(T_test, T_sim2); % 绘制测试集混淆矩阵
    cm_test.Title = '测试集混淆矩阵';
    cm_test.ColumnSummary = 'column-normalized'; % 列归一化显示
    cm_test.RowSummary = 'row-normalized';       % 行归一化显示
end
  • 功能
    • 如果flag_conusion为1,则绘制训练集和测试集的混淆矩阵。
    • 混淆矩阵有助于评估分类器在不同类别上的表现,特别是对不平衡数据集的分类效果。
    • confusionchart:创建混淆矩阵图表,显示真实类别与预测类别之间的关系。
    • ColumnSummaryRowSummary:设置混淆矩阵的列和行的归一化显示,便于比较分类器在不同类别上的表现。

总结

通过上述代码,您可以使用Matlab实现一个基于卷积神经网络(CNN)的分类模型。详细的中文注释帮助您理解每一步的具体操作和实现逻辑。该CNN模型适用于各种分类任务,特别是在处理具有空间特征的数据(如图像)时表现出色。根据具体需求,您可以调整网络结构、卷积核大小、神经元数量和训练参数,以优化模型性能和适应不同的应用场景。


http://www.kler.cn/a/448260.html

相关文章:

  • 【Spring事务】深入浅出Spring事务从原理到源码
  • 信创技术栈发展现状与展望:机遇与挑战并存
  • 前端关于pptxgen.js个人使用介绍
  • 基于 uniapp 开发 android 播放 webrtc 流
  • Loki 微服务模式组件介绍
  • WeakAuras NES Script(lua)
  • 【C语言】倒序输出
  • uniapp input的触发事件
  • robots协议
  • 使用Python和OpenCV进行双目摄像头测距的详细教程及源代码
  • Hive SQL 查询所有函数
  • setTimeout 最小执行时间是多少
  • java.util.ConcurrentModificationException异常出现的原因及解决方法
  • 【python实现烟花】
  • 解锁 SSM 与 Vue 在新锐台球厅管理系统设计与实现中的融合密码
  • 【大语言模型】ACL2024论文-29 答案即所需:通过回答问题实现指令跟随的文本嵌入
  • 【多维DP】【准NOI难度】力扣3251. 单调数组对的数目 II
  • 爬虫代码中如何处理异常?
  • 【面试 - 遇到的问题】Vue 里 router-view 使用 key + 关闭页面后重新打开页面-获取的数据赋值到旧组件问题(钩子执行顺序)
  • oracle使用imp命令导入dmp文件
  • 方正畅享全媒体新闻采编系统 reportCenter.do Sql注入漏洞复现(附脚本)
  • Dalsa线阵CCD相机使用开发手册
  • EasyPoi 使用$fe:模板语法生成Word动态行
  • sass的用法
  • 36. Three.js案例-创建带光照和阴影的球体与平面
  • 四、使用langchain搭建RAG:金融问答机器人--构建web应用,问答链,带记忆功能