卷积神经网络(CNN)讲解及代码

本文重点介绍如何使用MATLAB的deeplearning toolbox实现卷积神经网络(CNN)。通过简化的代码示例和注释,适合已有一定CNN基础的读者。文章提供了从下载工具箱到运行示例代码的详细步骤,并推荐了相关资源帮助理解CNN的反向传播算法。
摘要由CSDN通过智能技术生成

相关文章:
1. 经典反向传播算法公式详细推导
2. 卷积神经网络(CNN)反向传播算法公式详细推导

网上有很多关于CNN的教程讲解,在这里我们抛开长篇大论,只针对代码来谈。本文用的是matlab编写的deeplearning toolbox,包括NN、CNN、DBN、SAE、CAE。在这里我们感谢作者编写了这样一个简单易懂,适用于新手学习的代码。由于本文直接针对代码,这就要求读者有一定的CNN基础,可以参考Lecun的Gradient-Based Learning Applied to Document Recognitiontornadomeet的博文
首先把Toolbox下载下来,解压缩到某位置。然后打开Matlab,把文件夹内的util和data利用Set Path添加至路径中。接着打开tests文件夹的test_example_CNN.m。最后在文件夹CNN中运行该代码。

下面是test_example_CNN.m中的代码及注释,比较简单。

load mnist_uint8;  %读取数据

% 把图像的灰度值变成0~1,因为本代码采用的是sigmoid激活函数
train_x = double(reshape(train_x',28,28,60000))/255;
test_x = double(reshape(test_x',28,28,10000))/255;
train_y = double(train_y');
test_y = double(test_y');

%% 卷积网络的结构为 6c-2s-12c-2s 
% 1 epoch 会运行大约200s, 错误率大约为11%。而 100 epochs 的错误率大约为1.2%。

rand('state',0) %指定状态使每次运行产生的随机结果相同

cnn.layers = {
    struct('type', 'i') % 输入层
    struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) % 卷积层
    struct('type', 's', 'scale', 2) % pooling层
    struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) % 卷积层
    struct('type', 's', 'scale', 2) % pooling层
};


opts.alpha = 1;  % 梯度下降的步长
opts.batchsize = 50; % 每次批处理50张图
opts.numepochs = 1; % 所有图片循环处理一次

cnn = cnnsetup(cnn, train_x, train_y); % 初始化CNN
cnn = cnntrain(cnn, train_x, train_y, opts); % 训练CNN

[er, bad] = cnntest(cnn, test_x, test_y); % 测试CNN

%plot mean squared error
figure; plot(cnn.rL);
assert(er<0.12, 'Too big error');

下面是cnnsetup.m中的代码及注释。

function net = cnnsetup(net, x, y)
    assert(~isOctave() || compare_versions(OCTAVE_VERSION, '3.8.0', '>='), ['Octave 3.8.0 or greater is required for CNNs as there is a bug in convolution in previous versions. See http://savannah.gnu.org/bugs/?39314. Your version is ' myOctaveVersion]);  %判断版本
    inputmaps = 1;  % 由于网络的输入为1张特征图,因此inputmaps为1
    mapsize = size(squeeze(x(:, :, 1)));  %squeeze():除去x中为1的维度,即得到28*28

    for l = 1 : numel(
好的,下面我将对上面的代码逐段进行讲解。 首先,我们引入了PyTorch需要的库: ```python import torch import torch.nn as nn import torch.optim as optim import torchvision.datasets as datasets import torchvision.transforms as transforms ``` 其中,`torch`是PyTorch的核心库,提供了张量操作和自动微分功能;`nn`是PyTorch的神经网络库,提供了各种神经网络层和损失函数;`optim`是PyTorch的优化器库,提供了各种优化算法;`datasets`和`transforms`是PyTorch的数据处理库,提供了各种数据集和数据预处理方法。 接下来,我们定义了CNN模型: ```python class ConvNet(nn.Module): def __init__(self): super(ConvNet, self).__init__() self.conv1 = nn.Conv2d(3, 16, 3, padding=1) self.pool1 = nn.MaxPool2d(2) self.conv2 = nn.Conv2d(16, 32, 3, padding=1) self.pool2 = nn.MaxPool2d(2) self.conv3 = nn.Conv2d(32, 64, 3, padding=1) self.pool3 = nn.MaxPool2d(2) self.fc1 = nn.Linear(64 * 4 * 4, 256) self.fc2 = nn.Linear(256, 10) def forward(self, x): x = self.pool1(torch.relu(self.conv1(x))) x = self.pool2(torch.relu(self.conv2(x))) x = self.pool3(torch.relu(self.conv3(x))) x = x.view(-1, 64 * 4 * 4) x = torch.relu(self.fc1(x)) x = self.fc2(x) return x ``` 这个模型包含三个卷积层和两个全连接层。在`__init__`方法中,我们定义了各个层的参数,如输入通道数、输出通道数、卷积核大小、填充等。在`forward`方法中,我们定义了模型的前向传播过程,即各层的输入输出关系。其中,`relu`是激活函数,`MaxPool2d`是池化层,`Linear`是全连接层,`view`是将多维张量转换成一维张量的方法。 然后,我们加载了CIFAR-10数据集: ```python train_dataset = datasets.CIFAR10(root='data/', train=True, transform=transforms.ToTensor(), download=True) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True) test_dataset = datasets.CIFAR10(root='data/', train=False, transform=transforms.ToTensor(), download=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False) ``` 这里使用了`datasets.CIFAR10`方法加载了CIFAR-10数据集,并使用了`transforms.ToTensor`方法将数据转换成PyTorch张量格式。然后,使用`torch.utils.data.DataLoader`方法将数据集分成多个批次进行训练和测试。 接着,我们定义了损失函数和优化器: ```python model = ConvNet() criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) ``` 这里使用了`nn.CrossEntropyLoss`作为损失函数,这是一个适用于多分类问题的损失函数。使用了`optim.Adam`作为优化器,这是一种常用的自适应学习率优化算法。 然后,我们进行模型训练: ```python for epoch in range(10): for i, (images, labels) in enumerate(train_loader): optimizer.zero_grad() outputs = model(images) loss = criterion(outputs, labels) loss.backward() optimizer.step() if (i+1) % 100 == 0: print(f'Epoch [{epoch+1}/{10}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item():.4f}') ``` 这里进行了10个epoch的训练。每个epoch中,我们使用`enumerate`方法对训练数据集进行批次循环,获取每个批次的图像数据和标签数据。然后,将图像数据送入模型中进行前向传播,计算损失函数并进行反向传播,最后使用优化器更新模型参数。在每个epoch的训练过程中,每100个批次打印一次损失值。 最后,我们进行模型测试: ```python with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the model on the test images: {:.2f}%'.format(100 * correct / total)) ``` 这里使用了`torch.no_grad`上下文管理器,表示在测试过程中不需要计算梯度。然后,对测试数据集进行循环,计算模型的预测结果和真实标签之间的正确率。最后,打印模型在测试数据集上的准确率。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值