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

什么是卷积神经网络?

一、概念

        卷积神经网络(Convolutional Neural Network, CNN)可以说是最为经典的深度学习模型之一,特别适用于处理图像等具有网格结构的数据。CNN通过卷积层、池化层和全连接层的组合,能够自动提取数据的特征,并进行分类或回归任务。其中,CNN最核心的部件便是卷积层和池化层:

  • 卷积层(Convolutional Layer):卷积层是CNN的核心组件,通过卷积操作提取输入数据的局部特征。卷积操作使用多个卷积核(filter)在输入数据上滑动,生成特征图(feature map)。

  • 池化层(Pooling Layer):池化层用于对特征图进行下采样,减少数据的维度和计算量,同时保留重要特征。常见的池化操作有最大池化(Max Pooling)平均池化(Average Pooling)

二、核心算法

1、卷积操作

        卷积操作是通过卷积核(filter)在输入数据上滑动,进行点积运算,生成特征图(feature map)。卷积核是一组可训练的权重,用于提取输入数据的局部特征,每次滑动时计算卷积核与输入数据的局部区域的点积,并将结果存储在特征图中。卷积操作可以通过以下公式表示:

y(i, j) = \sum_{m=0}^{M-1}\sum_{n=0}^{N-1}x(i+m, j+n) \cdot w(m, n) + b

        其中,x是输入数据,w是卷积核,b是偏置,y是输出特征图,i 和 j 是特征图的坐标,M和N是卷积核的高度和宽度。假设输入的形状是n_{h} \times n_{w},卷积核大小为k_{h} \times k_{w},在不进行padding填充和stride步幅调整的情况下(后面会介绍这两个参数),输出形状为(n_{h}-k_{h}+1) \times (n_{w}-k_{w}+1)。一般来说,卷积操作的计算步骤如下:

  • 选择卷积核大小:选择卷积核的高度和宽度(例如,3x3或5x5)。
  • 滑动卷积核:将卷积核从输入数据的左上角开始,逐步向右和向下滑动,直到覆盖整个输入数据。
  • 计算点积:在每个位置,计算卷积核与输入数据的局部区域的点积,并加上偏置。
  • 存储结果:将点积结果存储在特征图的相应位置。

        上面这个图中的卷积操作,原始图像大小3*3,卷积核大小2*2,最后得到大小为2*2的特征图,计算过程如下:

  • 左上角特征值:0*0+1*1+3*2+4*3 = 19
  • 右上角特征值:1*0+2*1+4*2+5*3 = 25
  • 左下角特征值:3*0+4*1+6*2+7*3 = 37
  • 右下角特征值:4*0+5*1+7*2+8*3 = 43

2、池化操作

        池化操作用于对特征图进行下采样,减少数据的维度和计算量,同时保留重要特征。常见的池化操作有最大池化(Max Pooling)和平均池化(Average Pooling)。池化操作的基本原理是将池化窗口在特征图上滑动,在每个位置计算池化窗口内的最大值或平均值,并将结果存储在下采样后的特征图中。池化操作之后,输入层和输出层的大小关系计算与卷积操作一致。一般的池化计算步骤如下:

  • 选择池化窗口大小:选择池化窗口的高度和宽度(例如,2*2或3*3)。
  • 滑动池化窗口:将池化窗口从特征图的左上角开始,逐步向右和向下滑动,直到覆盖整个特征图。
  • 计算池化值:在每个位置,计算池化窗口内的最大值或平均值。
  • 存储结果:将池化值存储在下采样后的特征图的相应位置。

        上图中,设卷积之后的特征图大小为3*3,池化层大小为2*2且使用最大池化策略,则池化结果特征图的大小为2*2,计算过程如下:

  • 左上角特征值:max(0, 1, 3, 4) = 4
  • 右上角特征值:max(1, 2, 4, 5) = 5
  • 左下角特征值:max(3, 4, 6, 7) = 7
  • 右下角特征值:max(4, 5, 7, 8) = 8

3、参数选择

        不论是卷积还是池化,我们都可以通过调整以下的两个参数(非必须)来让特征提取结果符合我们的需求。

  • 填充(padding):卷积和池化过程默认不进行填充,但我们可以通过在输入高和宽的两侧填充元素(通常是0)来改变输入的高和宽,从而改变卷积或者池化输出的特征图大小,以便于我们在构造CNN网络的过程中按需求来维持每个层的输出形状,例如让输入和输出保持相同的维度。

  • 步幅(stride):卷积和池化都是在输入数据上进行滑动来提取特征,那么每次滑动的行数和列数称为步幅。默认的情况下,在高和宽上的滑动步幅都是1,我们也可以分别将它们设置成更大的值,从而进一步压缩输出大小。需要注意的是,卷积和池化只会在滑动到的位置上进行计算,这也就意味着如果我们设置的步幅较大,卷积和池化操作会跳过一些输入特征,而这些特征将被抛弃掉,不参与任何计算过程

三、python实现

        得益于深度学习库的强大,我们无需手动构建卷积层和池化层。这里,我们构建一个简单的数据集并进行CNN分类示例。SimpleDataset类生成一个包含黑色方块和白色方块的简单数据集。每个图像是28x28像素的灰度图像,黑色方块的像素值为0,白色方块的像素值为1。SimpleCNN类则定义了一个简单的卷积神经网络,包括两个卷积层、两个池化层、一个全连接层和一个输出层。

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader

# 自定义数据集
class SimpleDataset(Dataset):
    def __init__(self, transform=None):
        self.transform = transform
        self.data, self.labels = self._generate_data()

    def _generate_data(self):
        data = []
        labels = []
        for i in range(1000):
            if i % 2 == 0:
                # 黑色方块
                img = np.zeros((28, 28), dtype=np.float32)
                label = 0
            else:
                # 白色方块
                img = np.ones((28, 28), dtype=np.float32)
                label = 1
            data.append(img)
            labels.append(label)
        return np.array(data), np.array(labels)

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        img = self.data[idx]
        label = self.labels[idx]
        if self.transform:
            img = self.transform(img)
        return img, label

# 数据预处理
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

# 创建数据集和数据加载器
trainset = SimpleDataset(transform=transform)
trainloader = DataLoader(trainset, batch_size=100, shuffle=True, num_workers=2)

# 定义卷积神经网络
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=1)
        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
        self.fc1 = nn.Linear(64 * 7 * 7, 128)
        self.fc2 = nn.Linear(128, 2)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.pool(self.relu(self.conv1(x)))
        x = self.pool(self.relu(self.conv2(x)))
        x = x.view(-1, 64 * 7 * 7)
        x = self.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 定义损失函数和优化器
net = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

# 训练网络
for epoch in range(10):  # 迭代10个epoch
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data

        optimizer.zero_grad()

        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if i % 10 == 9:  # 每10个batch打印一次损失
            print(f'[Epoch {epoch + 1}, Batch {i + 1}] loss: {running_loss / 10:.3f}')
            running_loss = 0.0

print('Finished Training')

# 特征提取
def extract_features(model, dataloader):
    model.eval()
    features = []
    with torch.no_grad():
        for data in dataloader:
            inputs, _ = data
            x = model.pool(model.relu(model.conv1(inputs)))
            x = model.pool(model.relu(model.conv2(x)))
            x = x.view(-1, 64 * 7 * 7)
            features.append(x)
    return torch.cat(features, dim=0)

# 提取特征
features = extract_features(net, trainloader)
print('Extracted features shape:', features.shape)


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

相关文章:

  • Hive:日志,hql运行方式,Array,行列转换
  • CMake常用命令指南(CMakeList.txt)
  • 把markdown转换为pdf的方法
  • 深入探索 HTML5 拖拽效果 API:打造流畅交互体验
  • C# lock使用详解
  • python3+TensorFlow 2.x(二) 回归模型
  • linux实际中的常用命令
  • SQL Server约束
  • FPGA 使用 CLOCK_LOW_FANOUT 约束
  • 简易CPU设计入门:控制总线的剩余信号(二)
  • 双向链表在系统调度、游戏、文本编辑及组态方面的应用
  • 【llm对话系统】LLM 大模型Prompt 怎么写?
  • 2025多目标优化创新路径汇总
  • 快速生成2D卡通人物的AI工具:开启Live2D角色创作的新时代
  • SuperAGI - 构建、管理和运行 AI Agent
  • CAN总线数据采集与分析
  • React第二十六章(createPortal)
  • 学习率衰减策略
  • 常见字符串相关题目
  • Linux之内存管理前世今生(一)
  • 【公式】卢布贬值风险:义乌到俄罗斯贸易的汇率陷阱
  • 图漾相机搭配VisionPro使用简易教程
  • 异或哈希总结
  • 【信息系统项目管理师-选择真题】2013上半年综合知识答案和详解
  • ubuntu x64下交叉编译ffmpeg到目标架构为aarch架构的系统
  • 基于STM32的阿里云智能农业大棚